Browse Source

Draft Gazelle install guide

biotorrents 3 years ago
parent
commit
2a10a772c5
10 changed files with 1205 additions and 387 deletions
  1. 2
    2
      .gitignore
  2. 5
    16
      docs/forums.md
  3. 9
    29
      docs/index.md
  4. 476
    0
      docs/install.md
  5. 69
    94
      docs/meta.md
  6. 126
    151
      docs/torrents.md
  7. 66
    94
      docs/users.md
  8. 13
    1
      mkdocs.yml
  9. 1
    0
      readme.md
  10. 438
    0
      sphinx.conf

+ 2
- 2
.gitignore View File

@@ -1,3 +1,3 @@
1
-site/
2
-.DS_Store
3 1
 *.sw*
2
+.DS_Store
3
+site/

+ 5
- 16
docs/forums.md View File

@@ -2,14 +2,12 @@
2 2
 
3 3
 Endpoints related to the forums.
4 4
 
5
-
6 5
 ## Category view
7 6
 
8 7
 **Request**
9 8
 
10 9
 `ajax.php?action=forum`
11 10
 
12
-
13 11
 **Response**
14 12
 
15 13
 ```json
@@ -64,7 +62,6 @@ Endpoints related to the forums.
64 62
 }
65 63
 ```
66 64
 
67
-
68 65
 ## Forum view
69 66
 
70 67
 **Request**
@@ -75,7 +72,6 @@ Endpoints related to the forums.
75 72
 
76 73
 `&page=` — the page to display (default: `1`)
77 74
 
78
-
79 75
 **Response**
80 76
 
81 77
 ```json
@@ -114,8 +110,7 @@ Endpoints related to the forums.
114 110
 }
115 111
 ```
116 112
 
117
-
118
-## Thread view 
113
+## Thread view
119 114
 
120 115
 **Request**
121 116
 
@@ -129,7 +124,6 @@ Endpoints related to the forums.
129 124
 
130 125
 `&updatelastread=` — set to `1` to not update the last read id (default: `0`)
131 126
 
132
-
133 127
 **Response**
134 128
 
135 129
 ```json
@@ -203,7 +197,6 @@ Endpoints related to the forums.
203 197
 }
204 198
 ```
205 199
 
206
-
207 200
 ## Subscriptions
208 201
 
209 202
 **Request**
@@ -212,7 +205,6 @@ Endpoints related to the forums.
212 205
 
213 206
 `&showunread=` — `1` to show only unread, `0` for all subscriptions (default: `1`)
214 207
 
215
-
216 208
 **Response**
217 209
 
218 210
 ```json
@@ -243,26 +235,23 @@ Endpoints related to the forums.
243 235
 }
244 236
 ```
245 237
 
246
-
247 238
 ## Raw BBcode
248 239
 
249 240
 Fetch a post's unrendered content.
250 241
 
251
-
252 242
 **Request**
253 243
 
254 244
 `ajax.php?action=raw_bbcode`
255 245
 
256 246
 `&postid=` — post id to display (required)
257 247
 
258
-
259 248
 **Response**
260 249
 
261 250
 ```json
262 251
 {
263
-    "status": "success",
264
-    "response": {
265
-        "body": "[img]https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/1348970636l/12420783.jpg[/img]<br />\r\n<br />\r\nThe human species&#39; enjoyment of food is universal, though different cultures prefer wildly different flavors. Shepherd establishes a new companion field to molecular gastronomy called neurogastronomy. His book explains how the brain constructs and interprets multidimensional flavor profiles as the volatile compounds of food pass through the sense of retronasal smell. The science is accessible and still does justice to the complexity of the olfactory&ndash;neurological interactions described. This book will change the way you eat.<br />\r\n<br />\r\n[url=https://libgen.is/book/index.php?md5=6E9CE452E815418B1F134D5718751000]Library Genesis[/url] / [url=https://www.worldcat.org/title/neurogastronomy-how-the-brain-creates-flavor-and-why-it-matters/oclc/967255519&amp;referer=brief_results]WorldCat[/url]"
266
-    }
252
+  "status": "success",
253
+  "response": {
254
+    "body": "[img]https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/1348970636l/12420783.jpg[/img]<br />\r\n<br />\r\nThe human species&#39; enjoyment of food is universal, though different cultures prefer wildly different flavors. Shepherd establishes a new companion field to molecular gastronomy called neurogastronomy. His book explains how the brain constructs and interprets multidimensional flavor profiles as the volatile compounds of food pass through the sense of retronasal smell. The science is accessible and still does justice to the complexity of the olfactory&ndash;neurological interactions described. This book will change the way you eat.<br />\r\n<br />\r\n[url=https://libgen.is/book/index.php?md5=6E9CE452E815418B1F134D5718751000]Library Genesis[/url] / [url=https://www.worldcat.org/title/neurogastronomy-how-the-brain-creates-flavor-and-why-it-matters/oclc/967255519&amp;referer=brief_results]WorldCat[/url]"
255
+  }
267 256
 }
268 257
 ```

+ 9
- 29
docs/index.md View File

@@ -1,7 +1,6 @@
1 1
 The JSON API provides an easily parseable interface to [BioTorrents.de](https://biotorrents.de).
2 2
 Please use the navigation menu to find lists of endpoints, their arguments, and example responses.
3 3
 
4
-
5 4
 # Introduction
6 5
 
7 6
 All request URLs are in the form
@@ -26,7 +25,6 @@ All the JSON returned is in the form
26 25
 If the request is invalid, or a problem occurs, the `status` will be `failure`.
27 26
 In this case the value of `response` is `undefined`.
28 27
 
29
-
30 28
 ## Bearer token auth
31 29
 
32 30
 First, generate a token in your profile security settings and keep it safe.
@@ -39,14 +37,12 @@ curl biotorrents.de/ajax.php?action=index \
39 37
   -H "Authorization: Bearer {token}"
40 38
 ```
41 39
 
42
-
43 40
 ## Cookie auth
44 41
 
45 42
 Please send a POST request to `https://biotorrents.de/login.php` with `username` and `password`,
46 43
 or acquire a cookie from a browser session using the developer tools.
47 44
 Then store the cookie and use it to access the rest of the API.
48 45
 
49
-
50 46
 # Libraries
51 47
 
52 48
 These are the current public projects listed on the
@@ -56,23 +52,20 @@ Questions about the API can be answered in `#development` on
56 52
 
57 53
 Please get it touch if you'd like me to list your project below.
58 54
 
59
-
60
-| Language	| GitHub |
61
-| :--		| :-- |
62
-| C#		| [frankston/WhatAPI](https://github.com/frankston/WhatAPI) |
63
-| Go		| [kdvh/whatapi](https://github.com/kdvh/whatapi) |
64
-| JavaScript	| [deoxxa/whatcd](https://github.com/deoxxa/whatcd) |
65
-| Java		| [Gwindow/WhatAPI](https://github.com/Gwindow/WhatAPI) |
66
-| PHP		| [Jleagle/gazelle-api-client](https://github.com/Jleagle/gazelle-api-client) |
67
-| Python	| [isaaczafuta/whatapi](https://github.com/isaaczafuta/whatapi) |
68
-| Ruby		| [chasemgray/RubyGazelle](https://github.com/chasemgray/RubyGazelle) |
69
-
55
+| Language   | GitHub                                                                      |
56
+| :--------- | :-------------------------------------------------------------------------- |
57
+| C#         | [frankston/WhatAPI](https://github.com/frankston/WhatAPI)                   |
58
+| Go         | [kdvh/whatapi](https://github.com/kdvh/whatapi)                             |
59
+| JavaScript | [deoxxa/whatcd](https://github.com/deoxxa/whatcd)                           |
60
+| Java       | [Gwindow/WhatAPI](https://github.com/Gwindow/WhatAPI)                       |
61
+| PHP        | [Jleagle/gazelle-api-client](https://github.com/Jleagle/gazelle-api-client) |
62
+| Python     | [isaaczafuta/whatapi](https://github.com/isaaczafuta/whatapi)               |
63
+| Ruby       | [chasemgray/RubyGazelle](https://github.com/chasemgray/RubyGazelle)         |
70 64
 
71 65
 # Caveats
72 66
 
73 67
 **Abusing or using this API for malicious purposes is a bannable offense and will not be taken lightly.**
74 68
 
75
-
76 69
 ## Rate limit
77 70
 
78 71
 The API is rate-limited to one request every 6 seconds.
@@ -80,7 +73,6 @@ This limit doesn't apply to users in the Donor class.
80 73
 [Please consider donating](https://www.patreon.com/biotorrents)
81 74
 to support this scientific resource's development.
82 75
 
83
-
84 76
 ## Under construction
85 77
 
86 78
 Some endpoints aren't working correctly right now:
@@ -95,7 +87,6 @@ also contains other undocumented endpoints:
95 87
 - `news_ajax`
96 88
 - `send_recommendation`
97 89
 
98
-
99 90
 # Not implemented
100 91
 
101 92
 ## Similar artists
@@ -108,67 +99,56 @@ also contains other undocumented endpoints:
108 99
 
109 100
 `&limit=` — maximum number of results to return (fewer might be returned)
110 101
 
111
-
112 102
 **Response**
113 103
 
114 104
 ```json
115 105
 
116 106
 ```
117 107
 
118
-
119 108
 ## Better
120 109
 
121 110
 Fetch better.php (suggested torrent improvements).
122 111
 
123
-
124 112
 **Request**
125 113
 
126 114
 `ajax.php?action=better`
127 115
 
128
-
129 116
 **Response**
130 117
 
131 118
 ```json
132 119
 
133 120
 ```
134 121
 
135
-
136
-
137 122
 ## Torrent info
138 123
 
139 124
 **Request**
140 125
 
141 126
 `ajax.php?action=torrent_info`
142 127
 
143
-
144 128
 **Response**
145 129
 
146 130
 ```json
147 131
 
148 132
 ```
149 133
 
150
-
151 134
 ## Check private
152 135
 
153 136
 **Request**
154 137
 
155 138
 `ajax.php?action=checkprivate`
156 139
 
157
-
158 140
 **Response**
159 141
 
160 142
 ```json
161 143
 
162 144
 ```
163 145
 
164
-
165 146
 ## Vote favorite
166 147
 
167 148
 **Request**
168 149
 
169 150
 `ajax.php?action=votefavorite`
170 151
 
171
-
172 152
 **Response**
173 153
 
174 154
 ```json

+ 476
- 0
docs/install.md View File

@@ -0,0 +1,476 @@
1
+# Install
2
+
3
+Thanks for your interest in BioTorrents.de development!
4
+Gazelle is notoriously difficult to install and good docs are lacking.
5
+This page, based on the
6
+[original announcement protocol](https://github.com/biotorrents/announcement),
7
+is an attempt to make an evergreen install guide.
8
+It's fast paced and covers only the essentials.
9
+
10
+# Debian system profile
11
+
12
+```shell
13
+$ uname -a
14
+Linux ohm 5.10.0-6-amd64 #1 SMP Debian 5.10.28-1 (2021-04-09) x86_64 GNU/Linux
15
+
16
+$ nginx -v
17
+nginx version: nginx/1.18.0
18
+
19
+$ mysql -V
20
+mysql  Ver 15.1 Distrib 10.5.10-MariaDB, for debian-linux-gnu (x86_64) using  EditLine wrapper
21
+
22
+$ php -v
23
+PHP 7.4.21 (cli) (built: Jul  2 2021 03:59:48) ( NTS )
24
+
25
+$ memcached -h
26
+memcached 1.6.9
27
+
28
+$ indexer
29
+Sphinx 2.2.11-id64-release (95ae9a6)
30
+```
31
+
32
+# Server setup
33
+
34
+This section is done as root.
35
+If you're in a user shell, preface commands with `sudo`.
36
+
37
+## Upgrading to Debian unstable
38
+
39
+Install the most recent
40
+[Debian netinst image](https://www.debian.org/CD/netinst/)
41
+and modify `/etc/apt/sources.list`:
42
+
43
+```
44
+deb http://deb.debian.org/debian unstable main contrib non-free
45
+deb-src http://deb.debian.org/debian unstable main contrib non-free
46
+```
47
+
48
+Optionally, create `/etc/apt/apt.conf` with this content:
49
+
50
+```
51
+APT::Install-Recommends "1";
52
+APT::Install-Suggests "0";
53
+```
54
+
55
+Then upgrade the system:
56
+
57
+```shell
58
+# apt update
59
+# apt dist-upgrade
60
+# reboot
61
+```
62
+
63
+Further server setup,
64
+including TLD considerations, DNS, email, etc.,
65
+are beyond this guide's scope.
66
+For more info about SSH, Unbound, NSD, OpenSMTPd, Dovecot, Unix users, etc.,
67
+[please see the original launch announcement](https://github.com/biotorrents/announcement).
68
+
69
+## Nginx and Certbot
70
+
71
+Install Nginx and Certbot with `apt install nginx certbot python3-certbot-nginx`.
72
+
73
+The basic Gazelle Nginx config should look similar to this.
74
+Note that you'll likely have to change the file paths based on your setup.
75
+Also, PHP-FPM may need larger-than-default buffers to serve without 502 errors:
76
+
77
+```nginx
78
+server {
79
+        listen 443 ssl http2;
80
+        root /var/www/html/dev.biotorrents.de;
81
+
82
+        client_max_body_size 4M;
83
+        server_name dev.biotorrents.de;
84
+
85
+        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
86
+
87
+        ssl_certificate /etc/letsencrypt/live/biotorrents.de-0001/fullchain.pem; # managed by Certbot
88
+        ssl_certificate_key /etc/letsencrypt/live/biotorrents.de-0001/privkey.pem; # managed by Certbot
89
+
90
+        access_log off;
91
+        error_log  /var/log/nginx/dev.biotorrents.de-error.log;
92
+
93
+        location / {
94
+                index index.php;
95
+        }
96
+
97
+        # https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/
98
+        location ~ [^/]\.php(/|$) {
99
+                fastcgi_split_path_info ^(.+?\.php)(/.*)$;
100
+                if (!-f $document_root$fastcgi_script_name) {
101
+                        return 404;
102
+                }
103
+
104
+                # Mitigate https://httpoxy.org/ vulnerabilities
105
+                fastcgi_param HTTP_PROXY "";
106
+
107
+                fastcgi_pass  unix:/var/run/php/php7.4-fpm.sock;
108
+                fastcgi_index index.php;
109
+
110
+                # include the fastcgi_param setting
111
+                include /etc/nginx/params/fastcgi_params;
112
+
113
+                # https://stackoverflow.com/a/23845727
114
+                fastcgi_buffers 16 16k;
115
+                fastcgi_buffer_size 32k;
116
+        }
117
+
118
+        # https://nginx.org/en/docs/http/ngx_http_access_module.html
119
+        location ^~ /.git/ {
120
+                deny all;
121
+        }
122
+
123
+        location ^~ /classes/config.php {
124
+                deny all;
125
+        }
126
+}
127
+```
128
+
129
+The Nginx config for the Ocelot tracker should look like this.
130
+Nginx acts as a TLS reverse proxy so that Ocelot isn't directly exposed.
131
+Note the additional caveats of Ocelot's listening port (34000 is default),
132
+and setting the correct `Host` header (so tracker connections don't show up as localhost):
133
+
134
+```nginx
135
+server {
136
+        listen 443 ssl http2;
137
+        server_name tr0.biotorrents.de track.biotorrents.de;
138
+
139
+        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
140
+
141
+        ssl_certificate /etc/letsencrypt/live/biotorrents.de-0001/fullchain.pem; # managed by Certbot
142
+        ssl_certificate_key /etc/letsencrypt/live/biotorrents.de-0001/privkey.pem; # managed by Certbot
143
+
144
+        access_log off;
145
+        error_log  /var/log/nginx/tr0.biotorrents.de-error.log;
146
+
147
+        # https://nginx.org/en/docs/http/ngx_http_proxy_module.html
148
+        location / {
149
+                proxy_pass http://127.0.0.1:34000;
150
+                proxy_set_header Host $remote_addr:$proxy_port;
151
+                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
152
+                proxy_set_header X-Real-IP $remote_addr;
153
+        }
154
+}
155
+```
156
+
157
+Finally, set up TLS certificates with `certbot --nginx`.
158
+Add this entry to the root crontab to renew the certs daily:
159
+
160
+```
161
+20 1 * * * certbot renew >/dev/null 2>&1 && systemctl restart nginx >/dev/null 2>&1
162
+```
163
+
164
+Please see the
165
+[Certbot docs](https://certbot.eff.org/docs/using.html)
166
+for more info.
167
+Also see the
168
+[OWASP Secure Headers Project](https://owasp.org/www-project-secure-headers/)
169
+for info on proper Nginx security.
170
+
171
+## MariaDB
172
+
173
+Install MariaDB with `apt install mariadb-server`
174
+and initialize it with `mysql_secure_installation`.
175
+
176
+Note that BioTorrents.de uses TLS connections to a dedicated database server.
177
+Unix sockets are preferred for the database running on localhost.
178
+The config should look similar to this, paying attention to `sql-mode`:
179
+
180
+```
181
+[client-server]
182
+# Port or socket location where to connect
183
+port = 3306
184
+#socket = /var/run/mysqld/mysqld.sock
185
+
186
+# Import all .cnf files from configuration directory
187
+#!includedir /etc/mysql/conf.d/
188
+#!includedir /etc/mysql/mariadb.conf.d/
189
+
190
+[mariadb]
191
+# https://mariadb.com/kb/en/secure-connections-overview/
192
+tls-version = TLSv1.3
193
+#require-secure-transport = on
194
+
195
+# https://mariadb.com/kb/en/securing-connections-for-client-and-server/
196
+ssl-cert=/etc/mysql/ssl/server-cert.pem
197
+ssl-key=/etc/mysql/ssl/server-key.pem
198
+ssl-ca=/etc/mysql/ssl/ca.pem
199
+
200
+# https://mariadb.com/kb/en/configuring-mariadb-for-remote-client-access/
201
+skip-networking = 0
202
+bind-address = 10.0.0.3
203
+
204
+# https://johnemb.blogspot.com/2014/09/adding-or-removing-individual-sql-modes.html
205
+sql-mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
206
+```
207
+
208
+If you'd like to use TLS crypto in your database connections,
209
+[please see the MariaDB docs](https://mariadb.com/kb/en/securing-connections-for-client-and-server/).
210
+They contain the necessary info to generate self-signed certs.
211
+
212
+Finally, load the Gazelle database schema in an SQL shell.
213
+I prefer to generate secure passphrases with `pwgen -s | encrypt`.
214
+
215
+```mysql
216
+CREATE DATABASE gazelle_development;
217
+USE gazelle_development;
218
+SOURCE /var/www/html/dev.biotorrents.de/gazelle.sql;
219
+CREATE USER 'gazelle_development'@'localhost' IDENTIFIED BY '';
220
+GRANT ALL PRIVILEGES ON `gazelle_development`.* TO 'gazelle_development'@'localhost';
221
+```
222
+
223
+## PHP
224
+
225
+Install PHP and the necessary extensions.
226
+The basic PHP package:
227
+`apt install php php-dev php-fpm`.
228
+
229
+The PHP extensions.
230
+Note that there are two PHP memcached extensions.
231
+The correct one is just `php-memcache` without the "d."
232
+Your distro may require other extensions:
233
+`php-apcu php-mbstring php-memcache php-mysql`.
234
+
235
+BioTorrents.de also supports the
236
+[Seqhash algorithm](https://blog.libredna.org/post/seqhash/)
237
+and requires Blake3 hash support for this feature.
238
+Optionally, please install
239
+[php-blake3](https://github.com/cypherbits/php-blake3).
240
+
241
+Gazelle isn't picky about its PHP config needs,
242
+except that `short_open_tag = On` is still required.
243
+I strongly recommend crafting a
244
+[secure PHP config](https://cheatsheetseries.owasp.org/cheatsheets/PHP_Configuration_Cheat_Sheet.html).
245
+
246
+## memcached
247
+
248
+Install memcached with `apt install memcached`.
249
+
250
+BioTorrents.de supports separate production and development instances.
251
+If you with to run two instances, it's necessary to run two memcached sockets.
252
+Otherwise the sites will experience significant data cross-contamination.
253
+The required `/etc/memcached.conf` content:
254
+
255
+```
256
+-d
257
+-m 5120
258
+-s /var/run/memcached/memcached.sock
259
+-a 0777
260
+-t16
261
+-C
262
+-u memcache
263
+```
264
+
265
+A helper script to quickly bring up a second memcached as root:
266
+
267
+```shell
268
+#!/bin/bash
269
+memcached -d -m 5120 -s /var/run/memcached/memcached-dev.sock -a 0777 -t16 -C -u memcache
270
+```
271
+
272
+## Sphinx
273
+
274
+Install Sphinx with `apt install sphinxsearch`.
275
+
276
+The `/etc/sphinxsearch/sphinx.conf` content is too large to reasonably inline.
277
+Please find a copy at
278
+[biotorrents/documentation](https://github.com/biotorrents/documentation/blob/master/sphinx.conf).
279
+The only other Sphinx-related configs are root crontab entries:
280
+
281
+```crontab
282
+@reboot /usr/bin/searchd`.
283
+* * * * * indexer -c /etc/sphinxsearch/sphinx.conf --rotate delta requests_delta >/dev/null 2>&1
284
+7 * * * * indexer -c /etc/sphinxsearch/sphinx.conf --rotate torrents >/dev/null 2>&1
285
+7 0,12 * * * indexer -c /etc/sphinxsearch/sphinx.conf --rotate --all >/dev/null 2>&1
286
+```
287
+
288
+## Email
289
+
290
+Email setup is beyond this guide's scope.
291
+Please see
292
+[Gilles's OpenSMTPd and Dovecot guide](https://poolp.org/posts/2019-09-14/setting-up-a-mail-server-with-opensmtpd-dovecot-and-rspamd/).
293
+
294
+# Application setup
295
+
296
+This section should use a separate Unix user for each component.
297
+Gazelle, Ocelot, IRC, and sitebot should each have a distinct home folder and full shell.
298
+The applications would otherwise be an insecure jumble and hard to maintain.
299
+
300
+## Gazelle
301
+
302
+First create the necessary files and folders.
303
+Note that locations are arbitrary and may be one of:
304
+home folder, subfolder of `/var/www`, etc.
305
+
306
+```shell
307
+# nginx(8) log location
308
+mkdir -m 700 -p /var/www/log/{development,production}
309
+touch /var/www/log/production/{peerupdate.log,schedule.log}
310
+touch /var/www/log/development/{peerupdate.log,schedule.log}
311
+chown -R biotorrents:biotorrents /var/www/log
312
+
313
+# files outside the web root
314
+mkdir -m 700 -p /var/www/pictures /var/www/torrents
315
+chown -R www-data:www-data /var/www/pictures /var/www/torrents /var/www/torrents-dev
316
+```
317
+
318
+The Gazelle app user also needs this crontab.
319
+Expect to have backups in place by this stage,
320
+and note that server backups are beyond this guide's scope:
321
+
322
+```crontab
323
+0,15,30,45 * * * * curl -s "https://dev.biotorrents.de/schedule.php?key=00000000000000000000000000000000" >> /var/www/log/development/schedule.log 2>&1
324
+2-59/5 * * * * php /var/www/html/dev.biotorrents.de/peerupdate.php "00000000000000000000000000000000" >> /var/www/log/development/peerupdate.log
325
+```
326
+
327
+A useful script for resetting file permissions:
328
+
329
+```shell
330
+#!/bin/sh
331
+find . -type f -print0 | xargs -0 chmod 0644
332
+find . -type d -print0 | xargs -0 chmod 0755
333
+```
334
+
335
+### Gazelle app config
336
+
337
+[`classes/config.php`](https://github.com/biotorrents/gazelle/blob/development/classes/config.template.php)
338
+warrants its own section.
339
+When setting up Gazelle for the first time, these options must be enabled.
340
+
341
+- `'DEBUG_MODE' = false`
342
+- `'OPEN_REGISTRATION' = true`
343
+- `'FEATURE_SET_ENC_KEY_PUBLIC' = true`
344
+
345
+Note the separate production and development values and the possibility of duplicate definitions.
346
+BioTorrents.de uses a singleton class with extended recursive ArrayObject support invoked by
347
+[$ENV = ENV::go()](https://github.com/biotorrents/gazelle/blob/development/classes/env.class.php).
348
+
349
+There are some other values to set up.
350
+Please pay attention to these values that Gazelle needs for proper function:
351
+
352
+- `SITE_DOMAIN` and `IMAGE_DOMAIN`
353
+- `WEB_ROOT` and `SERVER_ROOT`
354
+- `TORRENT_STORE` and `STATIC_SERVER`
355
+- The "App keys" and "Database" sections
356
+- The "Tracker" and "Tracker URLs" sections
357
+- `MEMCACHED_SERVERS`
358
+
359
+### Composer
360
+
361
+Assuming that `php.ini` is correctly set up,
362
+you may need these modified setup instructions from the
363
+[official Composer docs](https://getcomposer.org/download/):
364
+
365
+```shell
366
+mkdir -p /var/www/bin
367
+php -d allow_url_fopen=1 -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
368
+# Hash checking, running the install script, and unlinking
369
+# See the official Composer docs for details
370
+mv composer.phar /var/www/bin/composer
371
+```
372
+
373
+Then add `/var/www/bin` to the Gazelle user's `$PATH` and run:
374
+`php composer.phar update`.
375
+
376
+### SCSS and fonts
377
+
378
+Install SassC with `apt install sassc`.
379
+
380
+[Download the font pack](https://docs.biotorrents.de/fonts.tgz)
381
+and extract it with:
382
+`tar zxvf fonts.tgz -C /var/www/html/dev.biotorrents.de/static/styles/assets/fonts`.
383
+
384
+Then install SassC with `apt install sassc`.
385
+This should be a for loop, to compile the CSS:
386
+
387
+```shell
388
+#!/bin/bash
389
+styles="/var/www/html/dev.biotorrents.de/static/styles"
390
+sassc "$styles/beluga/beluga.scss" > "$styles/beluga.css"
391
+sassc "$styles/bookish/bookish.scss" > "$styles/bookish.css"
392
+sassc "$styles/development/development.scss" > "$styles/development.css"
393
+sassc "$styles/genaviv/genaviv.scss" > "$styles/genaviv.css"
394
+sassc "$styles/global/global.scss" > "$styles/global.css"
395
+sassc "$styles/matcha/matcha.scss" > "$styles/matcha.css"
396
+sassc "$styles/oppai/oppai.scss" > "$styles/oppai.css"
397
+sassc "$styles/postmod/postmod.scss" > "$styles/postmod.css"
398
+sassc "$styles/public/public.scss" > "$styles/public.css"
399
+```
400
+
401
+## Ocelot
402
+
403
+BioTorrents.de uses What.CD's Ocelot with the
404
+[10th anniversary mixtape patches](https://twitter.com/whatcd/status/923942203080273921)
405
+and developing TLS support.
406
+The patched version is available at
407
+[biotorrents/ocelot](/biotorrents/ocelot).
408
+
409
+Then installed the dependencies like below.
410
+Note that specific dependencies may differ on your system.
411
+
412
+```shell
413
+apt install \
414
+	automake \
415
+	g++ \
416
+	gcc \
417
+	libboost-dev \
418
+	libboost-iostreams-dev \
419
+	libboost-system-dev \
420
+	libev-dev \
421
+	libmysql++-dev \
422
+	libtcmalloc-minimal4 \
423
+	make
424
+```
425
+
426
+The compilation ritual is likewise fraught with pitfalls.
427
+I found `autoreconf` with manual library locations to work best:
428
+
429
+```shell
430
+autoreconf
431
+./configure \
432
+	--with-boost-libdir=/usr/lib/x86_64-linux-gnu \
433
+	--with-ev-lib=/usr/lib/x86_64-linux-gnu \
434
+	--with-mysql-lib=/usr/lib/x86_64-linux-gnu \
435
+	--with-mysqlpp-lib=/usr/lib/x86_64-linux-gnu
436
+make
437
+make install
438
+```
439
+
440
+Copy `ocelot/ocelot.conf.dist`.
441
+The daemon runs on `localhost:34000` and Nginx TLS reverse proxies it to `localhost:443`.
442
+`ocelot.conf` lives in the Ocelot user's home folder and the daemon runs in a tmux window there.
443
+
444
+## IRC and kana (sitebot)
445
+
446
+Docs pending the completion of sitebot API integration.
447
+
448
+## Inside the Gazelle admin panel
449
+
450
+At this point it should be possible to register for the site.
451
+The first account is the sysop so please act quickly here.
452
+Disable `DEBUG_MODE` and `FEATURE_SET_ENC_KEY_PUBLIC` as soon as you register!
453
+Do `apt install qrencode` for 2FA support and enable it with a GPG key on the sysop account.
454
+
455
+Configure a client whitelist on the Toolbox page by the
456
+[BitTorrent spec's peer ID list](https://wiki.theory.org/index.php/BitTorrentSpecification#peer_id).
457
+Please find a list of quality client peer IDs below.
458
+Note that LibTorrent 0.1x.y also covers rTorrent/ruTorrent and other clients that use
459
+[rakshasa's library](https://github.com/rakshasa/libtorrent):
460
+
461
+| Client Name       | Peer ID |
462
+| :---------------- | :-----: |
463
+| Deluge 1.x.y      | `-DE1`  |
464
+| Deluge 2.x.y      | `-DE2`  |
465
+| KTorrent 3.x.y    | `-KT3`  |
466
+| KTorrent 4.x.y    | `-KT4`  |
467
+| KTorrent 5.x.y    | `-KT5`  |
468
+| LibTorrent 0.x.y  | `-lt0`  |
469
+| qBittorrent 2.x.y | `-qB2`  |
470
+| qBittorrent 3.x.y | `-qB3`  |
471
+| qBittorrent 4.x.y | `-qB4`  |
472
+| Transmission 2.xy | `-TR2`  |
473
+
474
+Most of the Toolbox pages don't write to the database and all of them should work.
475
+For more BitTorrents info see
476
+[Calomel's rTorrent hacking guide](https://calomel.org/rtorrent_mods.html).

+ 69
- 94
docs/meta.md View File

@@ -2,115 +2,105 @@
2 2
 
3 3
 Endpoints related to [BioTorrents.de](https://biotorrents.de) itself.
4 4
 
5
-
6 5
 ## Index
7 6
 
8 7
 Fetch basic site info from the homepage,
9 8
 e.g., your ratio and any unread notices.
10 9
 
11
-
12 10
 **Request**
13 11
 
14 12
 `ajax.php?action=index`
15 13
 
16
-
17 14
 **Response**
18 15
 
19 16
 ```json
20 17
 {
21
-    "status": "success",
22
-    "response": {
23
-        "username": "me",
24
-        "id": 2,
25
-        "authkey": "00000000000000000000000000000000",
26
-        "passkey": "00000000000000000000000000000000",
27
-        "notifications": {
28
-            "messages": 0,
29
-            "notifications": 0,
30
-            "newAnnouncement": false,
31
-            "newBlog": false,
32
-            "newSubscriptions": false
33
-        },
34
-        "userstats": {
35
-            "uploaded": 15918336971,
36
-            "downloaded": 2341094384,
37
-            "ratio": 6.79,
38
-            "requiredratio": 0,
39
-            "class": "Member"
40
-        }
18
+  "status": "success",
19
+  "response": {
20
+    "username": "me",
21
+    "id": 2,
22
+    "authkey": "00000000000000000000000000000000",
23
+    "passkey": "00000000000000000000000000000000",
24
+    "notifications": {
25
+      "messages": 0,
26
+      "notifications": 0,
27
+      "newAnnouncement": false,
28
+      "newBlog": false,
29
+      "newSubscriptions": false
30
+    },
31
+    "userstats": {
32
+      "uploaded": 15918336971,
33
+      "downloaded": 2341094384,
34
+      "ratio": 6.79,
35
+      "requiredratio": 0,
36
+      "class": "Member"
41 37
     }
38
+  }
42 39
 }
43 40
 ```
44 41
 
45
-
46 42
 ## Stats
47 43
 
48 44
 Fetch the homepage sidebar info.
49 45
 
50
-
51 46
 **Request**
52 47
 
53 48
 `ajax.php?action=stats`
54 49
 
55
-
56 50
 **Response**
57 51
 
58 52
 ```json
59 53
 {
60
-    "status": "success",
61
-    "response": {
62
-        "maxUsers": 0,
63
-        "enabledUsers": 82,
64
-        "usersActiveThisDay": 5,
65
-        "usersActiveThisWeek": 10,
66
-        "usersActiveThisMonth": 19,
67
-        "torrentCount": 60,
68
-        "groupCount": 12,
69
-        "artistCount": 151,
70
-        "requestCount": 3,
71
-        "filledRequestCount": 0,
72
-        "seederCount": 225,
73
-        "leecherCount": 0
74
-    }
54
+  "status": "success",
55
+  "response": {
56
+    "maxUsers": 0,
57
+    "enabledUsers": 82,
58
+    "usersActiveThisDay": 5,
59
+    "usersActiveThisWeek": 10,
60
+    "usersActiveThisMonth": 19,
61
+    "torrentCount": 60,
62
+    "groupCount": 12,
63
+    "artistCount": 151,
64
+    "requestCount": 3,
65
+    "filledRequestCount": 0,
66
+    "seederCount": 225,
67
+    "leecherCount": 0
68
+  }
75 69
 }
76 70
 ```
77 71
 
78
-
79 72
 ## Manifest
80 73
 
81 74
 Fetch an app manifest.
82 75
 
83
-
84 76
 **Request**
85 77
 
86 78
 `ajax.php?action=manifest`
87 79
 
88
-
89 80
 **Response**
90 81
 
91 82
 ```json
92 83
 {
93
-    "status": "success",
94
-    "response": {
95
-        "name": "BioTorrents.de",
96
-        "short_name": "BioTorrents.de",
97
-        "description": "A platform to share biological sequence and medical imaging data",
98
-        "start_url": "index.php",
99
-        "display": "standalone",
100
-        "background_color": "#ffffff",
101
-        "theme_color": "#0288d1",
102
-        "icons": [
103
-            {
104
-                "src": "/static/common/icon.png",
105
-                "sizes": "120x120",
106
-                "type": "image/png"
107
-            }
108
-        ]
109
-    }
84
+  "status": "success",
85
+  "response": {
86
+    "name": "BioTorrents.de",
87
+    "short_name": "BioTorrents.de",
88
+    "description": "A platform to share biological sequence and medical imaging data",
89
+    "start_url": "index.php",
90
+    "display": "standalone",
91
+    "background_color": "#ffffff",
92
+    "theme_color": "#0288d1",
93
+    "icons": [
94
+      {
95
+        "src": "/static/common/icon.png",
96
+        "sizes": "120x120",
97
+        "type": "image/png"
98
+      }
99
+    ]
100
+  }
110 101
 }
111 102
 ```
112 103
 
113
-
114 104
 ## Load average
115 105
 
116 106
 Requires moderator permissions to access without error.
@@ -119,38 +109,29 @@ Requires moderator permissions to access without error.
119 109
 
120 110
 `ajax.php?action=loadavg`
121 111
 
122
-
123 112
 **Response**
124 113
 
125 114
 ```json
126 115
 {
127
-    "status": "success",
128
-    "response": {
129
-        "loadAverage": [
130
-            0.11,
131
-            0.06,
132
-            0.02
133
-        ]
134
-    }
116
+  "status": "success",
117
+  "response": {
118
+    "loadAverage": [0.11, 0.06, 0.02]
119
+  }
135 120
 }
136 121
 ```
137 122
 
138
-
139 123
 **Error**
140 124
 
141 125
 `Invalid authorization key. Go back, refresh, and try again.`
142 126
 
143
-
144
-## Announcements 
127
+## Announcements
145 128
 
146 129
 Fetch the recent news and blogs.
147 130
 
148
-
149 131
 **Request**
150 132
 
151 133
 `ajax.php?action=announcements`
152 134
 
153
-
154 135
 **Response**
155 136
 
156 137
 ```json
@@ -194,12 +175,10 @@ Fetch the recent news and blogs.
194 175
 }
195 176
 ```
196 177
 
197
-
198 178
 ## Wiki
199 179
 
200 180
 Either `id` or `name` is required.
201 181
 
202
-
203 182
 **Request**
204 183
 
205 184
 `ajax.php?action=wiki`
@@ -208,36 +187,32 @@ Either `id` or `name` is required.
208 187
 
209 188
 `&name=` — page alias to display
210 189
 
211
-
212 190
 **Response**
213 191
 
214 192
 ```json
215 193
 {
216
-    "status": "success",
217
-    "response": {
218
-        "title": "User Classes",
219
-        "bbBody": "BBcode",
220
-        "body": "HTML",
221
-        "aliases": "userclasses",
222
-        "authorID": 1,
223
-        "authorName": "ohm",
224
-        "date": "2020-11-13 18:46:06",
225
-        "revision": 10
226
-    }
194
+  "status": "success",
195
+  "response": {
196
+    "title": "User Classes",
197
+    "bbBody": "BBcode",
198
+    "body": "HTML",
199
+    "aliases": "userclasses",
200
+    "authorID": 1,
201
+    "authorName": "ohm",
202
+    "date": "2020-11-13 18:46:06",
203
+    "revision": 10
204
+  }
227 205
 }
228 206
 ```
229 207
 
230
-
231 208
 ## Ontology
232 209
 
233 210
 Fetch a site metadata blueprint.
234 211
 
235
-
236 212
 **Request**
237 213
 
238 214
 `ajax.php?action=ontology`
239 215
 
240
-
241 216
 **Response**
242 217
 
243 218
 ```json
@@ -274,7 +249,7 @@ Fetch a site metadata blueprint.
274 249
                     },
275 250
                     "APML": {
276 251
                         "0": "apml"
277
-                    },		    
252
+                    },
278 253
                     # etc.
279 254
                 },
280 255
 		# etc.

+ 126
- 151
docs/torrents.md View File

@@ -2,7 +2,6 @@
2 2
 
3 3
 Endpoints related to torrents.
4 4
 
5
-
6 5
 ## Torrent
7 6
 
8 7
 **Request**
@@ -13,72 +12,70 @@ Endpoints related to torrents.
13 12
 
14 13
 `&hash=` — torrent's hash (must be uppercase)
15 14
 
16
-
17 15
 **Response**
18 16
 
19 17
 ```json
20 18
 {
21
-    "status": "success",
22
-    "response": {
23
-        "group": {
24
-            "description": "HTML",
25
-            "picture": "https://i.imgur.com/sF40cxi.png",
26
-            "id": 1,
27
-            "name": "Alcohol dehydrogenase ADH1",
28
-            "organism": "Saccharomyces cerevisiae",
29
-            "strain": "S288C",
30
-            "authors": [
31
-                {
32
-                    "id": 2,
33
-                    "name": "David Schild"
34
-                },
35
-                {
36
-                    "id": 1,
37
-                    "name": "Robert K. Mortimer"
38
-                }
39
-            ],
40
-            "year": 1985,
41
-            "accession": "YOL086C",
42
-            "categoryId": 1,
43
-            "categoryName": "Sequences",
44
-            "time": "2019-12-10 01:48:07",
45
-            "isBookmarked": false,
46
-            "tags": [
47
-                "coding",
48
-                "fungi",
49
-                "one.shot",
50
-                "organic.chemistry",
51
-                "protocol.available"
52
-            ]
19
+  "status": "success",
20
+  "response": {
21
+    "group": {
22
+      "description": "HTML",
23
+      "picture": "https://i.imgur.com/sF40cxi.png",
24
+      "id": 1,
25
+      "name": "Alcohol dehydrogenase ADH1",
26
+      "organism": "Saccharomyces cerevisiae",
27
+      "strain": "S288C",
28
+      "authors": [
29
+        {
30
+          "id": 2,
31
+          "name": "David Schild"
53 32
         },
54
-        "torrent": {
55
-            "id": 1,
56
-            "infoHash": "6A5413B9A0C5EF5B68BED6ABBB8112CBE3870647",
57
-            "platform": "Sanger",
58
-            "format": "FASTA",
59
-            "license": "Public Domain",
60
-            "scope": "Contig",
61
-            "annotated": false,
62
-            "archive": "None",
63
-            "fileCount": 4,
64
-            "size": 5754,
65
-            "seeders": 5,
66
-            "leechers": 0,
67
-            "snatched": 3,
68
-            "freeTorrent": false,
69
-            "reported": false,
70
-            "time": "2019-12-10 01:48:08",
71
-            "description": "HTML",
72
-            "fileList": "S288C_YOL086C_ADH1_coding.fsa{{{1095}}}|||S288C_YOL086C_ADH1_flanking.fsa{{{3157}}}|||S288C_YOL086C_ADH1_genomic.fsa{{{1117}}}|||S288C_YOL086C_ADH1_protein.fsa{{{385}}}",
73
-            "filePath": "ADH1 - YOL086C",
74
-            "userId": 0,
75
-            "username": "Anonymous"
33
+        {
34
+          "id": 1,
35
+          "name": "Robert K. Mortimer"
76 36
         }
37
+      ],
38
+      "year": 1985,
39
+      "accession": "YOL086C",
40
+      "categoryId": 1,
41
+      "categoryName": "Sequences",
42
+      "time": "2019-12-10 01:48:07",
43
+      "isBookmarked": false,
44
+      "tags": [
45
+        "coding",
46
+        "fungi",
47
+        "one.shot",
48
+        "organic.chemistry",
49
+        "protocol.available"
50
+      ]
51
+    },
52
+    "torrent": {
53
+      "id": 1,
54
+      "infoHash": "6A5413B9A0C5EF5B68BED6ABBB8112CBE3870647",
55
+      "platform": "Sanger",
56
+      "format": "FASTA",
57
+      "license": "Public Domain",
58
+      "scope": "Contig",
59
+      "annotated": false,
60
+      "archive": "None",
61
+      "fileCount": 4,
62
+      "size": 5754,
63
+      "seeders": 5,
64
+      "leechers": 0,
65
+      "snatched": 3,
66
+      "freeTorrent": false,
67
+      "reported": false,
68
+      "time": "2019-12-10 01:48:08",
69
+      "description": "HTML",
70
+      "fileList": "S288C_YOL086C_ADH1_coding.fsa{{{1095}}}|||S288C_YOL086C_ADH1_flanking.fsa{{{3157}}}|||S288C_YOL086C_ADH1_genomic.fsa{{{1117}}}|||S288C_YOL086C_ADH1_protein.fsa{{{385}}}",
71
+      "filePath": "ADH1 - YOL086C",
72
+      "userId": 0,
73
+      "username": "Anonymous"
77 74
     }
75
+  }
78 76
 }
79 77
 ```
80 78
 
81
-
82 79
 ## Torrent group
83 80
 
84 81
 **Request**
@@ -89,7 +86,6 @@ Endpoints related to torrents.
89 86
 
90 87
 `&hash=` — hash of a torrent in the torrent group (must be uppercase)
91 88
 
92
-
93 89
 **Response**
94 90
 
95 91
 ```json
@@ -160,14 +156,12 @@ Endpoints related to torrents.
160 156
 }
161 157
 ```
162 158
 
163
-
164 159
 ## Browse (search)
165 160
 
166 161
 Note that [BioTorrents.de](https://biotorrents.de) still uses Oppaitime metadata behind the scenes.
167 162
 These docs are also adapted from What.CD, an older and different distribution.
168 163
 The advanced search options are certain to change in the future.
169 164
 
170
-
171 165
 **Request**
172 166
 
173 167
 `ajax.php?action=browse`
@@ -178,7 +172,6 @@ The advanced search options are certain to change in the future.
178 172
 
179 173
 `taglist`, `tags_type`, `order_by`, `order_way`, `filter_cat`, `freetorrent`, `vanityhouse`, `scene`, `haslog`, `releasetype`, `media`, `format`, `encoding`, `artistname`, `filelist`, `groupname`, `recordlabel`, `cataloguenumber`, `year`, `remastertitle`, `remasteryear`, `remasterrecordlabel`, `remastercataloguenumber` — as in advanced search
180 174
 
181
-
182 175
 **Response**
183 176
 
184 177
 ```json
@@ -252,19 +245,16 @@ The advanced search options are certain to change in the future.
252 245
 }
253 246
 ```
254 247
 
255
-
256
-## Comments 
248
+## Comments
257 249
 
258 250
 Fetch comments from torrent pages.
259 251
 
260
-
261 252
 **Request**
262 253
 
263 254
 `ajax.php?action=tcomments`
264 255
 
265 256
 `&id=` — torrent's id (required)
266 257
 
267
-
268 258
 **Response**
269 259
 
270 260
 ```json
@@ -299,7 +289,6 @@ Fetch comments from torrent pages.
299 289
 }
300 290
 ```
301 291
 
302
-
303 292
 # Torrent features
304 293
 
305 294
 Various features around the torrents themselves.
@@ -312,7 +301,6 @@ Various features around the torrents themselves.
312 301
 
313 302
 `&id=` — collage's id (required)
314 303
 
315
-
316 304
 **Response**
317 305
 
318 306
 ```json
@@ -373,14 +361,12 @@ Various features around the torrents themselves.
373 361
 }
374 362
 ```
375 363
 
376
-
377
-## Artist 
364
+## Artist
378 365
 
379 366
 Under construction as of 2020-11-24.
380 367
 Currently not returning the artist's torrent groups.
381 368
 Please see the response below for details.
382 369
 
383
-
384 370
 **Request**
385 371
 
386 372
 `ajax.php?action=artist`
@@ -391,35 +377,33 @@ Please see the response below for details.
391 377
 
392 378
 `&artistreleases=` — if set, only include groups where the artist is the main artist
393 379
 
394
-
395 380
 **Response**
396 381
 
397 382
 ```json
398 383
 {
399
-    "status": "success",
400
-    "response": {
401
-        "id": 94,
402
-        "name": "Jackie Treehorn",
403
-        "notificationsEnabled": false,
404
-        "hasBookmarked": false,
405
-        "image": "",
406
-        "body": "",
407
-        "vanityHouse": false,
408
-        "tags": [],
409
-        "statistics": {
410
-            "numGroups": 0,
411
-            "numTorrents": 0,
412
-            "numSeeders": 0,
413
-            "numLeechers": 0,
414
-            "numSnatches": 0
415
-        },
416
-        "torrentgroup": [],
417
-        "requests": []
418
-    }
384
+  "status": "success",
385
+  "response": {
386
+    "id": 94,
387
+    "name": "Jackie Treehorn",
388
+    "notificationsEnabled": false,
389
+    "hasBookmarked": false,
390
+    "image": "",
391
+    "body": "",
392
+    "vanityHouse": false,
393
+    "tags": [],
394
+    "statistics": {
395
+      "numGroups": 0,
396
+      "numTorrents": 0,
397
+      "numSeeders": 0,
398
+      "numLeechers": 0,
399
+      "numSnatches": 0
400
+    },
401
+    "torrentgroup": [],
402
+    "requests": []
403
+  }
419 404
 }
420 405
 ```
421 406
 
422
-
423 407
 ## Request
424 408
 
425 409
 **Request**
@@ -430,70 +414,67 @@ Please see the response below for details.
430 414
 
431 415
 `&page=` — page of the comments to display (default: last page)
432 416
 
433
-
434 417
 **Response**
435 418
 
436 419
 ```json
437 420
 {
438
-    "status": "success",
439
-    "response": {
440
-        "requestId": 2,
441
-        "requestorId": 2,
442
-        "requestorName": "me",
443
-        "isBookmarked": false,
444
-        "requestTax": 0.1,
445
-        "timeAdded": "2020-04-23 02:02:37",
446
-        "canEdit": true,
447
-        "canVote": true,
448
-        "minimumVote": 20971520,
449
-        "voteCount": 1,
450
-        "lastVote": "2020-11-15 06:51:56",
451
-        "topContributors": [
452
-            {
453
-                "userId": 2,
454
-                "userName": "me",
455
-                "bounty": 15461882266
456
-            }
457
-        ],
458
-        "totalBounty": 15461882266,
459
-        "categoryId": 10,
460
-        "categoryName": "Models",
461
-        "title": "Markov State Model Database of Protein Folding Datasets",
462
-        "year": 0,
463
-        "image": "",
464
-        "bbDescription": "BBcode",
465
-        "description": "HTML",
466
-        "artists": [
467
-            {
468
-                "id": 88,
469
-                "name": "Thomas Lane"
470
-            }
471
-        ],
472
-        "isFilled": false,
473
-        "fillerId": 0,
474
-        "fillerName": "",
475
-        "torrentId": 0,
476
-        "timeFilled": "",
477
-        "tags": [
478
-            "coding",
479
-            "proteomics",
480
-            "biochemistry",
481
-            "data.science",
482
-            "gene.expression"
483
-        ],
484
-        "comments": [],
485
-        "commentPage": 1,
486
-        "commentPages": 0
487
-    }
421
+  "status": "success",
422
+  "response": {
423
+    "requestId": 2,
424
+    "requestorId": 2,
425
+    "requestorName": "me",
426
+    "isBookmarked": false,
427
+    "requestTax": 0.1,
428
+    "timeAdded": "2020-04-23 02:02:37",
429
+    "canEdit": true,
430
+    "canVote": true,
431
+    "minimumVote": 20971520,
432
+    "voteCount": 1,
433
+    "lastVote": "2020-11-15 06:51:56",
434
+    "topContributors": [
435
+      {
436
+        "userId": 2,
437
+        "userName": "me",
438
+        "bounty": 15461882266
439
+      }
440
+    ],
441
+    "totalBounty": 15461882266,
442
+    "categoryId": 10,
443
+    "categoryName": "Models",
444
+    "title": "Markov State Model Database of Protein Folding Datasets",
445
+    "year": 0,
446
+    "image": "",
447
+    "bbDescription": "BBcode",
448
+    "description": "HTML",
449
+    "artists": [
450
+      {
451
+        "id": 88,
452
+        "name": "Thomas Lane"
453
+      }
454
+    ],
455
+    "isFilled": false,
456
+    "fillerId": 0,
457
+    "fillerName": "",
458
+    "torrentId": 0,
459
+    "timeFilled": "",
460
+    "tags": [
461
+      "coding",
462
+      "proteomics",
463
+      "biochemistry",
464
+      "data.science",
465
+      "gene.expression"
466
+    ],
467
+    "comments": [],
468
+    "commentPage": 1,
469
+    "commentPages": 0
470
+  }
488 471
 }
489 472
 ```
490 473
 
491
-
492 474
 ## Request search
493 475
 
494 476
 If no arguments are specified then the most recent requests are shown.
495 477
 
496
-
497 478
 **Request**
498 479
 
499 480
 `ajax.php?action=requests`
@@ -510,7 +491,6 @@ If no arguments are specified then the most recent requests are shown.
510 491
 
511 492
 `filter_cat[]`, `releases[]`, `bitrates[]`, `formats[]`, `media[]` — as used on requests.php
512 493
 
513
-
514 494
 **Response**
515 495
 
516 496
 ```json
@@ -557,12 +537,10 @@ If no arguments are specified then the most recent requests are shown.
557 537
 }
558 538
 ```
559 539
 
560
-
561 540
 ## Top 10
562 541
 
563 542
 Fetch the Top 10 torrents, tags, or users.
564 543
 
565
-
566 544
 ### Torrents
567 545
 
568 546
 **Request**
@@ -573,7 +551,6 @@ Fetch the Top 10 torrents, tags, or users.
573 551
 
574 552
 `&type=` — one of: torrents, tags, users (default: `torrents`)
575 553
 
576
-
577 554
 **Response**
578 555
 
579 556
 ```json
@@ -709,7 +686,6 @@ Fetch the Top 10 torrents, tags, or users.
709 686
 }
710 687
 ```
711 688
 
712
-
713 689
 ### Tags
714 690
 
715 691
 ```json
@@ -760,7 +736,6 @@ Fetch the Top 10 torrents, tags, or users.
760 736
 }
761 737
 ```
762 738
 
763
-
764 739
 ### Users
765 740
 
766 741
 Usernames are masked to `null` in the output unless you have moderator permissions.

+ 66
- 94
docs/users.md View File

@@ -2,82 +2,78 @@
2 2
 
3 3
 Endpoints related to user accounts.
4 4
 
5
-
6 5
 ## User
7 6
 
8 7
 If you're viewing your own account, `personal->passkey` will be shown.
9 8
 
10
-
11 9
 **Request**
12 10
 
13 11
 `ajax.php?action=user`
14 12
 
15 13
 `&id=` — id of the user to display (required)
16 14
 
17
-
18 15
 **Response**
19 16
 
20 17
 ```json
21 18
 {
22
-    "status": "success",
23
-    "response": {
24
-        "username": "eva",
25
-        "avatar": "https://ptpimg.me/1x1h48.png",
26
-        "isFriend": false,
27
-        "profileText": "",
28
-        "stats": {
29
-            "joinedDate": "2020-03-08 14:27:59",
30
-            "lastAccess": "2020-11-24 15:25:17",
31
-            "uploaded": 2192870833,
32
-            "downloaded": 1244283888,
33
-            "ratio": 1.76235,
34
-            "requiredRatio": 0
35
-        },
36
-        "ranks": {
37
-            "uploaded": 0,
38
-            "downloaded": 2,
39
-            "uploads": 0,
40
-            "requests": 0,
41
-            "bounty": 0,
42
-            "posts": 2,
43
-            "artists": 0,
44
-            "overall": 0
45
-        },
46
-        "personal": {
47
-            "class": "Donor",
48
-            "paranoia": 0,
49
-            "paranoiaText": "Off",
50
-            "donor": false,
51
-            "warned": false,
52
-            "enabled": true,
53
-            "passkey": ""
54
-        },
55
-        "community": {
56
-            "posts": 4,
57
-            "torrentComments": 0,
58
-            "artistComments": 0,
59
-            "collageComments": 0,
60
-            "requestComments": 0,
61
-            "collagesStarted": 1,
62
-            "collagesContrib": 1,
63
-            "requestsFilled": 0,
64
-            "bountyEarned": 0,
65
-            "requestsVoted": 0,
66
-            "bountySpent": 0,
67
-            "uploaded": 0,
68
-            "groups": 0,
69
-            "seeding": 0,
70
-            "leeching": 0,
71
-            "snatched": 7,
72
-            "invited": 0,
73
-            "artistsAdded": 0
74
-        }
19
+  "status": "success",
20
+  "response": {
21
+    "username": "eva",
22
+    "avatar": "https://ptpimg.me/1x1h48.png",
23
+    "isFriend": false,
24
+    "profileText": "",
25
+    "stats": {
26
+      "joinedDate": "2020-03-08 14:27:59",
27
+      "lastAccess": "2020-11-24 15:25:17",
28
+      "uploaded": 2192870833,
29
+      "downloaded": 1244283888,
30
+      "ratio": 1.76235,
31
+      "requiredRatio": 0
32
+    },
33
+    "ranks": {
34
+      "uploaded": 0,
35
+      "downloaded": 2,
36
+      "uploads": 0,
37
+      "requests": 0,
38
+      "bounty": 0,
39
+      "posts": 2,
40
+      "artists": 0,
41
+      "overall": 0
42
+    },
43
+    "personal": {
44
+      "class": "Donor",
45
+      "paranoia": 0,
46
+      "paranoiaText": "Off",
47
+      "donor": false,
48
+      "warned": false,
49
+      "enabled": true,
50
+      "passkey": ""
51
+    },
52
+    "community": {
53
+      "posts": 4,
54
+      "torrentComments": 0,
55
+      "artistComments": 0,
56
+      "collageComments": 0,
57
+      "requestComments": 0,
58
+      "collagesStarted": 1,
59
+      "collagesContrib": 1,
60
+      "requestsFilled": 0,
61
+      "bountyEarned": 0,
62
+      "requestsVoted": 0,
63
+      "bountySpent": 0,
64
+      "uploaded": 0,
65
+      "groups": 0,
66
+      "seeding": 0,
67
+      "leeching": 0,
68
+      "snatched": 7,
69
+      "invited": 0,
70
+      "artistsAdded": 0
75 71
     }
72
+  }
76 73
 }
77 74
 ```
78 75
 
79
-
80
-## User search 
76
+## User search
81 77
 
82 78
 **Request**
83 79
 
@@ -87,7 +83,6 @@ If you're viewing your own account, `personal->passkey` will be shown.
87 83
 
88 84
 `&page=` — page to display (default: `1`)
89 85
 
90
-
91 86
 **Response**
92 87
 
93 88
 ```json
@@ -122,8 +117,7 @@ If you're viewing your own account, `personal->passkey` will be shown.
122 117
 }
123 118
 ```
124 119
 
125
-
126
-## Community stats 
120
+## Community stats
127 121
 
128 122
 **Request**
129 123
 
@@ -131,31 +125,28 @@ If you're viewing your own account, `personal->passkey` will be shown.
131 125
 
132 126
 `&userid=` — id of the user to display (required)
133 127
 
134
-
135 128
 **Response**
136 129
 
137 130
 ```json
138 131
 {
139
-    "status": "success",
140
-    "response": {
141
-        "leeching": 0,
142
-        "seeding": "60",
143
-        "snatched": "3",
144
-        "usnatched": false,
145
-        "downloaded": false,
146
-        "udownloaded": false,
147
-        "seedingperc": 100
148
-    }
132
+  "status": "success",
133
+  "response": {
134
+    "leeching": 0,
135
+    "seeding": "60",
136
+    "snatched": "3",
137
+    "usnatched": false,
138
+    "downloaded": false,
139
+    "udownloaded": false,
140
+    "seedingperc": 100
141
+  }
149 142
 }
150 143
 ```
151 144
 
152
-
153 145
 ## Recents (torrents)
154 146
 
155 147
 This endpoint circumvents the "upload anonymously" feature.
156 148
 Various features of the response will likely change in the future.
157 149
 
158
-
159 150
 **Request**
160 151
 
161 152
 `ajax.php?action=user_recents`
@@ -164,7 +155,6 @@ Various features of the response will likely change in the future.
164 155
 
165 156
 `&limit=` — how many recent torrents to fetch
166 157
 
167
-
168 158
 **Response**
169 159
 
170 160
 ```json
@@ -220,7 +210,6 @@ Various features of the response will likely change in the future.
220 210
 }
221 211
 ```
222 212
 
223
-
224 213
 ## History (community)
225 214
 
226 215
 **Request**
@@ -229,7 +218,6 @@ Various features of the response will likely change in the future.
229 218
 
230 219
 `&userid=` — id of user (required)
231 220
 
232
-
233 221
 **Response**
234 222
 
235 223
 ```json
@@ -270,17 +258,14 @@ Various features of the response will likely change in the future.
270 258
 }
271 259
 ```
272 260
 
273
-
274 261
 # Your account
275 262
 
276 263
 Endpoints that only fetch info about your own account.
277 264
 
278
-
279 265
 ## Inbox
280 266
 
281 267
 The current example isn't from the [BioTorrents.de](https://biotorrents.de) database.
282 268
 
283
-
284 269
 **Request**
285 270
 
286 271
 `ajax.php?action=inbox`
@@ -295,7 +280,6 @@ The current example isn't from the [BioTorrents.de](https://biotorrents.de) data
295 280
 
296 281
 `&type=` — one of: inbox or sentbox (default: `inbox`)
297 282
 
298
-
299 283
 **Response**
300 284
 
301 285
 ```json
@@ -325,19 +309,16 @@ The current example isn't from the [BioTorrents.de](https://biotorrents.de) data
325 309
 }
326 310
 ```
327 311
 
328
-
329
-## Conversation 
312
+## Conversation
330 313
 
331 314
 The current example isn't from the [BioTorrents.de](https://biotorrents.de) database.
332 315
 
333
-
334 316
 **Request**
335 317
 
336 318
 `ajax.php?action=inbox&type=viewconv`
337 319
 
338 320
 `&id=` — id of the message to display (required)
339 321
 
340
-
341 322
 **Response**
342 323
 
343 324
 ```json
@@ -366,7 +347,6 @@ The current example isn't from the [BioTorrents.de](https://biotorrents.de) data
366 347
 
367 348
 Fetch bookmarked torrents or artists.
368 349
 
369
-
370 350
 ### Torrents
371 351
 
372 352
 **Request**
@@ -375,7 +355,6 @@ Fetch bookmarked torrents or artists.
375 355
 
376 356
 `&type=` — one of torrents, artists (default: `torrents`)
377 357
 
378
-
379 358
 **Response**
380 359
 
381 360
 ```json
@@ -439,33 +418,28 @@ Fetch bookmarked torrents or artists.
439 418
 }
440 419
 ```
441 420
 
442
-
443 421
 ## Notifications
444 422
 
445 423
 Fetch new upload filter notifications.
446 424
 
447
-
448 425
 **Request**
449 426
 
450 427
 `ajax.php?action=notifications`
451 428
 
452 429
 `&page=` — page number to display (default: `1`)
453 430
 
454
-
455 431
 **Response**
456 432
 
457 433
 ```json
458 434
 
459 435
 ```
460 436
 
461
-
462 437
 ### Get user notifications
463 438
 
464 439
 **Request**
465 440
 
466 441
 `ajax.php?action=get_user_notifications`
467 442
 
468
-
469 443
 **Response**
470 444
 
471 445
 ```json
@@ -483,7 +457,6 @@ Fetch new upload filter notifications.
483 457
 }
484 458
 ```
485 459
 
486
-
487 460
 ### Clear user notification
488 461
 
489 462
 **Request**
@@ -502,7 +475,6 @@ Fetch new upload filter notifications.
502 475
 - Collages
503 476
 - Global
504 477
 
505
-
506 478
 **Response**
507 479
 
508 480
 ```php

+ 13
- 1
mkdocs.yml View File

@@ -1 +1,13 @@
1
-site_name: 'API ⸬ BioTorrents.de'
1
+site_name: 'Docs ⸬ BioTorrents.de'
2
+site_url: 'https://docs.biotorrents.de'
3
+
4
+repo_name: 'Gazelle'
5
+repo_url: 'https://github.com/biotorrents/gazelle'
6
+
7
+nav:
8
+  - 'index.md'
9
+  - 'torrents.md'
10
+  - 'users.md'
11
+  - 'forums.md'
12
+  - 'meta.md'
13
+  - 'install.md'

+ 1
- 0
readme.md View File

@@ -2,3 +2,4 @@ MkDocs Markdown files for the JSON API documentation.
2 2
 Please see
3 3
 [API ⸬ BioTorrents.de](https://docs.biotorrents.de)
4 4
 for more info.
5
+Now includes a Gazelle install guide!

+ 438
- 0
sphinx.conf View File

@@ -0,0 +1,438 @@
1
+source connect {
2
+    type = mysql
3
+    sql_host = 10.0.0.3
4
+    sql_port = 3306
5
+    #sql_sock = /var/run/mysqld/mysqld.sock
6
+    sql_user = gazelle_development
7
+    sql_pass = 
8
+    sql_db = gazelle_development
9
+
10
+    mysql_ssl_cert = /etc/mysql/ssl/client-cert.pem
11
+    mysql_ssl_key = /etc/mysql/ssl/client-key.pem
12
+    mysql_ssl_ca = /etc/mysql/ssl/ca.pem
13
+}
14
+
15
+source torrents_base : connect {
16
+    sql_attr_uint = groupid
17
+    sql_attr_uint = time
18
+    sql_attr_uint = categoryid
19
+    sql_attr_bigint = size
20
+    sql_attr_uint = snatched
21
+    sql_attr_uint = seeders
22
+    sql_attr_uint = leechers
23
+    sql_attr_uint = year
24
+    sql_attr_uint = freetorrent
25
+    sql_attr_uint = censored
26
+}
27
+
28
+source torrents : torrents_base {
29
+    # By inheriting from torrents_base, we keep all the connection info
30
+
31
+    sql_query_pre = SET group_concat_max_len = 101400
32
+    sql_query_pre = SET @starttime = NOW()
33
+    sql_query_pre = REPLACE INTO sphinx_index_last_pos VALUES ('torrents', UNIX_TIMESTAMP(@starttime))
34
+
35
+    sql_query_pre = TRUNCATE sphinx_tg
36
+    sql_query_pre = INSERT INTO sphinx_tg \
37
+        (id, name, namejp, tags, year, cnumber, catid, \
38
+            studio, series, dlsid) \
39
+        SELECT id, name, namejp, taglist, year, cataloguenumber, \
40
+            categoryid, studio, series, dlsiteid \
41
+        FROM torrents_group \
42
+        WHERE time < @starttime
43
+
44
+    sql_query_pre = TRUNCATE sphinx_t
45
+    sql_query_pre = INSERT INTO sphinx_t \
46
+        (id, gid, size, snatched, seeders, leechers, time, \
47
+            freetorrent, description, media, container, resolution, codec, \
48
+            audioformat, language, subber, censored, \
49
+            filelist, uid) \
50
+        SELECT ID, GroupID, Size, Snatched, Seeders, Leechers, UNIX_TIMESTAMP(Time), \
51
+            CAST(FreeTorrent AS CHAR), Description, Media, Container, Resolution, Codec, \
52
+            AudioFormat, Subbing, Language, Subber, Censored, \
53
+            FileList, UserID \
54
+        FROM torrents \
55
+        WHERE Time < @starttime
56
+
57
+    sql_query_pre = TRUNCATE sphinx_a
58
+    sql_query_pre = INSERT INTO sphinx_a \
59
+        (gid, aname) \
60
+        SELECT GroupID, GROUP_CONCAT(ag.Name SEPARATOR ' ') \
61
+        FROM torrents_artists AS ta \
62
+            JOIN artists_group AS ag USING(ArtistID) \
63
+        GROUP BY ta.groupid \
64
+        ORDER BY NULL
65
+
66
+    sql_query = SELECT t.id, g.id AS groupid, g.name AS groupname, \
67
+            g.namejp AS groupnamejp, tags AS taglist, year, year AS yearfulltext, \
68
+            cnumber AS cataloguenumber, dlsid AS dlsiteid, \
69
+            studio, series, \
70
+            catid AS categoryid, t.time, \
71
+            size, snatched, seeders, leechers, \
72
+            freetorrent, description, media, container, \
73
+            resolution, codec, audioformat, language, subber, censored, \
74
+            REPLACE(filelist, '_', ' ') AS filelist, \
75
+            '_all' AS fake \
76
+        FROM sphinx_t AS t \
77
+            JOIN sphinx_tg AS g ON t.gid = g.id
78
+
79
+    sql_joined_field = artistname from query; \
80
+        SELECT t.id, aname FROM sphinx_a JOIN sphinx_t AS t USING(gid) ORDER BY t.id ASC;
81
+
82
+    sql_query_post_index = DELETE FROM sphinx_delta WHERE Time <= \
83
+        (SELECT id FROM sphinx_index_last_pos WHERE type = 'torrents')
84
+}
85
+
86
+index torrents {
87
+    source = torrents
88
+    path = /var/lib/sphinxsearch/torrents
89
+    dict = keywords
90
+    preopen = 1
91
+
92
+    # http://sphinxsearch.com/docs/current.html#conf-morphology
93
+    morphology = stem_en, libstemmer_sv
94
+    #morphology = lemmatize_en_all
95
+    expand_keywords = 1
96
+
97
+    min_word_len = 2
98
+    phrase_boundary = U+F7 # This needs to the the same as the file delimiter in classes/torrents.class.php
99
+    phrase_boundary_step = 50
100
+    min_infix_len = 3
101
+
102
+    charset_table = \
103
+    U+00C0->a, U+00C1->a, U+00C2->a, U+00C3->a, U+00C4->a, U+00C5->a, U+00E0->a, U+00E1->a, U+00E2->a, \
104
+    U+00E3->a, U+00E4->a, U+00E5->a, U+0100->a, U+0101->a, U+0102->a, U+0103->a, U+010300->a, U+0104->a, U+0105->a, U+01CD->a, U+01CE->a, U+01DE->a, U+01DF->a, \
105
+    U+01E0->a, U+01E1->a, U+01FA->a, U+01FB->a, U+0200->a, U+0201->a, U+0202->a, U+0203->a, U+0226->a, U+0227->a, U+023A->a, U+0250->a, U+04D0->a, U+04D1->a, U+1D2C->a, U+1D43->a, U+1D44->a, U+1D8F->a, U+1E00->a, U+1E01->a, U+1E9A->a, U+1EA0->a, U+1EA1->a, \
106
+    U+1EA2->a, U+1EA3->a, U+1EA4->a, U+1EA5->a, U+1EA6->a, U+1EA7->a, U+1EA8->a, U+1EA9->a, U+1EAA->a, U+1EAB->a, U+1EAC->a, U+1EAD->a, U+1EAE->a, U+1EAF->a, U+1EB0->a, U+1EB1->a, U+1EB2->a, U+1EB3->a, U+1EB4->a, U+1EB5->a, U+1EB6->a, U+1EB7->a, U+2090->a, \
107
+    U+2C65->a, U+0180->b, U+0181->b, U+0182->b, U+0183->b, U+0243->b, U+0253->b, U+0299->b, U+16D2->b, U+1D03->b, U+1D2E->b, U+1D2F->b, U+1D47->b, U+1D6C->b, U+1D80->b, U+1E02->b, U+1E03->b, U+1E04->b, U+1E05->b, U+1E06->b, U+1E07->b, U+00C7->c, U+00E7->c, \
108
+    U+0106->c, U+0107->c, U+0108->c, U+0109->c, U+010A->c, U+010B->c, U+010C->c, U+010D->c, U+0187->c, U+0188->c, U+023B->c, U+023C->c, U+0255->c, U+0297->c, U+1D9C->c, U+1D9D->c, U+1E08->c, U+1E09->c, U+212D->c, U+2184->c, U+C487->c, U+010E->d, U+010F->d, U+0110->d, \
109
+    U+0111->d, U+0189->d, U+018A->d, U+018B->d, U+018C->d, U+01C5->d, U+01F2->d, U+0221->d, U+0256->d, U+0257->d, U+1D05->d, U+1D30->d, U+1D48->d, U+1D6D->d, U+1D81->d, U+1D91->d, U+1E0A->d, U+1E0B->d, U+1E0C->d, U+1E0D->d, U+1E0E->d, U+1E0F->d, U+1E10->d, \
110
+    U+1E11->d, U+1E12->d, U+1E13->d, U+00C8->e, U+00C9->e, U+00CA->e, U+00CB->e, U+00E8->e, U+00E9->e, U+00EA->e, U+00EB->e, U+0112->e, U+0113->e, U+0114->e, U+0115->e, U+0116->e, U+0117->e, U+0118->e, U+0119->e, U+011A->e, U+011B->e, U+018E->e, U+0190->e, \
111
+    U+01DD->e, U+0204->e, U+0205->e, U+0206->e, U+0207->e, U+0228->e, U+0229->e, U+0246->e, U+0247->e, U+0258->e, U+025B->e, U+025C->e, U+025D->e, U+025E->e, U+029A->e, U+1D07->e, U+1D08->e, U+1D31->e, U+1D32->e, U+1D49->e, U+1D4B->e, U+1D4C->e, U+1D92->e, \
112
+    U+1D93->e, U+1D94->e, U+1D9F->e, U+1E14->e, U+1E15->e, U+1E16->e, U+1E17->e, U+1E18->e, U+1E19->e, U+1E1A->e, U+1E1B->e, U+1E1C->e, U+1E1D->e, U+1EB8->e, U+1EB9->e, U+1EBA->e, U+1EBB->e, U+1EBC->e, U+1EBD->e, U+1EBE->e, U+1EBF->e, U+1EC0->e, U+1EC1->e, \
113
+    U+1EC2->e, U+1EC3->e, U+1EC4->e, U+1EC5->e, U+1EC6->e, U+1EC7->e, U+2091->e, U+0191->f, U+0192->f, U+1D6E->f, U+1D82->f, U+1DA0->f, U+1E1E->f, U+1E1F->f, U+011C->g, U+011D->g, U+011E->g, U+011F->g, U+0120->g, U+0121->g, U+0122->g, U+0123->g, U+0193->g, \
114
+    U+01E4->g, U+01E5->g, U+01E6->g, U+01E7->g, U+01F4->g, U+01F5->g, U+0260->g, U+0261->g, U+0262->g, U+029B->g, U+1D33->g, U+1D4D->g, U+1D77->g, U+1D79->g, U+1D83->g, U+1DA2->g, U+1E20->g, U+1E21->g, U+0124->h, U+0125->h, U+0126->h, U+0127->h, U+021E->h, \
115
+    U+021F->h, U+0265->h, U+0266->h, U+029C->h, U+02AE->h, U+02AF->h, U+02B0->h, U+02B1->h, U+1D34->h, U+1DA3->h, U+1E22->h, U+1E23->h, U+1E24->h, U+1E25->h, U+1E26->h, U+1E27->h, U+1E28->h, U+1E29->h, U+1E2A->h, U+1E2B->h, U+1E96->h, U+210C->h, U+2C67->h, \
116
+    U+2C68->h, U+2C75->h, U+2C76->h, U+00CC->i, U+00CD->i, U+00CE->i, U+00CF->i, U+00EC->i, U+00ED->i, U+00EE->i, U+00EF->i, U+010309->i, U+0128->i, U+0129->i, U+012A->i, U+012B->i, U+012C->i, U+012D->i, U+012E->i, U+012F->i, U+0130->i, U+0131->i, U+0197->i, \
117
+    U+01CF->i, U+01D0->i, U+0208->i, U+0209->i, U+020A->i, U+020B->i, U+0268->i, U+026A->i, U+040D->i, U+0418->i, U+0419->i, U+0438->i, U+0439->i, U+0456->i, U+1D09->i, U+1D35->i, U+1D4E->i, U+1D62->i, U+1D7B->i, U+1D96->i, U+1DA4->i, U+1DA6->i, U+1DA7->i, \
118
+    U+1E2C->i, U+1E2D->i, U+1E2E->i, U+1E2F->i, U+1EC8->i, U+1EC9->i, U+1ECA->i, U+1ECB->i, U+2071->i, U+2111->i, U+0134->j, U+0135->j, U+01C8->j, U+01CB->j, U+01F0->j, U+0237->j, U+0248->j, U+0249->j, U+025F->j, U+0284->j, U+029D->j, U+02B2->j, U+1D0A->j, \
119
+    U+1D36->j, U+1DA1->j, U+1DA8->j, U+0136->k, U+0137->k, U+0198->k, U+0199->k, U+01E8->k, U+01E9->k, U+029E->k, U+1D0B->k, U+1D37->k, U+1D4F->k, U+1D84->k, U+1E30->k, U+1E31->k, U+1E32->k, U+1E33->k, U+1E34->k, U+1E35->k, U+2C69->k, U+2C6A->k, U+0139->l, \
120
+    U+013A->l, U+013B->l, U+013C->l, U+013D->l, U+013E->l, U+013F->l, U+0140->l, U+0141->l, U+0142->l, U+019A->l, U+01C8->l, U+0234->l, U+023D->l, U+026B->l, U+026C->l, U+026D->l, U+029F->l, U+02E1->l, U+1D0C->l, U+1D38->l, U+1D85->l, U+1DA9->l, U+1DAA->l, \
121
+    U+1DAB->l, U+1E36->l, U+1E37->l, U+1E38->l, U+1E39->l, U+1E3A->l, U+1E3B->l, U+1E3C->l, U+1E3D->l, U+2C60->l, U+2C61->l, U+2C62->l, U+019C->m, U+026F->m, U+0270->m, U+0271->m, U+1D0D->m, U+1D1F->m, U+1D39->m, U+1D50->m, U+1D5A->m, U+1D6F->m, U+1D86->m, \
122
+    U+1DAC->m, U+1DAD->m, U+1E3E->m, U+1E3F->m, U+1E40->m, U+1E41->m, U+1E42->m, U+1E43->m, U+00D1->n, U+00F1->n, U+0143->n, U+0144->n, U+0145->n, U+0146->n, U+0147->n, U+0148->n, U+0149->n, U+019D->n, U+019E->n, U+01CB->n, U+01F8->n, U+01F9->n, U+0220->n, \
123
+    U+0235->n, U+0272->n, U+0273->n, U+0274->n, U+1D0E->n, U+1D3A->n, U+1D3B->n, U+1D70->n, U+1D87->n, U+1DAE->n, U+1DAF->n, U+1DB0->n, U+1E44->n, U+1E45->n, U+1E46->n, U+1E47->n, U+1E48->n, U+1E49->n, U+1E4A->n, U+1E4B->n, U+207F->n, U+00D2->o, U+00D3->o, \
124
+    U+00D4->o, U+00D5->o, U+00D6->o, U+00D8->o, U+00F2->o, U+00F3->o, U+00F4->o, U+00F5->o, U+00F6->o, U+00F8->o, U+01030F->o, U+014C->o, U+014D->o, U+014E->o, U+014F->o, U+0150->o, U+0151->o, U+0186->o, U+019F->o, U+01A0->o, U+01A1->o, U+01D1->o, U+01D2->o, \
125
+    U+01EA->o, U+01EB->o, U+01EC->o, U+01ED->o, U+01FE->o, U+01FF->o, U+020C->o, U+020D->o, U+020E->o, U+020F->o, U+022A->o, U+022B->o, U+022C->o, U+022D->o, U+022E->o, U+022F->o, U+0230->o, U+0231->o, U+0254->o, U+0275->o, U+043E->o, U+04E6->o, U+04E7->o, \
126
+    U+04E8->o, U+04E9->o, U+04EA->o, U+04EB->o, U+1D0F->o, U+1D10->o, U+1D11->o, U+1D12->o, U+1D13->o, U+1D16->o, U+1D17->o, U+1D3C->o, U+1D52->o, U+1D53->o, U+1D54->o, U+1D55->o, U+1D97->o, U+1DB1->o, U+1E4C->o, U+1E4D->o, U+1E4E->o, U+1E4F->o, U+1E50->o, \
127
+    U+1E51->o, U+1E52->o, U+1E53->o, U+1ECC->o, U+1ECD->o, U+1ECE->o, U+1ECF->o, U+1ED0->o, U+1ED1->o, U+1ED2->o, U+1ED3->o, U+1ED4->o, U+1ED5->o, U+1ED6->o, U+1ED7->o, U+1ED8->o, U+1ED9->o, U+1EDA->o, U+1EDB->o, U+1EDC->o, U+1EDD->o, U+1EDE->o, U+1EDF->o, \
128
+    U+1EE0->o, U+1EE1->o, U+1EE2->o, U+1EE3->o, U+2092->o, U+2C9E->o, U+2C9F->o, U+01A4->p, U+01A5->p, U+1D18->p, U+1D3E->p, U+1D56->p, U+1D71->p, U+1D7D->p, U+1D88->p, U+1E54->p, U+1E55->p, U+1E56->p, U+1E57->p, U+2C63->p, U+024A->q, U+024B->q, U+02A0->q, \
129
+    U+0154->r, U+0155->r, U+0156->r, U+0157->r, U+0158->r, U+0159->r, U+0210->r, U+0211->r, U+0212->r, U+0213->r, U+024C->r, U+024D->r, U+0279->r, U+027A->r, U+027B->r, U+027C->r, U+027D->r, U+027E->r, U+027F->r, U+0280->r, U+0281->r, U+02B3->r, U+02B4->r, \
130
+    U+02B5->r, U+02B6->r, U+1D19->r, U+1D1A->r, U+1D3F->r, U+1D63->r, U+1D72->r, U+1D73->r, U+1D89->r, U+1DCA->r, U+1E58->r, U+1E59->r, U+1E5A->r, U+1E5B->r, U+1E5C->r, U+1E5D->r, U+1E5E->r, U+1E5F->r, U+211C->r, U+2C64->r, U+00DF->s, U+015A->s, U+015B->s, \
131
+    U+015C->s, U+015D->s, U+015E->s, U+015F->s, U+0160->s, U+0161->s, U+017F->s, U+0218->s, U+0219->s, U+023F->s, U+0282->s, U+02E2->s, U+1D74->s, U+1D8A->s, U+1DB3->s, U+1E60->s, U+1E61->s, U+1E62->s, U+1E63->s, U+1E64->s, U+1E65->s, U+1E66->s, U+1E67->s, \
132
+    U+1E68->s, U+1E69->s, U+1E9B->s, U+0162->t, U+0163->t, U+0164->t, U+0165->t, U+0166->t, U+0167->t, U+01AB->t, U+01AC->t, U+01AD->t, U+01AE->t, U+021A->t, U+021B->t, U+0236->t, U+023E->t, U+0287->t, U+0288->t, U+1D1B->t, U+1D40->t, U+1D57->t, U+1D75->t, \
133
+    U+1DB5->t, U+1E6A->t, U+1E6B->t, U+1E6C->t, U+1E6D->t, U+1E6E->t, U+1E6F->t, U+1E70->t, U+1E71->t, U+1E97->t, U+2C66->t, U+00D9->u, U+00DA->u, U+00DB->u, U+00DC->u, U+00F9->u, U+00FA->u, U+00FB->u, U+00FC->u, U+010316->u, U+0168->u, U+0169->u, U+016A->u, \
134
+    U+016B->u, U+016C->u, U+016D->u, U+016E->u, U+016F->u, U+0170->u, U+0171->u, U+0172->u, U+0173->u, U+01AF->u, U+01B0->u, U+01D3->u, U+01D4->u, U+01D5->u, U+01D6->u, U+01D7->u, U+01D8->u, U+01D9->u, U+01DA->u, U+01DB->u, U+01DC->u, U+0214->u, U+0215->u, \
135
+    U+0216->u, U+0217->u, U+0244->u, U+0289->u, U+1D1C->u, U+1D1D->u, U+1D1E->u, U+1D41->u, U+1D58->u, U+1D59->u, U+1D64->u, U+1D7E->u, U+1D99->u, U+1DB6->u, U+1DB8->u, U+1E72->u, U+1E73->u, U+1E74->u, U+1E75->u, U+1E76->u, U+1E77->u, U+1E78->u, U+1E79->u, \
136
+    U+1E7A->u, U+1E7B->u, U+1EE4->u, U+1EE5->u, U+1EE6->u, U+1EE7->u, U+1EE8->u, U+1EE9->u, U+1EEA->u, U+1EEB->u, U+1EEC->u, U+1EED->u, U+1EEE->u, U+1EEF->u, U+1EF0->u, U+1EF1->u, U+01B2->v, U+0245->v, U+028B->v, U+028C->v, U+1D20->v, U+1D5B->v, U+1D65->v, \
137
+    U+1D8C->v, U+1DB9->v, U+1DBA->v, U+1E7C->v, U+1E7D->v, U+1E7E->v, U+1E7F->v, U+2C74->v, U+0174->w, U+0175->w, U+028D->w, U+02B7->w, U+1D21->w, U+1D42->w, U+1E80->w, U+1E81->w, U+1E82->w, U+1E83->w, U+1E84->w, U+1E85->w, U+1E86->w, U+1E87->w, U+1E88->w, \
138
+    U+1E89->w, U+1E98->w, U+02E3->x, U+1D8D->x, U+1E8A->x, U+1E8B->x, U+1E8C->x, U+1E8D->x, U+2093->x, U+00DD->y, U+00FD->y, U+00FF->y, U+0176->y, U+0177->y, U+0178->y, U+01B3->y, U+01B4->y, U+0232->y, U+0233->y, U+024E->y, U+024F->y, U+028E->y, U+028F->y, \
139
+    U+02B8->y, U+1E8E->y, U+1E8F->y, U+1E99->y, U+1EF2->y, U+1EF3->y, U+1EF4->y, U+1EF5->y, U+1EF6->y, U+1EF7->y, U+1EF8->y, U+1EF9->y, U+0179->z, U+017A->z, U+017B->z, U+017C->z, U+017D->z, U+017E->z, U+01B5->z, U+01B6->z, U+0224->z, U+0225->z, U+0240->z, \
140
+    U+0290->z, U+0291->z, U+1D22->z, U+1D76->z, U+1D8E->z, U+1DBB->z, U+1DBC->z, U+1DBD->z, U+1E90->z, U+1E91->z, U+1E92->z, U+1E93->z, U+1E94->z, U+1E95->z, U+2128->z, U+2C6B->z, U+2C6C->z, U+00C6->U+00E6, U+01E2->U+00E6, U+01E3->U+00E6, U+01FC->U+00E6, \
141
+    U+01FD->U+00E6, U+1D01->U+00E6, U+1D02->U+00E6, U+1D2D->U+00E6, U+1D46->U+00E6, U+00E6, U+0622->U+0627, U+0623->U+0627, U+0624->U+0648, U+0625->U+0627, U+0626->U+064A, U+06C0->U+06D5, U+06C2->U+06C1, U+06D3->U+06D2, U+FB50->U+0671, U+FB51->U+0671, U+FB52->U+067B, \
142
+    U+FB53->U+067B, U+FB54->U+067B, U+FB56->U+067E, U+FB57->U+067E, U+FB58->U+067E, U+FB5A->U+0680, U+FB5B->U+0680, U+FB5C->U+0680, U+FB5E->U+067A, U+FB5F->U+067A, U+FB60->U+067A, U+FB62->U+067F, U+FB63->U+067F, U+FB64->U+067F, U+FB66->U+0679, U+FB67->U+0679, \
143
+    U+FB68->U+0679, U+FB6A->U+06A4, U+FB6B->U+06A4, U+FB6C->U+06A4, U+FB6E->U+06A6, U+FB6F->U+06A6, U+FB70->U+06A6, U+FB72->U+0684, U+FB73->U+0684, U+FB74->U+0684, U+FB76->U+0683, U+FB77->U+0683, U+FB78->U+0683, U+FB7A->U+0686, U+FB7B->U+0686, U+FB7C->U+0686, \
144
+    U+FB7E->U+0687, U+FB7F->U+0687, U+FB80->U+0687, U+FB82->U+068D, U+FB83->U+068D, U+FB84->U+068C, U+FB85->U+068C, U+FB86->U+068E, U+FB87->U+068E, U+FB88->U+0688, U+FB89->U+0688, U+FB8A->U+0698, U+FB8B->U+0698, U+FB8C->U+0691, U+FB8D->U+0691, U+FB8E->U+06A9, \
145
+    U+FB8F->U+06A9, U+FB90->U+06A9, U+FB92->U+06AF, U+FB93->U+06AF, U+FB94->U+06AF, U+FB96->U+06B3, U+FB97->U+06B3, U+FB98->U+06B3, U+FB9A->U+06B1, U+FB9B->U+06B1, U+FB9C->U+06B1, U+FB9E->U+06BA, U+FB9F->U+06BA, U+FBA0->U+06BB, U+FBA1->U+06BB, U+FBA2->U+06BB, \
146
+    U+FBA4->U+06C0, U+FBA5->U+06C0, U+FBA6->U+06C1, U+FBA7->U+06C1, U+FBA8->U+06C1, U+FBAA->U+06BE, U+FBAB->U+06BE, U+FBAC->U+06BE, U+FBAE->U+06D2, U+FBAF->U+06D2, U+FBB0->U+06D3, U+FBB1->U+06D3, U+FBD3->U+06AD, U+FBD4->U+06AD, U+FBD5->U+06AD, U+FBD7->U+06C7, \
147
+    U+FBD8->U+06C7, U+FBD9->U+06C6, U+FBDA->U+06C6, U+FBDB->U+06C8, U+FBDC->U+06C8, U+FBDD->U+0677, U+FBDE->U+06CB, U+FBDF->U+06CB, U+FBE0->U+06C5, U+FBE1->U+06C5, U+FBE2->U+06C9, U+FBE3->U+06C9, U+FBE4->U+06D0, U+FBE5->U+06D0, U+FBE6->U+06D0, U+FBE8->U+0649, \
148
+    U+FBFC->U+06CC, U+FBFD->U+06CC, U+FBFE->U+06CC, U+0621, U+0627..U+063A, U+0641..U+064A, U+0660..U+0669, U+066E, U+066F, U+0671..U+06BF, U+06C1, U+06C3..U+06D2, U+06D5, U+06EE..U+06FC, U+06FF, U+0750..U+076D, U+FB55, U+FB59, U+FB5D, U+FB61, U+FB65, U+FB69, \
149
+    U+FB6D, U+FB71, U+FB75, U+FB79, U+FB7D, U+FB81, U+FB91, U+FB95, U+FB99, U+FB9D, U+FBA3, U+FBA9, U+FBAD, U+FBD6, U+FBE7, U+FBE9, U+FBFF, U+0531..U+0556->U+0561..U+0586, U+0561..U+0586, U+0587, U+09DC->U+09A1, U+09DD->U+09A2, U+09DF->U+09AF, U+09F0->U+09AC, \
150
+    U+09F1->U+09AC, U+0985..U+0990, U+0993..U+09B0, U+09B2, U+09B6..U+09B9, U+09CE, U+09E0, U+09E1, U+09E6..U+09EF, U+F900->U+8C48, U+F901->U+66F4, U+F902->U+8ECA, U+F903->U+8CC8, U+F904->U+6ED1, U+F905->U+4E32, U+F906->U+53E5, U+F907->U+9F9C, U+F908->U+9F9C, \
151
+    U+F909->U+5951, U+F90A->U+91D1, U+F90B->U+5587, U+F90C->U+5948, U+F90D->U+61F6, U+F90E->U+7669, U+F90F->U+7F85, U+F910->U+863F, U+F911->U+87BA, U+F912->U+88F8, U+F913->U+908F, U+F914->U+6A02, U+F915->U+6D1B, U+F916->U+70D9, U+F917->U+73DE, U+F918->U+843D, \
152
+    U+F919->U+916A, U+F91A->U+99F1, U+F91B->U+4E82, U+F91C->U+5375, U+F91D->U+6B04, U+F91E->U+721B, U+F91F->U+862D, U+F920->U+9E1E, U+F921->U+5D50, U+F922->U+6FEB, U+F923->U+85CD, U+F924->U+8964, U+F925->U+62C9, U+F926->U+81D8, U+F927->U+881F, U+F928->U+5ECA, \
153
+    U+F929->U+6717, U+F92A->U+6D6A, U+F92B->U+72FC, U+F92C->U+90CE, U+F92D->U+4F86, U+F92E->U+51B7, U+F92F->U+52DE, U+F930->U+64C4, U+F931->U+6AD3, U+F932->U+7210, U+F933->U+76E7, U+F934->U+8001, U+F935->U+8606, U+F936->U+865C, U+F937->U+8DEF, U+F938->U+9732, \
154
+    U+F939->U+9B6F, U+F93A->U+9DFA, U+F93B->U+788C, U+F93C->U+797F, U+F93D->U+7DA0, U+F93E->U+83C9, U+F93F->U+9304, U+F940->U+9E7F, U+F941->U+8AD6, U+F942->U+58DF, U+F943->U+5F04, U+F944->U+7C60, U+F945->U+807E, U+F946->U+7262, U+F947->U+78CA, U+F948->U+8CC2, \
155
+    U+F949->U+96F7, U+F94A->U+58D8, U+F94B->U+5C62, U+F94C->U+6A13, U+F94D->U+6DDA, U+F94E->U+6F0F, U+F94F->U+7D2F, U+F950->U+7E37, U+F951->U+964B, U+F952->U+52D2, U+F953->U+808B, U+F954->U+51DC, U+F955->U+51CC, U+F956->U+7A1C, U+F957->U+7DBE, U+F958->U+83F1, \
156
+    U+F959->U+9675, U+F95A->U+8B80, U+F95B->U+62CF, U+F95C->U+6A02, U+F95D->U+8AFE, U+F95E->U+4E39, U+F95F->U+5BE7, U+F960->U+6012, U+F961->U+7387, U+F962->U+7570, U+F963->U+5317, U+F964->U+78FB, U+F965->U+4FBF, U+F966->U+5FA9, U+F967->U+4E0D, U+F968->U+6CCC, \
157
+    U+F969->U+6578, U+F96A->U+7D22, U+F96B->U+53C3, U+F96C->U+585E, U+F96D->U+7701, U+F96E->U+8449, U+F96F->U+8AAA, U+F970->U+6BBA, U+F971->U+8FB0, U+F972->U+6C88, U+F973->U+62FE, U+F974->U+82E5, U+F975->U+63A0, U+F976->U+7565, U+F977->U+4EAE, U+F978->U+5169, \
158
+    U+F979->U+51C9, U+F97A->U+6881, U+F97B->U+7CE7, U+F97C->U+826F, U+F97D->U+8AD2, U+F97E->U+91CF, U+F97F->U+52F5, U+F980->U+5442, U+F981->U+5973, U+F982->U+5EEC, U+F983->U+65C5, U+F984->U+6FFE, U+F985->U+792A, U+F986->U+95AD, U+F987->U+9A6A, U+F988->U+9E97, \
159
+    U+F989->U+9ECE, U+F98A->U+529B, U+F98B->U+66C6, U+F98C->U+6B77, U+F98D->U+8F62, U+F98E->U+5E74, U+F98F->U+6190, U+F990->U+6200, U+F991->U+649A, U+F992->U+6F23, U+F993->U+7149, U+F994->U+7489, U+F995->U+79CA, U+F996->U+7DF4, U+F997->U+806F, U+F998->U+8F26, \
160
+    U+F999->U+84EE, U+F99A->U+9023, U+F99B->U+934A, U+F99C->U+5217, U+F99D->U+52A3, U+F99E->U+54BD, U+F99F->U+70C8, U+F9A0->U+88C2, U+F9A1->U+8AAA, U+F9A2->U+5EC9, U+F9A3->U+5FF5, U+F9A4->U+637B, U+F9A5->U+6BAE, U+F9A6->U+7C3E, U+F9A7->U+7375, U+F9A8->U+4EE4, \
161
+    U+F9A9->U+56F9, U+F9AA->U+5BE7, U+F9AB->U+5DBA, U+F9AC->U+601C, U+F9AD->U+73B2, U+F9AE->U+7469, U+F9AF->U+7F9A, U+F9B0->U+8046, U+F9B1->U+9234, U+F9B2->U+96F6, U+F9B3->U+9748, U+F9B4->U+9818, U+F9B5->U+4F8B, U+F9B6->U+79AE, U+F9B7->U+91B4, U+F9B8->U+96B8, \
162
+    U+F9B9->U+60E1, U+F9BA->U+4E86, U+F9BB->U+50DA, U+F9BC->U+5BEE, U+F9BD->U+5C3F, U+F9BE->U+6599, U+F9BF->U+6A02, U+F9C0->U+71CE, U+F9C1->U+7642, U+F9C2->U+84FC, U+F9C3->U+907C, U+F9C4->U+9F8D, U+F9C5->U+6688, U+F9C6->U+962E, U+F9C7->U+5289, U+F9C8->U+677B, \
163
+    U+F9C9->U+67F3, U+F9CA->U+6D41, U+F9CB->U+6E9C, U+F9CC->U+7409, U+F9CD->U+7559, U+F9CE->U+786B, U+F9CF->U+7D10, U+F9D0->U+985E, U+F9D1->U+516D, U+F9D2->U+622E, U+F9D3->U+9678, U+F9D4->U+502B, U+F9D5->U+5D19, U+F9D6->U+6DEA, U+F9D7->U+8F2A, U+F9D8->U+5F8B, \
164
+    U+F9D9->U+6144, U+F9DA->U+6817, U+F9DB->U+7387, U+F9DC->U+9686, U+F9DD->U+5229, U+F9DE->U+540F, U+F9DF->U+5C65, U+F9E0->U+6613, U+F9E1->U+674E, U+F9E2->U+68A8, U+F9E3->U+6CE5, U+F9E4->U+7406, U+F9E5->U+75E2, U+F9E6->U+7F79, U+F9E7->U+88CF, U+F9E8->U+88E1, \
165
+    U+F9E9->U+91CC, U+F9EA->U+96E2, U+F9EB->U+533F, U+F9EC->U+6EBA, U+F9ED->U+541D, U+F9EE->U+71D0, U+F9EF->U+7498, U+F9F0->U+85FA, U+F9F1->U+96A3, U+F9F2->U+9C57, U+F9F3->U+9E9F, U+F9F4->U+6797, U+F9F5->U+6DCB, U+F9F6->U+81E8, U+F9F7->U+7ACB, U+F9F8->U+7B20, \
166
+    U+F9F9->U+7C92, U+F9FA->U+72C0, U+F9FB->U+7099, U+F9FC->U+8B58, U+F9FD->U+4EC0, U+F9FE->U+8336, U+F9FF->U+523A, U+FA00->U+5207, U+FA01->U+5EA6, U+FA02->U+62D3, U+FA03->U+7CD6, U+FA04->U+5B85, U+FA05->U+6D1E, U+FA06->U+66B4, U+FA07->U+8F3B, U+FA08->U+884C, \
167
+    U+FA09->U+964D, U+FA0A->U+898B, U+FA0B->U+5ED3, U+FA0C->U+5140, U+FA0D->U+55C0, U+FA10->U+585A, U+FA12->U+6674, U+FA15->U+51DE, U+FA16->U+732A, U+FA17->U+76CA, U+FA18->U+793C, U+FA19->U+795E, U+FA1A->U+7965, U+FA1B->U+798F, U+FA1C->U+9756, U+FA1D->U+7CBE, \
168
+    U+FA1E->U+7FBD, U+FA20->U+8612, U+FA22->U+8AF8, U+FA25->U+9038, U+FA26->U+90FD, U+FA2A->U+98EF, U+FA2B->U+98FC, U+FA2C->U+9928, U+FA2D->U+9DB4, U+FA30->U+4FAE, U+FA31->U+50E7, U+FA32->U+514D, U+FA33->U+52C9, U+FA34->U+52E4, U+FA35->U+5351, U+FA36->U+559D, \
169
+    U+FA37->U+5606, U+FA38->U+5668, U+FA39->U+5840, U+FA3A->U+58A8, U+FA3B->U+5C64, U+FA3C->U+5C6E, U+FA3D->U+6094, U+FA3E->U+6168, U+FA3F->U+618E, U+FA40->U+61F2, U+FA41->U+654F, U+FA42->U+65E2, U+FA43->U+6691, U+FA44->U+6885, U+FA45->U+6D77, U+FA46->U+6E1A, \
170
+    U+FA47->U+6F22, U+FA48->U+716E, U+FA49->U+722B, U+FA4A->U+7422, U+FA4B->U+7891, U+FA4C->U+793E, U+FA4D->U+7949, U+FA4E->U+7948, U+FA4F->U+7950, U+FA50->U+7956, U+FA51->U+795D, U+FA52->U+798D, U+FA53->U+798E, U+FA54->U+7A40, U+FA55->U+7A81, U+FA56->U+7BC0, \
171
+    U+FA57->U+7DF4, U+FA58->U+7E09, U+FA59->U+7E41, U+FA5A->U+7F72, U+FA5B->U+8005, U+FA5C->U+81ED, U+FA5D->U+8279, U+FA5E->U+8279, U+FA5F->U+8457, U+FA60->U+8910, U+FA61->U+8996, U+FA62->U+8B01, U+FA63->U+8B39, U+FA64->U+8CD3, U+FA65->U+8D08, U+FA66->U+8FB6, \
172
+    U+FA67->U+9038, U+FA68->U+96E3, U+FA69->U+97FF, U+FA6A->U+983B, U+FA70->U+4E26, U+FA71->U+51B5, U+FA72->U+5168, U+FA73->U+4F80, U+FA74->U+5145, U+FA75->U+5180, U+FA76->U+52C7, U+FA77->U+52FA, U+FA78->U+559D, U+FA79->U+5555, U+FA7A->U+5599, U+FA7B->U+55E2, \
173
+    U+FA7C->U+585A, U+FA7D->U+58B3, U+FA7E->U+5944, U+FA7F->U+5954, U+FA80->U+5A62, U+FA81->U+5B28, U+FA82->U+5ED2, U+FA83->U+5ED9, U+FA84->U+5F69, U+FA85->U+5FAD, U+FA86->U+60D8, U+FA87->U+614E, U+FA88->U+6108, U+FA89->U+618E, U+FA8A->U+6160, U+FA8B->U+61F2, \
174
+    U+FA8C->U+6234, U+FA8D->U+63C4, U+FA8E->U+641C, U+FA8F->U+6452, U+FA90->U+6556, U+FA91->U+6674, U+FA92->U+6717, U+FA93->U+671B, U+FA94->U+6756, U+FA95->U+6B79, U+FA96->U+6BBA, U+FA97->U+6D41, U+FA98->U+6EDB, U+FA99->U+6ECB, U+FA9A->U+6F22, U+FA9B->U+701E, \
175
+    U+FA9C->U+716E, U+FA9D->U+77A7, U+FA9E->U+7235, U+FA9F->U+72AF, U+FAA0->U+732A, U+FAA1->U+7471, U+FAA2->U+7506, U+FAA3->U+753B, U+FAA4->U+761D, U+FAA5->U+761F, U+FAA6->U+76CA, U+FAA7->U+76DB, U+FAA8->U+76F4, U+FAA9->U+774A, U+FAAA->U+7740, U+FAAB->U+78CC, \
176
+    U+FAAC->U+7AB1, U+FAAD->U+7BC0, U+FAAE->U+7C7B, U+FAAF->U+7D5B, U+FAB0->U+7DF4, U+FAB1->U+7F3E, U+FAB2->U+8005, U+FAB3->U+8352, U+FAB4->U+83EF, U+FAB5->U+8779, U+FAB6->U+8941, U+FAB7->U+8986, U+FAB8->U+8996, U+FAB9->U+8ABF, U+FABA->U+8AF8, U+FABB->U+8ACB, \
177
+    U+FABC->U+8B01, U+FABD->U+8AFE, U+FABE->U+8AED, U+FABF->U+8B39, U+FAC0->U+8B8A, U+FAC1->U+8D08, U+FAC2->U+8F38, U+FAC3->U+9072, U+FAC4->U+9199, U+FAC5->U+9276, U+FAC6->U+967C, U+FAC7->U+96E3, U+FAC8->U+9756, U+FAC9->U+97DB, U+FACA->U+97FF, U+FACB->U+980B, \
178
+    U+FACC->U+983B, U+FACD->U+9B12, U+FACE->U+9F9C, U+FACF->U+2284A, U+FAD0->U+22844, U+FAD1->U+233D5, U+FAD2->U+3B9D, U+FAD3->U+4018, U+FAD4->U+4039, U+FAD5->U+25249, U+FAD6->U+25CD0, U+FAD7->U+27ED3, U+FAD8->U+9F43, U+FAD9->U+9F8E, U+2F800->U+4E3D, U+2F801->U+4E38, \
179
+    U+2F802->U+4E41, U+2F803->U+20122, U+2F804->U+4F60, U+2F805->U+4FAE, U+2F806->U+4FBB, U+2F807->U+5002, U+2F808->U+507A, U+2F809->U+5099, U+2F80A->U+50E7, U+2F80B->U+50CF, U+2F80C->U+349E, U+2F80D->U+2063A, U+2F80E->U+514D, U+2F80F->U+5154, U+2F810->U+5164, \
180
+    U+2F811->U+5177, U+2F812->U+2051C, U+2F813->U+34B9, U+2F814->U+5167, U+2F815->U+518D, U+2F816->U+2054B, U+2F817->U+5197, U+2F818->U+51A4, U+2F819->U+4ECC, U+2F81A->U+51AC, U+2F81B->U+51B5, U+2F81C->U+291DF, U+2F81D->U+51F5, U+2F81E->U+5203, U+2F81F->U+34DF, \
181
+    U+2F820->U+523B, U+2F821->U+5246, U+2F822->U+5272, U+2F823->U+5277, U+2F824->U+3515, U+2F825->U+52C7, U+2F826->U+52C9, U+2F827->U+52E4, U+2F828->U+52FA, U+2F829->U+5305, U+2F82A->U+5306, U+2F82B->U+5317, U+2F82C->U+5349, U+2F82D->U+5351, U+2F82E->U+535A, \
182
+    U+2F82F->U+5373, U+2F830->U+537D, U+2F831->U+537F, U+2F832->U+537F, U+2F833->U+537F, U+2F834->U+20A2C, U+2F835->U+7070, U+2F836->U+53CA, U+2F837->U+53DF, U+2F838->U+20B63, U+2F839->U+53EB, U+2F83A->U+53F1, U+2F83B->U+5406, U+2F83C->U+549E, U+2F83D->U+5438, \
183
+    U+2F83E->U+5448, U+2F83F->U+5468, U+2F840->U+54A2, U+2F841->U+54F6, U+2F842->U+5510, U+2F843->U+5553, U+2F844->U+5563, U+2F845->U+5584, U+2F846->U+5584, U+2F847->U+5599, U+2F848->U+55AB, U+2F849->U+55B3, U+2F84A->U+55C2, U+2F84B->U+5716, U+2F84C->U+5606, \
184
+    U+2F84D->U+5717, U+2F84E->U+5651, U+2F84F->U+5674, U+2F850->U+5207, U+2F851->U+58EE, U+2F852->U+57CE, U+2F853->U+57F4, U+2F854->U+580D, U+2F855->U+578B, U+2F856->U+5832, U+2F857->U+5831, U+2F858->U+58AC, U+2F859->U+214E4, U+2F85A->U+58F2, U+2F85B->U+58F7, \
185
+    U+2F85C->U+5906, U+2F85D->U+591A, U+2F85E->U+5922, U+2F85F->U+5962, U+2F860->U+216A8, U+2F861->U+216EA, U+2F862->U+59EC, U+2F863->U+5A1B, U+2F864->U+5A27, U+2F865->U+59D8, U+2F866->U+5A66, U+2F867->U+36EE, U+2F868->U+36FC, U+2F869->U+5B08, U+2F86A->U+5B3E, \
186
+    U+2F86B->U+5B3E, U+2F86C->U+219C8, U+2F86D->U+5BC3, U+2F86E->U+5BD8, U+2F86F->U+5BE7, U+2F870->U+5BF3, U+2F871->U+21B18, U+2F872->U+5BFF, U+2F873->U+5C06, U+2F874->U+5F53, U+2F875->U+5C22, U+2F876->U+3781, U+2F877->U+5C60, U+2F878->U+5C6E, U+2F879->U+5CC0, \
187
+    U+2F87A->U+5C8D, U+2F87B->U+21DE4, U+2F87C->U+5D43, U+2F87D->U+21DE6, U+2F87E->U+5D6E, U+2F87F->U+5D6B, U+2F880->U+5D7C, U+2F881->U+5DE1, U+2F882->U+5DE2, U+2F883->U+382F, U+2F884->U+5DFD, U+2F885->U+5E28, U+2F886->U+5E3D, U+2F887->U+5E69, U+2F888->U+3862, \
188
+    U+2F889->U+22183, U+2F88A->U+387C, U+2F88B->U+5EB0, U+2F88C->U+5EB3, U+2F88D->U+5EB6, U+2F88E->U+5ECA, U+2F88F->U+2A392, U+2F890->U+5EFE, U+2F891->U+22331, U+2F892->U+22331, U+2F893->U+8201, U+2F894->U+5F22, U+2F895->U+5F22, U+2F896->U+38C7, U+2F897->U+232B8, \
189
+    U+2F898->U+261DA, U+2F899->U+5F62, U+2F89A->U+5F6B, U+2F89B->U+38E3, U+2F89C->U+5F9A, U+2F89D->U+5FCD, U+2F89E->U+5FD7, U+2F89F->U+5FF9, U+2F8A0->U+6081, U+2F8A1->U+393A, U+2F8A2->U+391C, U+2F8A3->U+6094, U+2F8A4->U+226D4, U+2F8A5->U+60C7, U+2F8A6->U+6148, \
190
+    U+2F8A7->U+614C, U+2F8A8->U+614E, U+2F8A9->U+614C, U+2F8AA->U+617A, U+2F8AB->U+618E, U+2F8AC->U+61B2, U+2F8AD->U+61A4, U+2F8AE->U+61AF, U+2F8AF->U+61DE, U+2F8B0->U+61F2, U+2F8B1->U+61F6, U+2F8B2->U+6210, U+2F8B3->U+621B, U+2F8B4->U+625D, U+2F8B5->U+62B1, \
191
+    U+2F8B6->U+62D4, U+2F8B7->U+6350, U+2F8B8->U+22B0C, U+2F8B9->U+633D, U+2F8BA->U+62FC, U+2F8BB->U+6368, U+2F8BC->U+6383, U+2F8BD->U+63E4, U+2F8BE->U+22BF1, U+2F8BF->U+6422, U+2F8C0->U+63C5, U+2F8C1->U+63A9, U+2F8C2->U+3A2E, U+2F8C3->U+6469, U+2F8C4->U+647E, \
192
+    U+2F8C5->U+649D, U+2F8C6->U+6477, U+2F8C7->U+3A6C, U+2F8C8->U+654F, U+2F8C9->U+656C, U+2F8CA->U+2300A, U+2F8CB->U+65E3, U+2F8CC->U+66F8, U+2F8CD->U+6649, U+2F8CE->U+3B19, U+2F8CF->U+6691, U+2F8D0->U+3B08, U+2F8D1->U+3AE4, U+2F8D2->U+5192, U+2F8D3->U+5195, \
193
+    U+2F8D4->U+6700, U+2F8D5->U+669C, U+2F8D6->U+80AD, U+2F8D7->U+43D9, U+2F8D8->U+6717, U+2F8D9->U+671B, U+2F8DA->U+6721, U+2F8DB->U+675E, U+2F8DC->U+6753, U+2F8DD->U+233C3, U+2F8DE->U+3B49, U+2F8DF->U+67FA, U+2F8E0->U+6785, U+2F8E1->U+6852, U+2F8E2->U+6885, \
194
+    U+2F8E3->U+2346D, U+2F8E4->U+688E, U+2F8E5->U+681F, U+2F8E6->U+6914, U+2F8E7->U+3B9D, U+2F8E8->U+6942, U+2F8E9->U+69A3, U+2F8EA->U+69EA, U+2F8EB->U+6AA8, U+2F8EC->U+236A3, U+2F8ED->U+6ADB, U+2F8EE->U+3C18, U+2F8EF->U+6B21, U+2F8F0->U+238A7, U+2F8F1->U+6B54, \
195
+    U+2F8F2->U+3C4E, U+2F8F3->U+6B72, U+2F8F4->U+6B9F, U+2F8F5->U+6BBA, U+2F8F6->U+6BBB, U+2F8F7->U+23A8D, U+2F8F8->U+21D0B, U+2F8F9->U+23AFA, U+2F8FA->U+6C4E, U+2F8FB->U+23CBC, U+2F8FC->U+6CBF, U+2F8FD->U+6CCD, U+2F8FE->U+6C67, U+2F8FF->U+6D16, U+2F900->U+6D3E, \
196
+    U+2F901->U+6D77, U+2F902->U+6D41, U+2F903->U+6D69, U+2F904->U+6D78, U+2F905->U+6D85, U+2F906->U+23D1E, U+2F907->U+6D34, U+2F908->U+6E2F, U+2F909->U+6E6E, U+2F90A->U+3D33, U+2F90B->U+6ECB, U+2F90C->U+6EC7, U+2F90D->U+23ED1, U+2F90E->U+6DF9, U+2F90F->U+6F6E, \
197
+    U+2F910->U+23F5E, U+2F911->U+23F8E, U+2F912->U+6FC6, U+2F913->U+7039, U+2F914->U+701E, U+2F915->U+701B, U+2F916->U+3D96, U+2F917->U+704A, U+2F918->U+707D, U+2F919->U+7077, U+2F91A->U+70AD, U+2F91B->U+20525, U+2F91C->U+7145, U+2F91D->U+24263, U+2F91E->U+719C, \
198
+    U+2F91F->U+243AB, U+2F920->U+7228, U+2F921->U+7235, U+2F922->U+7250, U+2F923->U+24608, U+2F924->U+7280, U+2F925->U+7295, U+2F926->U+24735, U+2F927->U+24814, U+2F928->U+737A, U+2F929->U+738B, U+2F92A->U+3EAC, U+2F92B->U+73A5, U+2F92C->U+3EB8, U+2F92D->U+3EB8, \
199
+    U+2F92E->U+7447, U+2F92F->U+745C, U+2F930->U+7471, U+2F931->U+7485, U+2F932->U+74CA, U+2F933->U+3F1B, U+2F934->U+7524, U+2F935->U+24C36, U+2F936->U+753E, U+2F937->U+24C92, U+2F938->U+7570, U+2F939->U+2219F, U+2F93A->U+7610, U+2F93B->U+24FA1, U+2F93C->U+24FB8, \
200
+    U+2F93D->U+25044, U+2F93E->U+3FFC, U+2F93F->U+4008, U+2F940->U+76F4, U+2F941->U+250F3, U+2F942->U+250F2, U+2F943->U+25119, U+2F944->U+25133, U+2F945->U+771E, U+2F946->U+771F, U+2F947->U+771F, U+2F948->U+774A, U+2F949->U+4039, U+2F94A->U+778B, U+2F94B->U+4046, \
201
+    U+2F94C->U+4096, U+2F94D->U+2541D, U+2F94E->U+784E, U+2F94F->U+788C, U+2F950->U+78CC, U+2F951->U+40E3, U+2F952->U+25626, U+2F953->U+7956, U+2F954->U+2569A, U+2F955->U+256C5, U+2F956->U+798F, U+2F957->U+79EB, U+2F958->U+412F, U+2F959->U+7A40, U+2F95A->U+7A4A, \
202
+    U+2F95B->U+7A4F, U+2F95C->U+2597C, U+2F95D->U+25AA7, U+2F95E->U+25AA7, U+2F95F->U+7AEE, U+2F960->U+4202, U+2F961->U+25BAB, U+2F962->U+7BC6, U+2F963->U+7BC9, U+2F964->U+4227, U+2F965->U+25C80, U+2F966->U+7CD2, U+2F967->U+42A0, U+2F968->U+7CE8, U+2F969->U+7CE3, \
203
+    U+2F96A->U+7D00, U+2F96B->U+25F86, U+2F96C->U+7D63, U+2F96D->U+4301, U+2F96E->U+7DC7, U+2F96F->U+7E02, U+2F970->U+7E45, U+2F971->U+4334, U+2F972->U+26228, U+2F973->U+26247, U+2F974->U+4359, U+2F975->U+262D9, U+2F976->U+7F7A, U+2F977->U+2633E, U+2F978->U+7F95, \
204
+    U+2F979->U+7FFA, U+2F97A->U+8005, U+2F97B->U+264DA, U+2F97C->U+26523, U+2F97D->U+8060, U+2F97E->U+265A8, U+2F97F->U+8070, U+2F980->U+2335F, U+2F981->U+43D5, U+2F982->U+80B2, U+2F983->U+8103, U+2F984->U+440B, U+2F985->U+813E, U+2F986->U+5AB5, U+2F987->U+267A7, \
205
+    U+2F988->U+267B5, U+2F989->U+23393, U+2F98A->U+2339C, U+2F98B->U+8201, U+2F98C->U+8204, U+2F98D->U+8F9E, U+2F98E->U+446B, U+2F98F->U+8291, U+2F990->U+828B, U+2F991->U+829D, U+2F992->U+52B3, U+2F993->U+82B1, U+2F994->U+82B3, U+2F995->U+82BD, U+2F996->U+82E6, \
206
+    U+2F997->U+26B3C, U+2F998->U+82E5, U+2F999->U+831D, U+2F99A->U+8363, U+2F99B->U+83AD, U+2F99C->U+8323, U+2F99D->U+83BD, U+2F99E->U+83E7, U+2F99F->U+8457, U+2F9A0->U+8353, U+2F9A1->U+83CA, U+2F9A2->U+83CC, U+2F9A3->U+83DC, U+2F9A4->U+26C36, U+2F9A5->U+26D6B, \
207
+    U+2F9A6->U+26CD5, U+2F9A7->U+452B, U+2F9A8->U+84F1, U+2F9A9->U+84F3, U+2F9AA->U+8516, U+2F9AB->U+273CA, U+2F9AC->U+8564, U+2F9AD->U+26F2C, U+2F9AE->U+455D, U+2F9AF->U+4561, U+2F9B0->U+26FB1, U+2F9B1->U+270D2, U+2F9B2->U+456B, U+2F9B3->U+8650, U+2F9B4->U+865C, \
208
+    U+2F9B5->U+8667, U+2F9B6->U+8669, U+2F9B7->U+86A9, U+2F9B8->U+8688, U+2F9B9->U+870E, U+2F9BA->U+86E2, U+2F9BB->U+8779, U+2F9BC->U+8728, U+2F9BD->U+876B, U+2F9BE->U+8786, U+2F9BF->U+45D7, U+2F9C0->U+87E1, U+2F9C1->U+8801, U+2F9C2->U+45F9, U+2F9C3->U+8860, \
209
+    U+2F9C4->U+8863, U+2F9C5->U+27667, U+2F9C6->U+88D7, U+2F9C7->U+88DE, U+2F9C8->U+4635, U+2F9C9->U+88FA, U+2F9CA->U+34BB, U+2F9CB->U+278AE, U+2F9CC->U+27966, U+2F9CD->U+46BE, U+2F9CE->U+46C7, U+2F9CF->U+8AA0, U+2F9D0->U+8AED, U+2F9D1->U+8B8A, U+2F9D2->U+8C55, \
210
+    U+2F9D3->U+27CA8, U+2F9D4->U+8CAB, U+2F9D5->U+8CC1, U+2F9D6->U+8D1B, U+2F9D7->U+8D77, U+2F9D8->U+27F2F, U+2F9D9->U+20804, U+2F9DA->U+8DCB, U+2F9DB->U+8DBC, U+2F9DC->U+8DF0, U+2F9DD->U+208DE, U+2F9DE->U+8ED4, U+2F9DF->U+8F38, U+2F9E0->U+285D2, U+2F9E1->U+285ED, \
211
+    U+2F9E2->U+9094, U+2F9E3->U+90F1, U+2F9E4->U+9111, U+2F9E5->U+2872E, U+2F9E6->U+911B, U+2F9E7->U+9238, U+2F9E8->U+92D7, U+2F9E9->U+92D8, U+2F9EA->U+927C, U+2F9EB->U+93F9, U+2F9EC->U+9415, U+2F9ED->U+28BFA, U+2F9EE->U+958B, U+2F9EF->U+4995, U+2F9F0->U+95B7, \
212
+    U+2F9F1->U+28D77, U+2F9F2->U+49E6, U+2F9F3->U+96C3, U+2F9F4->U+5DB2, U+2F9F5->U+9723, U+2F9F6->U+29145, U+2F9F7->U+2921A, U+2F9F8->U+4A6E, U+2F9F9->U+4A76, U+2F9FA->U+97E0, U+2F9FB->U+2940A, U+2F9FC->U+4AB2, U+2F9FD->U+29496, U+2F9FE->U+980B, U+2F9FF->U+980B, \
213
+    U+2FA00->U+9829, U+2FA01->U+295B6, U+2FA02->U+98E2, U+2FA03->U+4B33, U+2FA04->U+9929, U+2FA05->U+99A7, U+2FA06->U+99C2, U+2FA07->U+99FE, U+2FA08->U+4BCE, U+2FA09->U+29B30, U+2FA0A->U+9B12, U+2FA0B->U+9C40, U+2FA0C->U+9CFD, U+2FA0D->U+4CCE, U+2FA0E->U+4CED, \
214
+    U+2FA0F->U+9D67, U+2FA10->U+2A0CE, U+2FA11->U+4CF8, U+2FA12->U+2A105, U+2FA13->U+2A20E, U+2FA14->U+2A291, U+2FA15->U+9EBB, U+2FA16->U+4D56, U+2FA17->U+9EF9, U+2FA18->U+9EFE, U+2FA19->U+9F05, U+2FA1A->U+9F0F, U+2FA1B->U+9F16, U+2FA1C->U+9F3B, U+2FA1D->U+2A600, \
215
+    U+2F00->U+4E00, U+2F01->U+4E28, U+2F02->U+4E36, U+2F03->U+4E3F, U+2F04->U+4E59, U+2F05->U+4E85, U+2F06->U+4E8C, U+2F07->U+4EA0, U+2F08->U+4EBA, U+2F09->U+513F, U+2F0A->U+5165, U+2F0B->U+516B, U+2F0C->U+5182, U+2F0D->U+5196, U+2F0E->U+51AB, U+2F0F->U+51E0, \
216
+    U+2F10->U+51F5, U+2F11->U+5200, U+2F12->U+529B, U+2F13->U+52F9, U+2F14->U+5315, U+2F15->U+531A, U+2F16->U+5338, U+2F17->U+5341, U+2F18->U+535C, U+2F19->U+5369, U+2F1A->U+5382, U+2F1B->U+53B6, U+2F1C->U+53C8, U+2F1D->U+53E3, U+2F1E->U+56D7, U+2F1F->U+571F, \
217
+    U+2F20->U+58EB, U+2F21->U+5902, U+2F22->U+590A, U+2F23->U+5915, U+2F24->U+5927, U+2F25->U+5973, U+2F26->U+5B50, U+2F27->U+5B80, U+2F28->U+5BF8, U+2F29->U+5C0F, U+2F2A->U+5C22, U+2F2B->U+5C38, U+2F2C->U+5C6E, U+2F2D->U+5C71, U+2F2E->U+5DDB, U+2F2F->U+5DE5, \
218
+    U+2F30->U+5DF1, U+2F31->U+5DFE, U+2F32->U+5E72, U+2F33->U+5E7A, U+2F34->U+5E7F, U+2F35->U+5EF4, U+2F36->U+5EFE, U+2F37->U+5F0B, U+2F38->U+5F13, U+2F39->U+5F50, U+2F3A->U+5F61, U+2F3B->U+5F73, U+2F3C->U+5FC3, U+2F3D->U+6208, U+2F3E->U+6236, U+2F3F->U+624B, \
219
+    U+2F40->U+652F, U+2F41->U+6534, U+2F42->U+6587, U+2F43->U+6597, U+2F44->U+65A4, U+2F45->U+65B9, U+2F46->U+65E0, U+2F47->U+65E5, U+2F48->U+66F0, U+2F49->U+6708, U+2F4A->U+6728, U+2F4B->U+6B20, U+2F4C->U+6B62, U+2F4D->U+6B79, U+2F4E->U+6BB3, U+2F4F->U+6BCB, \
220
+    U+2F50->U+6BD4, U+2F51->U+6BDB, U+2F52->U+6C0F, U+2F53->U+6C14, U+2F54->U+6C34, U+2F55->U+706B, U+2F56->U+722A, U+2F57->U+7236, U+2F58->U+723B, U+2F59->U+723F, U+2F5A->U+7247, U+2F5B->U+7259, U+2F5C->U+725B, U+2F5D->U+72AC, U+2F5E->U+7384, U+2F5F->U+7389, \
221
+    U+2F60->U+74DC, U+2F61->U+74E6, U+2F62->U+7518, U+2F63->U+751F, U+2F64->U+7528, U+2F65->U+7530, U+2F66->U+758B, U+2F67->U+7592, U+2F68->U+7676, U+2F69->U+767D, U+2F6A->U+76AE, U+2F6B->U+76BF, U+2F6C->U+76EE, U+2F6D->U+77DB, U+2F6E->U+77E2, U+2F6F->U+77F3, \
222
+    U+2F70->U+793A, U+2F71->U+79B8, U+2F72->U+79BE, U+2F73->U+7A74, U+2F74->U+7ACB, U+2F75->U+7AF9, U+2F76->U+7C73, U+2F77->U+7CF8, U+2F78->U+7F36, U+2F79->U+7F51, U+2F7A->U+7F8A, U+2F7B->U+7FBD, U+2F7C->U+8001, U+2F7D->U+800C, U+2F7E->U+8012, U+2F7F->U+8033, \
223
+    U+2F80->U+807F, U+2F81->U+8089, U+2F82->U+81E3, U+2F83->U+81EA, U+2F84->U+81F3, U+2F85->U+81FC, U+2F86->U+820C, U+2F87->U+821B, U+2F88->U+821F, U+2F89->U+826E, U+2F8A->U+8272, U+2F8B->U+8278, U+2F8C->U+864D, U+2F8D->U+866B, U+2F8E->U+8840, U+2F8F->U+884C, \
224
+    U+2F90->U+8863, U+2F91->U+897E, U+2F92->U+898B, U+2F93->U+89D2, U+2F94->U+8A00, U+2F95->U+8C37, U+2F96->U+8C46, U+2F97->U+8C55, U+2F98->U+8C78, U+2F99->U+8C9D, U+2F9A->U+8D64, U+2F9B->U+8D70, U+2F9C->U+8DB3, U+2F9D->U+8EAB, U+2F9E->U+8ECA, U+2F9F->U+8F9B, \
225
+    U+2FA0->U+8FB0, U+2FA1->U+8FB5, U+2FA2->U+9091, U+2FA3->U+9149, U+2FA4->U+91C6, U+2FA5->U+91CC, U+2FA6->U+91D1, U+2FA7->U+9577, U+2FA8->U+9580, U+2FA9->U+961C, U+2FAA->U+96B6, U+2FAB->U+96B9, U+2FAC->U+96E8, U+2FAD->U+9751, U+2FAE->U+975E, U+2FAF->U+9762, \
226
+    U+2FB0->U+9769, U+2FB1->U+97CB, U+2FB2->U+97ED, U+2FB3->U+97F3, U+2FB4->U+9801, U+2FB5->U+98A8, U+2FB6->U+98DB, U+2FB7->U+98DF, U+2FB8->U+9996, U+2FB9->U+9999, U+2FBA->U+99AC, U+2FBB->U+9AA8, U+2FBC->U+9AD8, U+2FBD->U+9ADF, U+2FBE->U+9B25, U+2FBF->U+9B2F, \
227
+    U+2FC0->U+9B32, U+2FC1->U+9B3C, U+2FC2->U+9B5A, U+2FC3->U+9CE5, U+2FC4->U+9E75, U+2FC5->U+9E7F, U+2FC6->U+9EA5, U+2FC7->U+9EBB, U+2FC8->U+9EC3, U+2FC9->U+9ECD, U+2FCA->U+9ED1, U+2FCB->U+9EF9, U+2FCC->U+9EFD, U+2FCD->U+9F0E, U+2FCE->U+9F13, U+2FCF->U+9F20, \
228
+    U+2FD0->U+9F3B, U+2FD1->U+9F4A, U+2FD2->U+9F52, U+2FD3->U+9F8D, U+2FD4->U+9F9C, U+2FD5->U+9FA0, U+3042->U+3041, U+3044->U+3043, U+3046->U+3045, U+3048->U+3047, U+304A->U+3049, U+304C->U+304B, U+304E->U+304D, U+3050->U+304F, U+3052->U+3051, U+3054->U+3053, \
229
+    U+3056->U+3055, U+3058->U+3057, U+305A->U+3059, U+305C->U+305B, U+305E->U+305D, U+3060->U+305F, U+3062->U+3061, U+3064->U+3063, U+3065->U+3063, U+3067->U+3066, U+3069->U+3068, U+3070->U+306F, U+3071->U+306F, U+3073->U+3072, U+3074->U+3072, U+3076->U+3075, \
230
+    U+3077->U+3075, U+3079->U+3078, U+307A->U+3078, U+307C->U+307B, U+307D->U+307B, U+3084->U+3083, U+3086->U+3085, U+3088->U+3087, U+308F->U+308E, U+3094->U+3046, U+3095->U+304B, U+3096->U+3051, U+30A2->U+30A1, U+30A4->U+30A3, U+30A6->U+30A5, U+30A8->U+30A7, \
231
+    U+30AA->U+30A9, U+30AC->U+30AB, U+30AE->U+30AD, U+30B0->U+30AF, U+30B2->U+30B1, U+30B4->U+30B3, U+30B6->U+30B5, U+30B8->U+30B7, U+30BA->U+30B9, U+30BC->U+30BB, U+30BE->U+30BD, U+30C0->U+30BF, U+30C2->U+30C1, U+30C5->U+30C4, U+30C7->U+30C6, U+30C9->U+30C8, \
232
+    U+30D0->U+30CF, U+30D1->U+30CF, U+30D3->U+30D2, U+30D4->U+30D2, U+30D6->U+30D5, U+30D7->U+30D5, U+30D9->U+30D8, U+30DA->U+30D8, U+30DC->U+30DB, U+30DD->U+30DB, U+30E4->U+30E3, U+30E6->U+30E5, U+30E8->U+30E7, U+30EF->U+30EE, U+30F4->U+30A6, U+30AB->U+30F5, \
233
+    U+30B1->U+30F6, U+30F7->U+30EF, U+30F8->U+30F0, U+30F9->U+30F1, U+30FA->U+30F2, U+30AF->U+31F0, U+30B7->U+31F1, U+30B9->U+31F2, U+30C8->U+31F3, U+30CC->U+31F4, U+30CF->U+31F5, U+30D2->U+31F6, U+30D5->U+31F7, U+30D8->U+31F8, U+30DB->U+31F9, U+30E0->U+31FA, \
234
+    U+30E9->U+31FB, U+30EA->U+31FC, U+30EB->U+31FD, U+30EC->U+31FE, U+30ED->U+31FF, U+FF66->U+30F2, U+FF67->U+30A1, U+FF68->U+30A3, U+FF69->U+30A5, U+FF6A->U+30A7, U+FF6B->U+30A9, U+FF6C->U+30E3, U+FF6D->U+30E5, U+FF6E->U+30E7, U+FF6F->U+30C3, U+FF71->U+30A1, \
235
+    U+FF72->U+30A3, U+FF73->U+30A5, U+FF74->U+30A7, U+FF75->U+30A9, U+FF76->U+30AB, U+FF77->U+30AD, U+FF78->U+30AF, U+FF79->U+30B1, U+FF7A->U+30B3, U+FF7B->U+30B5, U+FF7C->U+30B7, U+FF7D->U+30B9, U+FF7E->U+30BB, U+FF7F->U+30BD, U+FF80->U+30BF, U+FF81->U+30C1, \
236
+    U+FF82->U+30C3, U+FF83->U+30C6, U+FF84->U+30C8, U+FF85->U+30CA, U+FF86->U+30CB, U+FF87->U+30CC, U+FF88->U+30CD, U+FF89->U+30CE, U+FF8A->U+30CF, U+FF8B->U+30D2, U+FF8C->U+30D5, U+FF8D->U+30D8, U+FF8E->U+30DB, U+FF8F->U+30DE, U+FF90->U+30DF, U+FF91->U+30E0, \
237
+    U+FF92->U+30E1, U+FF93->U+30E2, U+FF94->U+30E3, U+FF95->U+30E5, U+FF96->U+30E7, U+FF97->U+30E9, U+FF98->U+30EA, U+FF99->U+30EB, U+FF9A->U+30EC, U+FF9B->U+30ED, U+FF9C->U+30EF, U+FF9D->U+30F3, U+FFA0->U+3164, U+FFA1->U+3131, U+FFA2->U+3132, U+FFA3->U+3133, \
238
+    U+FFA4->U+3134, U+FFA5->U+3135, U+FFA6->U+3136, U+FFA7->U+3137, U+FFA8->U+3138, U+FFA9->U+3139, U+FFAA->U+313A, U+FFAB->U+313B, U+FFAC->U+313C, U+FFAD->U+313D, U+FFAE->U+313E, U+FFAF->U+313F, U+FFB0->U+3140, U+FFB1->U+3141, U+FFB2->U+3142, U+FFB3->U+3143, \
239
+    U+FFB4->U+3144, U+FFB5->U+3145, U+FFB6->U+3146, U+FFB7->U+3147, U+FFB8->U+3148, U+FFB9->U+3149, U+FFBA->U+314A, U+FFBB->U+314B, U+FFBC->U+314C, U+FFBD->U+314D, U+FFBE->U+314E, U+FFC2->U+314F, U+FFC3->U+3150, U+FFC4->U+3151, U+FFC5->U+3152, U+FFC6->U+3153, \
240
+    U+FFC7->U+3154, U+FFCA->U+3155, U+FFCB->U+3156, U+FFCC->U+3157, U+FFCD->U+3158, U+FFCE->U+3159, U+FFCF->U+315A, U+FFD2->U+315B, U+FFD3->U+315C, U+FFD4->U+315D, U+FFD5->U+315E, U+FFD6->U+315F, U+FFD7->U+3160, U+FFDA->U+3161, U+FFDB->U+3162, U+FFDC->U+3163, \
241
+    U+3131->U+1100, U+3132->U+1101, U+3133->U+11AA, U+3134->U+1102, U+3135->U+11AC, U+3136->U+11AD, U+3137->U+1103, U+3138->U+1104, U+3139->U+1105, U+313A->U+11B0, U+313B->U+11B1, U+313C->U+11B2, U+313D->U+11B3, U+313E->U+11B4, U+313F->U+11B5, U+3140->U+111A, \
242
+    U+3141->U+1106, U+3142->U+1107, U+3143->U+1108, U+3144->U+1121, U+3145->U+1109, U+3146->U+110A, U+3147->U+110B, U+3148->U+110C, U+3149->U+110D, U+314A->U+110E, U+314B->U+110F, U+314C->U+1110, U+314D->U+1111, U+314E->U+1112, U+314F->U+1161, U+3150->U+1162, \
243
+    U+3151->U+1163, U+3152->U+1164, U+3153->U+1165, U+3154->U+1166, U+3155->U+1167, U+3156->U+1168, U+3157->U+1169, U+3158->U+116A, U+3159->U+116B, U+315A->U+116C, U+315B->U+116D, U+315C->U+116E, U+315D->U+116F, U+315E->U+1170, U+315F->U+1171, U+3160->U+1172, \
244
+    U+3161->U+1173, U+3162->U+1174, U+3163->U+1175, U+3165->U+1114, U+3166->U+1115, U+3167->U+11C7, U+3168->U+11C8, U+3169->U+11CC, U+316A->U+11CE, U+316B->U+11D3, U+316C->U+11D7, U+316D->U+11D9, U+316E->U+111C, U+316F->U+11DD, U+3170->U+11DF, U+3171->U+111D, \
245
+    U+3172->U+111E, U+3173->U+1120, U+3174->U+1122, U+3175->U+1123, U+3176->U+1127, U+3177->U+1129, U+3178->U+112B, U+3179->U+112C, U+317A->U+112D, U+317B->U+112E, U+317C->U+112F, U+317D->U+1132, U+317E->U+1136, U+317F->U+1140, U+3180->U+1147, U+3181->U+114C, \
246
+    U+3182->U+11F1, U+3183->U+11F2, U+3184->U+1157, U+3185->U+1158, U+3186->U+1159, U+3187->U+1184, U+3188->U+1185, U+3189->U+1188, U+318A->U+1191, U+318B->U+1192, U+318C->U+1194, U+318D->U+119E, U+318E->U+11A1, U+A490->U+A408, U+A491->U+A1B9, U+4E00..U+9FBB, \
247
+    U+3400..U+4DB5, U+20000..U+2A6D6, U+FA0E, U+FA0F, U+FA11, U+FA13, U+FA14, U+FA1F, U+FA21, U+FA23, U+FA24, U+FA27, U+FA28, U+FA29, U+3105..U+312C, U+31A0..U+31B7, U+3041, U+3043, U+3045, U+3047, U+3049, U+304B, U+304D, U+304F, U+3051, U+3053, U+3055, U+3057, \
248
+    U+3059, U+305B, U+305D, U+305F, U+3061, U+3063, U+3066, U+3068, U+306A..U+306F, U+3072, U+3075, U+3078, U+307B, U+307E..U+3083, U+3085, U+3087, U+3089..U+308E, U+3090..U+3093, U+30A1, U+30A3, U+30A5, U+30A7, U+30A9, U+30AD, U+30AF, U+30B3, U+30B5, U+30BB, \
249
+    U+30BD, U+30BF, U+30C1, U+30C3, U+30C4, U+30C6, U+30CA, U+30CB, U+30CD, U+30CE, U+30DE, U+30DF, U+30E1, U+30E2, U+30E3, U+30E5, U+30E7, U+30EE, U+30F0..U+30F3, U+30F5, U+30F6, U+31F0, U+31F1, U+31F2, U+31F3, U+31F4, U+31F5, U+31F6, U+31F7, U+31F8, U+31F9, \
250
+    U+31FA, U+31FB, U+31FC, U+31FD, U+31FE, U+31FF, U+AC00..U+D7A3, U+1100..U+1159, U+1161..U+11A2, U+11A8..U+11F9, U+A000..U+A48C, U+A492..U+A4C6, U+2C80->U+2C81, U+2C81, U+2C82->U+2C83, U+2C83, U+2C84->U+2C85, U+2C85, U+2C86->U+2C87, U+2C87, U+2C88->U+2C89, \
251
+    U+2C89, U+2C8A->U+2C8B, U+2C8B, U+2C8C->U+2C8D, U+2C8D, U+2C8E->U+2C8F, U+2C8F, U+2C90->U+2C91, U+2C91, U+2C92->U+2C93, U+2C93, U+2C94->U+2C95, U+2C95, U+2C96->U+2C97, U+2C97, U+2C98->U+2C99, U+2C99, U+2C9A->U+2C9B, U+2C9B, U+2C9C->U+2C9D, U+2C9D, U+2C9E->U+2C9F, \
252
+    U+2C9F, U+2CA0->U+2CA1, U+2CA1, U+2CA2->U+2CA3, U+2CA3, U+2CA4->U+2CA5, U+2CA5, U+2CA6->U+2CA7, U+2CA7, U+2CA8->U+2CA9, U+2CA9, U+2CAA->U+2CAB, U+2CAB, U+2CAC->U+2CAD, U+2CAD, U+2CAE->U+2CAF, U+2CAF, U+2CB0->U+2CB1, U+2CB1, U+2CB2->U+2CB3, U+2CB3, U+2CB4->U+2CB5, \
253
+    U+2CB5, U+2CB6->U+2CB7, U+2CB7, U+2CB8->U+2CB9, U+2CB9, U+2CBA->U+2CBB, U+2CBB, U+2CBC->U+2CBD, U+2CBD, U+2CBE->U+2CBF, U+2CBF, U+2CC0->U+2CC1, U+2CC1, U+2CC2->U+2CC3, U+2CC3, U+2CC4->U+2CC5, U+2CC5, U+2CC6->U+2CC7, U+2CC7, U+2CC8->U+2CC9, U+2CC9, U+2CCA->U+2CCB, \
254
+    U+2CCB, U+2CCC->U+2CCD, U+2CCD, U+2CCE->U+2CCF, U+2CCF, U+2CD0->U+2CD1, U+2CD1, U+2CD2->U+2CD3, U+2CD3, U+2CD4->U+2CD5, U+2CD5, U+2CD6->U+2CD7, U+2CD7, U+2CD8->U+2CD9, U+2CD9, U+2CDA->U+2CDB, U+2CDB, U+2CDC->U+2CDD, U+2CDD, U+2CDE->U+2CDF, U+2CDF, U+2CE0->U+2CE1, \
255
+    U+2CE1, U+2CE2->U+2CE3, U+2CE3, U+0400->U+0435, U+0401->U+0435, U+0402->U+0452, U+0452, U+0403->U+0433, U+0404->U+0454, U+0454, U+0405->U+0455, U+0455, U+0406->U+0456, U+0407->U+0456, U+0457->U+0456, U+0456, U+0408..U+040B->U+0458..U+045B, U+0458..U+045B, \
256
+    U+040C->U+043A, U+040D->U+0438, U+040E->U+0443, U+040F->U+045F, U+045F, U+0450->U+0435, U+0451->U+0435, U+0453->U+0433, U+045C->U+043A, U+045D->U+0438, U+045E->U+0443, U+0460->U+0461, U+0461, U+0462->U+0463, U+0463, U+0464->U+0465, U+0465, U+0466->U+0467, \
257
+    U+0467, U+0468->U+0469, U+0469, U+046A->U+046B, U+046B, U+046C->U+046D, U+046D, U+046E->U+046F, U+046F, U+0470->U+0471, U+0471, U+0472->U+0473, U+0473, U+0474->U+0475, U+0476->U+0475, U+0477->U+0475, U+0475, U+0478->U+0479, U+0479, U+047A->U+047B, U+047B, \
258
+    U+047C->U+047D, U+047D, U+047E->U+047F, U+047F, U+0480->U+0481, U+0481, U+048A->U+0438, U+048B->U+0438, U+048C->U+044C, U+048D->U+044C, U+048E->U+0440, U+048F->U+0440, U+0490->U+0433, U+0491->U+0433, U+0490->U+0433, U+0491->U+0433, U+0492->U+0433, U+0493->U+0433, \
259
+    U+0494->U+0433, U+0495->U+0433, U+0496->U+0436, U+0497->U+0436, U+0498->U+0437, U+0499->U+0437, U+049A->U+043A, U+049B->U+043A, U+049C->U+043A, U+049D->U+043A, U+049E->U+043A, U+049F->U+043A, U+04A0->U+043A, U+04A1->U+043A, U+04A2->U+043D, U+04A3->U+043D, \
260
+    U+04A4->U+043D, U+04A5->U+043D, U+04A6->U+043F, U+04A7->U+043F, U+04A8->U+04A9, U+04A9, U+04AA->U+0441, U+04AB->U+0441, U+04AC->U+0442, U+04AD->U+0442, U+04AE->U+0443, U+04AF->U+0443, U+04B0->U+0443, U+04B1->U+0443, U+04B2->U+0445, U+04B3->U+0445, U+04B4->U+04B5, \
261
+    U+04B5, U+04B6->U+0447, U+04B7->U+0447, U+04B8->U+0447, U+04B9->U+0447, U+04BA->U+04BB, U+04BB, U+04BC->U+04BD, U+04BE->U+04BD, U+04BF->U+04BD, U+04BD, U+04C0->U+04CF, U+04CF, U+04C1->U+0436, U+04C2->U+0436, U+04C3->U+043A, U+04C4->U+043A, U+04C5->U+043B, \
262
+    U+04C6->U+043B, U+04C7->U+043D, U+04C8->U+043D, U+04C9->U+043D, U+04CA->U+043D, U+04CB->U+0447, U+04CC->U+0447, U+04CD->U+043C, U+04CE->U+043C, U+04D0->U+0430, U+04D1->U+0430, U+04D2->U+0430, U+04D3->U+0430, U+04D4->U+00E6, U+04D5->U+00E6, U+04D6->U+0435, \
263
+    U+04D7->U+0435, U+04D8->U+04D9, U+04DA->U+04D9, U+04DB->U+04D9, U+04D9, U+04DC->U+0436, U+04DD->U+0436, U+04DE->U+0437, U+04DF->U+0437, U+04E0->U+04E1, U+04E1, U+04E2->U+0438, U+04E3->U+0438, U+04E4->U+0438, U+04E5->U+0438, U+04E6->U+043E, U+04E7->U+043E, \
264
+    U+04E8->U+043E, U+04E9->U+043E, U+04EA->U+043E, U+04EB->U+043E, U+04EC->U+044D, U+04ED->U+044D, U+04EE->U+0443, U+04EF->U+0443, U+04F0->U+0443, U+04F1->U+0443, U+04F2->U+0443, U+04F3->U+0443, U+04F4->U+0447, U+04F5->U+0447, U+04F6->U+0433, U+04F7->U+0433, \
265
+    U+04F8->U+044B, U+04F9->U+044B, U+04FA->U+0433, U+04FB->U+0433, U+04FC->U+0445, U+04FD->U+0445, U+04FE->U+0445, U+04FF->U+0445, U+0410..U+0418->U+0430..U+0438, U+0419->U+0438, U+0430..U+0438, U+041A..U+042F->U+043A..U+044F, U+043A..U+044F, U+0929->U+0928, \
266
+    U+0931->U+0930, U+0934->U+0933, U+0958->U+0915, U+0959->U+0916, U+095A->U+0917, U+095B->U+091C, U+095C->U+0921, U+095D->U+0922, U+095E->U+092B, U+095F->U+092F, U+0904..U+0928, U+092A..U+0930, U+0932, U+0933, U+0935..U+0939, U+0960, U+0961, U+0966..U+096F, \
267
+    U+097B..U+097F, U+10FC->U+10DC, U+10D0..U+10FA, U+10A0..U+10C5->U+2D00..U+2D25, U+2D00..U+2D25, U+0386->U+03B1, U+0388->U+03B5, U+0389->U+03B7, U+038A->U+03B9, U+038C->U+03BF, U+038E->U+03C5, U+038F->U+03C9, U+0390->U+03B9, U+03AA->U+03B9, U+03AB->U+03C5, \
268
+    U+03AC->U+03B1, U+03AD->U+03B5, U+03AE->U+03B7, U+03AF->U+03B9, U+03B0->U+03C5, U+03CA->U+03B9, U+03CB->U+03C5, U+03CC->U+03BF, U+03CD->U+03C5, U+03CE->U+03C9, U+03D0->U+03B2, U+03D1->U+03B8, U+03D2->U+03C5, U+03D3->U+03C5, U+03D4->U+03C5, U+03D5->U+03C6, \
269
+    U+03D6->U+03C0, U+03D8->U+03D9, U+03DA->U+03DB, U+03DC->U+03DD, U+03DE->U+03DF, U+03E0->U+03E1, U+03E2->U+03E3, U+03E4->U+03E5, U+03E6->U+03E7, U+03E8->U+03E9, U+03EA->U+03EB, U+03EC->U+03ED, U+03EE->U+03EF, U+03F0->U+03BA, U+03F1->U+03C1, U+03F2->U+03C3, \
270
+    U+03F4->U+03B8, U+03F5->U+03B5, U+03F6->U+03B5, U+03F7->U+03F8, U+03F9->U+03C3, U+03FA->U+03FB, U+1F00->U+03B1, U+1F01->U+03B1, U+1F02->U+03B1, U+1F03->U+03B1, U+1F04->U+03B1, U+1F05->U+03B1, U+1F06->U+03B1, U+1F07->U+03B1, U+1F08->U+03B1, U+1F09->U+03B1, \
271
+    U+1F0A->U+03B1, U+1F0B->U+03B1, U+1F0C->U+03B1, U+1F0D->U+03B1, U+1F0E->U+03B1, U+1F0F->U+03B1, U+1F10->U+03B5, U+1F11->U+03B5, U+1F12->U+03B5, U+1F13->U+03B5, U+1F14->U+03B5, U+1F15->U+03B5, U+1F18->U+03B5, U+1F19->U+03B5, U+1F1A->U+03B5, U+1F1B->U+03B5, \
272
+    U+1F1C->U+03B5, U+1F1D->U+03B5, U+1F20->U+03B7, U+1F21->U+03B7, U+1F22->U+03B7, U+1F23->U+03B7, U+1F24->U+03B7, U+1F25->U+03B7, U+1F26->U+03B7, U+1F27->U+03B7, U+1F28->U+03B7, U+1F29->U+03B7, U+1F2A->U+03B7, U+1F2B->U+03B7, U+1F2C->U+03B7, U+1F2D->U+03B7, \
273
+    U+1F2E->U+03B7, U+1F2F->U+03B7, U+1F30->U+03B9, U+1F31->U+03B9, U+1F32->U+03B9, U+1F33->U+03B9, U+1F34->U+03B9, U+1F35->U+03B9, U+1F36->U+03B9, U+1F37->U+03B9, U+1F38->U+03B9, U+1F39->U+03B9, U+1F3A->U+03B9, U+1F3B->U+03B9, U+1F3C->U+03B9, U+1F3D->U+03B9, \
274
+    U+1F3E->U+03B9, U+1F3F->U+03B9, U+1F40->U+03BF, U+1F41->U+03BF, U+1F42->U+03BF, U+1F43->U+03BF, U+1F44->U+03BF, U+1F45->U+03BF, U+1F48->U+03BF, U+1F49->U+03BF, U+1F4A->U+03BF, U+1F4B->U+03BF, U+1F4C->U+03BF, U+1F4D->U+03BF, U+1F50->U+03C5, U+1F51->U+03C5, \
275
+    U+1F52->U+03C5, U+1F53->U+03C5, U+1F54->U+03C5, U+1F55->U+03C5, U+1F56->U+03C5, U+1F57->U+03C5, U+1F59->U+03C5, U+1F5B->U+03C5, U+1F5D->U+03C5, U+1F5F->U+03C5, U+1F60->U+03C9, U+1F61->U+03C9, U+1F62->U+03C9, U+1F63->U+03C9, U+1F64->U+03C9, U+1F65->U+03C9, \
276
+    U+1F66->U+03C9, U+1F67->U+03C9, U+1F68->U+03C9, U+1F69->U+03C9, U+1F6A->U+03C9, U+1F6B->U+03C9, U+1F6C->U+03C9, U+1F6D->U+03C9, U+1F6E->U+03C9, U+1F6F->U+03C9, U+1F70->U+03B1, U+1F71->U+03B1, U+1F72->U+03B5, U+1F73->U+03B5, U+1F74->U+03B7, U+1F75->U+03B7, \
277
+    U+1F76->U+03B9, U+1F77->U+03B9, U+1F78->U+03BF, U+1F79->U+03BF, U+1F7A->U+03C5, U+1F7B->U+03C5, U+1F7C->U+03C9, U+1F7D->U+03C9, U+1F80->U+03B1, U+1F81->U+03B1, U+1F82->U+03B1, U+1F83->U+03B1, U+1F84->U+03B1, U+1F85->U+03B1, U+1F86->U+03B1, U+1F87->U+03B1, \
278
+    U+1F88->U+03B1, U+1F89->U+03B1, U+1F8A->U+03B1, U+1F8B->U+03B1, U+1F8C->U+03B1, U+1F8D->U+03B1, U+1F8E->U+03B1, U+1F8F->U+03B1, U+1F90->U+03B7, U+1F91->U+03B7, U+1F92->U+03B7, U+1F93->U+03B7, U+1F94->U+03B7, U+1F95->U+03B7, U+1F96->U+03B7, U+1F97->U+03B7, \
279
+    U+1F98->U+03B7, U+1F99->U+03B7, U+1F9A->U+03B7, U+1F9B->U+03B7, U+1F9C->U+03B7, U+1F9D->U+03B7, U+1F9E->U+03B7, U+1F9F->U+03B7, U+1FA0->U+03C9, U+1FA1->U+03C9, U+1FA2->U+03C9, U+1FA3->U+03C9, U+1FA4->U+03C9, U+1FA5->U+03C9, U+1FA6->U+03C9, U+1FA7->U+03C9, \
280
+    U+1FA8->U+03C9, U+1FA9->U+03C9, U+1FAA->U+03C9, U+1FAB->U+03C9, U+1FAC->U+03C9, U+1FAD->U+03C9, U+1FAE->U+03C9, U+1FAF->U+03C9, U+1FB0->U+03B1, U+1FB1->U+03B1, U+1FB2->U+03B1, U+1FB3->U+03B1, U+1FB4->U+03B1, U+1FB6->U+03B1, U+1FB7->U+03B1, U+1FB8->U+03B1, \
281
+    U+1FB9->U+03B1, U+1FBA->U+03B1, U+1FBB->U+03B1, U+1FBC->U+03B1, U+1FC2->U+03B7, U+1FC3->U+03B7, U+1FC4->U+03B7, U+1FC6->U+03B7, U+1FC7->U+03B7, U+1FC8->U+03B5, U+1FC9->U+03B5, U+1FCA->U+03B7, U+1FCB->U+03B7, U+1FCC->U+03B7, U+1FD0->U+03B9, U+1FD1->U+03B9, \
282
+    U+1FD2->U+03B9, U+1FD3->U+03B9, U+1FD6->U+03B9, U+1FD7->U+03B9, U+1FD8->U+03B9, U+1FD9->U+03B9, U+1FDA->U+03B9, U+1FDB->U+03B9, U+1FE0->U+03C5, U+1FE1->U+03C5, U+1FE2->U+03C5, U+1FE3->U+03C5, U+1FE4->U+03C1, U+1FE5->U+03C1, U+1FE6->U+03C5, U+1FE7->U+03C5, \
283
+    U+1FE8->U+03C5, U+1FE9->U+03C5, U+1FEA->U+03C5, U+1FEB->U+03C5, U+1FEC->U+03C1, U+1FF2->U+03C9, U+1FF3->U+03C9, U+1FF4->U+03C9, U+1FF6->U+03C9, U+1FF7->U+03C9, U+1FF8->U+03BF, U+1FF9->U+03BF, U+1FFA->U+03C9, U+1FFB->U+03C9, U+1FFC->U+03C9, U+0391..U+03A1->U+03B1..U+03C1, \
284
+    U+03B1..U+03C1, U+03A3..U+03A9->U+03C3..U+03C9, U+03C3..U+03C9, U+03C2, U+03D9, U+03DB, U+03DD, U+03DF, U+03E1, U+03E3, U+03E5, U+03E7, U+03E9, U+03EB, U+03ED, U+03EF, U+03F3, U+03F8, U+03FB, U+0A85..U+0A8C, U+0A8F, U+0A90, U+0A93..U+0AB0, U+0AB2, U+0AB3, \
285
+    U+0AB5..U+0AB9, U+0AE0, U+0AE1, U+0AE6..U+0AEF, U+0A33->U+0A32, U+0A36->U+0A38, U+0A59->U+0A16, U+0A5A->U+0A17, U+0A5B->U+0A1C, U+0A5E->U+0A2B, U+0A05..U+0A0A, U+0A0F, U+0A10, U+0A13..U+0A28, U+0A2A..U+0A30, U+0A32, U+0A35, U+0A38, U+0A39, U+0A5C, U+0A66..U+0A6F, \
286
+    U+FB1D->U+05D9, U+FB1F->U+05F2, U+FB20->U+05E2, U+FB21->U+05D0, U+FB22->U+05D3, U+FB23->U+05D4, U+FB24->U+05DB, U+FB25->U+05DC, U+FB26->U+05DD, U+FB27->U+05E8, U+FB28->U+05EA, U+FB2A->U+05E9, U+FB2B->U+05E9, U+FB2C->U+05E9, U+FB2D->U+05E9, U+FB2E->U+05D0, \
287
+    U+FB2F->U+05D0, U+FB30->U+05D0, U+FB31->U+05D1, U+FB32->U+05D2, U+FB33->U+05D3, U+FB34->U+05D4, U+FB35->U+05D5, U+FB36->U+05D6, U+FB38->U+05D8, U+FB39->U+05D9, U+FB3A->U+05DA, U+FB3B->U+05DB, U+FB3C->U+05DC, U+FB3E->U+05DE, U+FB40->U+05E0, U+FB41->U+05E1, \
288
+    U+FB43->U+05E3, U+FB44->U+05E4, U+FB46->U+05E6, U+FB47->U+05E7, U+FB48->U+05E8, U+FB49->U+05E9, U+FB4A->U+05EA, U+FB4B->U+05D5, U+FB4C->U+05D1, U+FB4D->U+05DB, U+FB4E->U+05E4, U+FB4F->U+05D0, U+05D0..U+05F2, U+0C85..U+0C8C, U+0C8E..U+0C90, U+0C92..U+0CA8, \
289
+    U+0CAA..U+0CB3, U+0CB5..U+0CB9, U+0CE0, U+0CE1, U+0CE6..U+0CEF, U+1900..U+191C, U+1930..U+1938, U+1946..U+194F, U+0D05..U+0D0C, U+0D0E..U+0D10, U+0D12..U+0D28, U+0D2A..U+0D39, U+0D60, U+0D61, U+0D66..U+0D6F, U+0B94->U+0B92, U+0B85..U+0B8A, U+0B8E..U+0B90, \
290
+    U+0B92, U+0B93, U+0B95, U+0B99, U+0B9A, U+0B9C, U+0B9E, U+0B9F, U+0BA3, U+0BA4, U+0BA8..U+0BAA, U+0BAE..U+0BB9, U+0BE6..U+0BEF, U+0E01..U+0E30, U+0E32, U+0E33, U+0E40..U+0E46, U+0E50..U+0E5B, U+FF10..U+FF19->0..9, U+FF21..U+FF3A->a..z, U+FF41..U+FF5A->a..z, \
291
+    U+3040..U+309F, U+30A0..U+30FF, \
292
+    0..9, A..Z->a..z, a..z, _
293
+
294
+    blend_chars = !, ", U+23, $, %, &, ', (, ), *, +, U+2C, -, ., /, :, U+3B, <, =, >, ?, @, U+5B, U+5C, U+5D, ^, U+60, U+7C, U+7E, U+A1..U+BF
295
+    blend_mode = trim_none, trim_head, trim_tail, trim_both
296
+}
297
+
298
+source delta : torrents_base {
299
+    sql_query = SELECT *, Year AS yearfulltext, '_all' AS fake FROM sphinx_delta WHERE Size > 0;
300
+    sql_query_killlist = SELECT ID FROM sphinx_delta
301
+}
302
+
303
+index delta : torrents {
304
+    source = delta
305
+    path = /var/lib/sphinxsearch/delta
306
+}
307
+
308
+source requests_base : connect {
309
+    sql_attr_uint = UserID
310
+    sql_attr_uint = TimeAdded
311
+    sql_attr_uint = LastVote
312
+    sql_attr_uint = CategoryID
313
+    sql_attr_uint = FillerID
314
+    sql_attr_uint = TorrentID
315
+    sql_attr_uint = TimeFilled
316
+    sql_attr_uint = Visible
317
+    sql_attr_uint = Votes
318
+    sql_attr_uint = Bounty
319
+}
320
+
321
+source requests : requests_base {
322
+    sql_query_pre = TRUNCATE TABLE sphinx_requests
323
+    sql_query_pre = SET group_concat_max_len = 10140
324
+    sql_query_pre = SET @starttime = NOW()
325
+    sql_query_pre = REPLACE INTO sphinx_index_last_pos VALUES ('requests', UNIX_TIMESTAMP(@starttime))
326
+
327
+    sql_query_pre = INSERT INTO sphinx_requests ( \
328
+                ID, UserID, TimeAdded, LastVote, CategoryID, Title, \
329
+                TitleJP, CatalogueNumber, DLSiteID, FillerID, \
330
+                TorrentID, TimeFilled, Visible, Votes, Bounty ) \
331
+            SELECT \
332
+                r.ID, r.UserID, UNIX_TIMESTAMP(TimeAdded), \
333
+                UNIX_TIMESTAMP(LastVote), CategoryID, Title, \
334
+                TitleJP, CatalogueNumber, DLSiteID, \
335
+                FillerID, TorrentID, \
336
+                UNIX_TIMESTAMP(TimeFilled), Visible, \
337
+                COUNT(rv.RequestID), SUM(rv.Bounty) >> 10 \
338
+            FROM requests AS r \
339
+                JOIN requests_votes AS rv ON rv.RequestID = r.ID \
340
+            GROUP BY rv.RequestID
341
+
342
+    sql_query_pre = INSERT INTO sphinx_requests ( \
343
+                ID, ArtistList ) \
344
+            SELECT \
345
+                RequestID, \
346
+                GROUP_CONCAT(ag.Name SEPARATOR ' ') \
347
+            FROM requests_artists AS ra \
348
+                JOIN artists_group AS ag ON ag.ArtistID = ra.ArtistID \
349
+                JOIN requests AS r ON r.ID = ra.RequestID \
350
+            WHERE TimeAdded <= @starttime \
351
+            GROUP BY r.ID \
352
+            ON DUPLICATE KEY UPDATE ArtistList = VALUES(ArtistList)
353
+
354
+    sql_query = SELECT ID, UserID, TimeAdded, LastVote, CategoryID, Title, \
355
+                TitleJP, ArtistList, CatalogueNumber, DLSiteID, FillerID, \
356
+                TorrentID, TimeFilled, Visible, Votes, Bounty \
357
+            FROM sphinx_requests
358
+
359
+    sql_joined_field = taglist from query; \
360
+        SELECT rt.RequestID, REPLACE(t.Name, '.', '_') \
361
+        FROM requests_tags AS rt \
362
+            JOIN tags AS t ON TagID = ID \
363
+        ORDER BY requestid ASC;
364
+
365
+    sql_attr_multi = uint Voter from query; \
366
+        SELECT RequestID AS ID, UserID FROM requests_votes
367
+
368
+    sql_attr_multi = uint Bookmarker from query; \
369
+        SELECT RequestID AS ID, UserID FROM bookmarks_requests
370
+
371
+    sql_query_post_index = DELETE FROM sphinx_requests_delta WHERE TimeAdded <= \
372
+        (SELECT ID FROM sphinx_index_last_pos WHERE type = 'requests')
373
+}
374
+
375
+source requests_delta : requests_base {
376
+    sql_query = SELECT ID, UserID, TimeAdded, LastVote, CategoryID, Title, TitleJP, TagList, \
377
+                ArtistList, CatalogueNumber, DLSiteID, FillerID, \
378
+                TorrentID, TimeFilled, Visible, Votes, Bounty \
379
+            FROM sphinx_requests_delta
380
+
381
+    sql_query_killlist = SELECT ID FROM sphinx_requests_delta
382
+
383
+    sql_attr_multi = uint Voter from query; \
384
+        SELECT v.RequestID, v.UserID FROM requests_votes AS v \
385
+        JOIN sphinx_requests_delta AS d ON d.ID = v.RequestID
386
+
387
+    sql_attr_multi = uint Bookmarker from query; \
388
+        SELECT b.RequestID, b.UserID FROM bookmarks_requests AS b \
389
+        JOIN sphinx_requests_delta AS d ON d.ID = b.RequestID
390
+}
391
+
392
+index requests : torrents {
393
+    source = requests
394
+    path = /var/lib/sphinxsearch/requests
395
+    min_infix_len = 3
396
+}
397
+
398
+index requests_delta : requests {
399
+    source = requests_delta
400
+    path = /var/lib/sphinxsearch/requests_delta
401
+}
402
+
403
+source log : connect {
404
+    sql_attr_uint = Time
405
+    sql_query = SELECT ID, UNIX_TIMESTAMP(Time) AS Time, Message FROM log
406
+    sql_query_post_index = REPLACE INTO sphinx_index_last_pos VALUES ('log', $maxid)
407
+}
408
+
409
+source log_delta : log {
410
+    sql_query_pre = SELECT ID FROM sphinx_index_last_pos WHERE type = 'log' INTO @lastid
411
+    sql_query = SELECT ID, UNIX_TIMESTAMP(Time) AS Time, Message FROM log WHERE ID > @lastid
412
+    sql_query_post_index = SET @nothing = 0
413
+}
414
+
415
+index log : torrents {
416
+    source = log
417
+    path = /var/lib/sphinxsearch/log
418
+    min_word_len = 1
419
+    min_infix_len = 0
420
+}
421
+
422
+index log_delta : log {
423
+    source = log_delta
424
+    path = /var/lib/sphinxsearch/log_delta
425
+}
426
+
427
+indexer {
428
+    mem_limit = 64M
429
+}
430
+
431
+searchd {
432
+    listen = localhost:9312
433
+    listen = localhost:9306:mysql41
434
+    log = /var/log/searchd/searchd.log
435
+    query_log = /var/log/searchd/query.log
436
+    pid_file = /var/log/searchd/searchd.pid
437
+    mva_updates_pool = 16M
438
+}

Loading…
Cancel
Save