recycleactor commited on
Commit
c091d8d
·
verified ·
1 Parent(s): 061e3b2

Upload 9 files

Browse files
Files changed (9) hide show
  1. Cargo.lock +1647 -0
  2. Cargo.toml +24 -0
  3. Dockerfile +24 -0
  4. Procfile +1 -0
  5. dockerignore +1 -0
  6. fly.toml +38 -0
  7. gitignore +12 -0
  8. src/api.rs +169 -0
  9. src/main.rs +451 -0
Cargo.lock ADDED
@@ -0,0 +1,1647 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 3
4
+
5
+ [[package]]
6
+ name = "addr2line"
7
+ version = "0.21.0"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
10
+ dependencies = [
11
+ "gimli",
12
+ ]
13
+
14
+ [[package]]
15
+ name = "adler"
16
+ version = "1.0.2"
17
+ source = "registry+https://github.com/rust-lang/crates.io-index"
18
+ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
19
+
20
+ [[package]]
21
+ name = "alloc-no-stdlib"
22
+ version = "2.0.3"
23
+ source = "registry+https://github.com/rust-lang/crates.io-index"
24
+ checksum = "35ef4730490ad1c4eae5c4325b2a95f521d023e5c885853ff7aca0a6a1631db3"
25
+
26
+ [[package]]
27
+ name = "alloc-stdlib"
28
+ version = "0.2.1"
29
+ source = "registry+https://github.com/rust-lang/crates.io-index"
30
+ checksum = "697ed7edc0f1711de49ce108c541623a0af97c6c60b2f6e2b65229847ac843c2"
31
+ dependencies = [
32
+ "alloc-no-stdlib",
33
+ ]
34
+
35
+ [[package]]
36
+ name = "ansi_term"
37
+ version = "0.12.1"
38
+ source = "registry+https://github.com/rust-lang/crates.io-index"
39
+ checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
40
+ dependencies = [
41
+ "winapi",
42
+ ]
43
+
44
+ [[package]]
45
+ name = "async-compression"
46
+ version = "0.3.8"
47
+ source = "registry+https://github.com/rust-lang/crates.io-index"
48
+ checksum = "5443ccbb270374a2b1055fc72da40e1f237809cd6bb0e97e66d264cd138473a6"
49
+ dependencies = [
50
+ "flate2",
51
+ "futures-core",
52
+ "memchr",
53
+ "pin-project-lite",
54
+ "tokio",
55
+ ]
56
+
57
+ [[package]]
58
+ name = "async-compression"
59
+ version = "0.4.5"
60
+ source = "registry+https://github.com/rust-lang/crates.io-index"
61
+ checksum = "bc2d0cfb2a7388d34f590e76686704c494ed7aaceed62ee1ba35cbf363abc2a5"
62
+ dependencies = [
63
+ "brotli",
64
+ "flate2",
65
+ "futures-core",
66
+ "memchr",
67
+ "pin-project-lite",
68
+ "tokio",
69
+ ]
70
+
71
+ [[package]]
72
+ name = "async-trait"
73
+ version = "0.1.77"
74
+ source = "registry+https://github.com/rust-lang/crates.io-index"
75
+ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9"
76
+ dependencies = [
77
+ "proc-macro2",
78
+ "quote",
79
+ "syn 2.0.48",
80
+ ]
81
+
82
+ [[package]]
83
+ name = "autocfg"
84
+ version = "1.1.0"
85
+ source = "registry+https://github.com/rust-lang/crates.io-index"
86
+ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
87
+
88
+ [[package]]
89
+ name = "axum"
90
+ version = "0.7.3"
91
+ source = "registry+https://github.com/rust-lang/crates.io-index"
92
+ checksum = "d09dbe0e490df5da9d69b36dca48a76635288a82f92eca90024883a56202026d"
93
+ dependencies = [
94
+ "async-trait",
95
+ "axum-core",
96
+ "bytes",
97
+ "futures-util",
98
+ "http 1.0.0",
99
+ "http-body 1.0.0",
100
+ "http-body-util",
101
+ "hyper 1.1.0",
102
+ "hyper-util",
103
+ "itoa 1.0.10",
104
+ "matchit",
105
+ "memchr",
106
+ "mime",
107
+ "percent-encoding",
108
+ "pin-project-lite",
109
+ "rustversion",
110
+ "serde",
111
+ "serde_json",
112
+ "serde_path_to_error",
113
+ "serde_urlencoded",
114
+ "sync_wrapper",
115
+ "tokio",
116
+ "tower",
117
+ "tower-layer",
118
+ "tower-service",
119
+ "tracing",
120
+ ]
121
+
122
+ [[package]]
123
+ name = "axum-core"
124
+ version = "0.4.2"
125
+ source = "registry+https://github.com/rust-lang/crates.io-index"
126
+ checksum = "e87c8503f93e6d144ee5690907ba22db7ba79ab001a932ab99034f0fe836b3df"
127
+ dependencies = [
128
+ "async-trait",
129
+ "bytes",
130
+ "futures-util",
131
+ "http 1.0.0",
132
+ "http-body 1.0.0",
133
+ "http-body-util",
134
+ "mime",
135
+ "pin-project-lite",
136
+ "rustversion",
137
+ "sync_wrapper",
138
+ "tower-layer",
139
+ "tower-service",
140
+ "tracing",
141
+ ]
142
+
143
+ [[package]]
144
+ name = "backtrace"
145
+ version = "0.3.69"
146
+ source = "registry+https://github.com/rust-lang/crates.io-index"
147
+ checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
148
+ dependencies = [
149
+ "addr2line",
150
+ "cc",
151
+ "cfg-if",
152
+ "libc",
153
+ "miniz_oxide 0.7.1",
154
+ "object",
155
+ "rustc-demangle",
156
+ ]
157
+
158
+ [[package]]
159
+ name = "base-x"
160
+ version = "0.2.8"
161
+ source = "registry+https://github.com/rust-lang/crates.io-index"
162
+ checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b"
163
+
164
+ [[package]]
165
+ name = "base64"
166
+ version = "0.13.0"
167
+ source = "registry+https://github.com/rust-lang/crates.io-index"
168
+ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
169
+
170
+ [[package]]
171
+ name = "bitflags"
172
+ version = "2.4.1"
173
+ source = "registry+https://github.com/rust-lang/crates.io-index"
174
+ checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
175
+
176
+ [[package]]
177
+ name = "brotli"
178
+ version = "3.3.4"
179
+ source = "registry+https://github.com/rust-lang/crates.io-index"
180
+ checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68"
181
+ dependencies = [
182
+ "alloc-no-stdlib",
183
+ "alloc-stdlib",
184
+ "brotli-decompressor",
185
+ ]
186
+
187
+ [[package]]
188
+ name = "brotli-decompressor"
189
+ version = "2.3.2"
190
+ source = "registry+https://github.com/rust-lang/crates.io-index"
191
+ checksum = "59ad2d4653bf5ca36ae797b1f4bb4dbddb60ce49ca4aed8a2ce4829f60425b80"
192
+ dependencies = [
193
+ "alloc-no-stdlib",
194
+ "alloc-stdlib",
195
+ ]
196
+
197
+ [[package]]
198
+ name = "bumpalo"
199
+ version = "3.7.0"
200
+ source = "registry+https://github.com/rust-lang/crates.io-index"
201
+ checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631"
202
+
203
+ [[package]]
204
+ name = "bytes"
205
+ version = "1.1.0"
206
+ source = "registry+https://github.com/rust-lang/crates.io-index"
207
+ checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
208
+
209
+ [[package]]
210
+ name = "cc"
211
+ version = "1.0.70"
212
+ source = "registry+https://github.com/rust-lang/crates.io-index"
213
+ checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0"
214
+
215
+ [[package]]
216
+ name = "cfg-if"
217
+ version = "1.0.0"
218
+ source = "registry+https://github.com/rust-lang/crates.io-index"
219
+ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
220
+
221
+ [[package]]
222
+ name = "const_fn"
223
+ version = "0.4.8"
224
+ source = "registry+https://github.com/rust-lang/crates.io-index"
225
+ checksum = "f92cfa0fd5690b3cf8c1ef2cabbd9b7ef22fa53cf5e1f92b05103f6d5d1cf6e7"
226
+
227
+ [[package]]
228
+ name = "cookie"
229
+ version = "0.14.4"
230
+ source = "registry+https://github.com/rust-lang/crates.io-index"
231
+ checksum = "03a5d7b21829bc7b4bf4754a978a241ae54ea55a40f92bb20216e54096f4b951"
232
+ dependencies = [
233
+ "percent-encoding",
234
+ "time",
235
+ "version_check",
236
+ ]
237
+
238
+ [[package]]
239
+ name = "cookie_store"
240
+ version = "0.12.0"
241
+ source = "registry+https://github.com/rust-lang/crates.io-index"
242
+ checksum = "3818dfca4b0cb5211a659bbcbb94225b7127407b2b135e650d717bfb78ab10d3"
243
+ dependencies = [
244
+ "cookie",
245
+ "idna",
246
+ "log",
247
+ "publicsuffix",
248
+ "serde",
249
+ "serde_json",
250
+ "time",
251
+ "url",
252
+ ]
253
+
254
+ [[package]]
255
+ name = "crc32fast"
256
+ version = "1.2.1"
257
+ source = "registry+https://github.com/rust-lang/crates.io-index"
258
+ checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
259
+ dependencies = [
260
+ "cfg-if",
261
+ ]
262
+
263
+ [[package]]
264
+ name = "discard"
265
+ version = "1.0.4"
266
+ source = "registry+https://github.com/rust-lang/crates.io-index"
267
+ checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
268
+
269
+ [[package]]
270
+ name = "dzmedia"
271
+ version = "0.1.0"
272
+ dependencies = [
273
+ "axum",
274
+ "http 1.0.0",
275
+ "reqwest",
276
+ "serde",
277
+ "serde_json",
278
+ "thiserror",
279
+ "tokio",
280
+ "tower-http",
281
+ "tracing-subscriber",
282
+ ]
283
+
284
+ [[package]]
285
+ name = "encoding_rs"
286
+ version = "0.8.28"
287
+ source = "registry+https://github.com/rust-lang/crates.io-index"
288
+ checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065"
289
+ dependencies = [
290
+ "cfg-if",
291
+ ]
292
+
293
+ [[package]]
294
+ name = "equivalent"
295
+ version = "1.0.1"
296
+ source = "registry+https://github.com/rust-lang/crates.io-index"
297
+ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
298
+
299
+ [[package]]
300
+ name = "flate2"
301
+ version = "1.0.22"
302
+ source = "registry+https://github.com/rust-lang/crates.io-index"
303
+ checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f"
304
+ dependencies = [
305
+ "cfg-if",
306
+ "crc32fast",
307
+ "libc",
308
+ "miniz_oxide 0.4.4",
309
+ ]
310
+
311
+ [[package]]
312
+ name = "fnv"
313
+ version = "1.0.7"
314
+ source = "registry+https://github.com/rust-lang/crates.io-index"
315
+ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
316
+
317
+ [[package]]
318
+ name = "form_urlencoded"
319
+ version = "1.0.1"
320
+ source = "registry+https://github.com/rust-lang/crates.io-index"
321
+ checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
322
+ dependencies = [
323
+ "matches",
324
+ "percent-encoding",
325
+ ]
326
+
327
+ [[package]]
328
+ name = "futures-channel"
329
+ version = "0.3.17"
330
+ source = "registry+https://github.com/rust-lang/crates.io-index"
331
+ checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888"
332
+ dependencies = [
333
+ "futures-core",
334
+ ]
335
+
336
+ [[package]]
337
+ name = "futures-core"
338
+ version = "0.3.17"
339
+ source = "registry+https://github.com/rust-lang/crates.io-index"
340
+ checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d"
341
+
342
+ [[package]]
343
+ name = "futures-macro"
344
+ version = "0.3.17"
345
+ source = "registry+https://github.com/rust-lang/crates.io-index"
346
+ checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb"
347
+ dependencies = [
348
+ "autocfg",
349
+ "proc-macro-hack",
350
+ "proc-macro2",
351
+ "quote",
352
+ "syn 1.0.99",
353
+ ]
354
+
355
+ [[package]]
356
+ name = "futures-sink"
357
+ version = "0.3.17"
358
+ source = "registry+https://github.com/rust-lang/crates.io-index"
359
+ checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11"
360
+
361
+ [[package]]
362
+ name = "futures-task"
363
+ version = "0.3.17"
364
+ source = "registry+https://github.com/rust-lang/crates.io-index"
365
+ checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99"
366
+
367
+ [[package]]
368
+ name = "futures-util"
369
+ version = "0.3.17"
370
+ source = "registry+https://github.com/rust-lang/crates.io-index"
371
+ checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481"
372
+ dependencies = [
373
+ "autocfg",
374
+ "futures-core",
375
+ "futures-macro",
376
+ "futures-task",
377
+ "pin-project-lite",
378
+ "pin-utils",
379
+ "proc-macro-hack",
380
+ "proc-macro-nested",
381
+ "slab",
382
+ ]
383
+
384
+ [[package]]
385
+ name = "gimli"
386
+ version = "0.28.1"
387
+ source = "registry+https://github.com/rust-lang/crates.io-index"
388
+ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
389
+
390
+ [[package]]
391
+ name = "h2"
392
+ version = "0.3.11"
393
+ source = "registry+https://github.com/rust-lang/crates.io-index"
394
+ checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e"
395
+ dependencies = [
396
+ "bytes",
397
+ "fnv",
398
+ "futures-core",
399
+ "futures-sink",
400
+ "futures-util",
401
+ "http 0.2.8",
402
+ "indexmap 1.7.0",
403
+ "slab",
404
+ "tokio",
405
+ "tokio-util 0.6.8",
406
+ "tracing",
407
+ ]
408
+
409
+ [[package]]
410
+ name = "h2"
411
+ version = "0.4.0"
412
+ source = "registry+https://github.com/rust-lang/crates.io-index"
413
+ checksum = "e1d308f63daf4181410c242d34c11f928dcb3aa105852019e043c9d1f4e4368a"
414
+ dependencies = [
415
+ "bytes",
416
+ "fnv",
417
+ "futures-core",
418
+ "futures-sink",
419
+ "futures-util",
420
+ "http 1.0.0",
421
+ "indexmap 2.1.0",
422
+ "slab",
423
+ "tokio",
424
+ "tokio-util 0.7.10",
425
+ "tracing",
426
+ ]
427
+
428
+ [[package]]
429
+ name = "hashbrown"
430
+ version = "0.11.2"
431
+ source = "registry+https://github.com/rust-lang/crates.io-index"
432
+ checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
433
+
434
+ [[package]]
435
+ name = "hashbrown"
436
+ version = "0.14.3"
437
+ source = "registry+https://github.com/rust-lang/crates.io-index"
438
+ checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
439
+
440
+ [[package]]
441
+ name = "hermit-abi"
442
+ version = "0.1.19"
443
+ source = "registry+https://github.com/rust-lang/crates.io-index"
444
+ checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
445
+ dependencies = [
446
+ "libc",
447
+ ]
448
+
449
+ [[package]]
450
+ name = "http"
451
+ version = "0.2.8"
452
+ source = "registry+https://github.com/rust-lang/crates.io-index"
453
+ checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399"
454
+ dependencies = [
455
+ "bytes",
456
+ "fnv",
457
+ "itoa 1.0.10",
458
+ ]
459
+
460
+ [[package]]
461
+ name = "http"
462
+ version = "1.0.0"
463
+ source = "registry+https://github.com/rust-lang/crates.io-index"
464
+ checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea"
465
+ dependencies = [
466
+ "bytes",
467
+ "fnv",
468
+ "itoa 1.0.10",
469
+ ]
470
+
471
+ [[package]]
472
+ name = "http-body"
473
+ version = "0.4.5"
474
+ source = "registry+https://github.com/rust-lang/crates.io-index"
475
+ checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
476
+ dependencies = [
477
+ "bytes",
478
+ "http 0.2.8",
479
+ "pin-project-lite",
480
+ ]
481
+
482
+ [[package]]
483
+ name = "http-body"
484
+ version = "1.0.0"
485
+ source = "registry+https://github.com/rust-lang/crates.io-index"
486
+ checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
487
+ dependencies = [
488
+ "bytes",
489
+ "http 1.0.0",
490
+ ]
491
+
492
+ [[package]]
493
+ name = "http-body-util"
494
+ version = "0.1.0"
495
+ source = "registry+https://github.com/rust-lang/crates.io-index"
496
+ checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840"
497
+ dependencies = [
498
+ "bytes",
499
+ "futures-util",
500
+ "http 1.0.0",
501
+ "http-body 1.0.0",
502
+ "pin-project-lite",
503
+ ]
504
+
505
+ [[package]]
506
+ name = "httparse"
507
+ version = "1.8.0"
508
+ source = "registry+https://github.com/rust-lang/crates.io-index"
509
+ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
510
+
511
+ [[package]]
512
+ name = "httpdate"
513
+ version = "1.0.1"
514
+ source = "registry+https://github.com/rust-lang/crates.io-index"
515
+ checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440"
516
+
517
+ [[package]]
518
+ name = "hyper"
519
+ version = "0.14.20"
520
+ source = "registry+https://github.com/rust-lang/crates.io-index"
521
+ checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac"
522
+ dependencies = [
523
+ "bytes",
524
+ "futures-channel",
525
+ "futures-core",
526
+ "futures-util",
527
+ "h2 0.3.11",
528
+ "http 0.2.8",
529
+ "http-body 0.4.5",
530
+ "httparse",
531
+ "httpdate",
532
+ "itoa 1.0.10",
533
+ "pin-project-lite",
534
+ "socket2 0.4.4",
535
+ "tokio",
536
+ "tower-service",
537
+ "tracing",
538
+ "want",
539
+ ]
540
+
541
+ [[package]]
542
+ name = "hyper"
543
+ version = "1.1.0"
544
+ source = "registry+https://github.com/rust-lang/crates.io-index"
545
+ checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75"
546
+ dependencies = [
547
+ "bytes",
548
+ "futures-channel",
549
+ "futures-util",
550
+ "h2 0.4.0",
551
+ "http 1.0.0",
552
+ "http-body 1.0.0",
553
+ "httparse",
554
+ "httpdate",
555
+ "itoa 1.0.10",
556
+ "pin-project-lite",
557
+ "tokio",
558
+ ]
559
+
560
+ [[package]]
561
+ name = "hyper-rustls"
562
+ version = "0.22.1"
563
+ source = "registry+https://github.com/rust-lang/crates.io-index"
564
+ checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64"
565
+ dependencies = [
566
+ "futures-util",
567
+ "hyper 0.14.20",
568
+ "log",
569
+ "rustls",
570
+ "tokio",
571
+ "tokio-rustls",
572
+ "webpki",
573
+ ]
574
+
575
+ [[package]]
576
+ name = "hyper-util"
577
+ version = "0.1.2"
578
+ source = "registry+https://github.com/rust-lang/crates.io-index"
579
+ checksum = "bdea9aac0dbe5a9240d68cfd9501e2db94222c6dc06843e06640b9e07f0fdc67"
580
+ dependencies = [
581
+ "bytes",
582
+ "futures-channel",
583
+ "futures-util",
584
+ "http 1.0.0",
585
+ "http-body 1.0.0",
586
+ "hyper 1.1.0",
587
+ "pin-project-lite",
588
+ "socket2 0.5.5",
589
+ "tokio",
590
+ "tracing",
591
+ ]
592
+
593
+ [[package]]
594
+ name = "idna"
595
+ version = "0.2.3"
596
+ source = "registry+https://github.com/rust-lang/crates.io-index"
597
+ checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
598
+ dependencies = [
599
+ "matches",
600
+ "unicode-bidi",
601
+ "unicode-normalization",
602
+ ]
603
+
604
+ [[package]]
605
+ name = "indexmap"
606
+ version = "1.7.0"
607
+ source = "registry+https://github.com/rust-lang/crates.io-index"
608
+ checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
609
+ dependencies = [
610
+ "autocfg",
611
+ "hashbrown 0.11.2",
612
+ ]
613
+
614
+ [[package]]
615
+ name = "indexmap"
616
+ version = "2.1.0"
617
+ source = "registry+https://github.com/rust-lang/crates.io-index"
618
+ checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
619
+ dependencies = [
620
+ "equivalent",
621
+ "hashbrown 0.14.3",
622
+ ]
623
+
624
+ [[package]]
625
+ name = "ipnet"
626
+ version = "2.3.1"
627
+ source = "registry+https://github.com/rust-lang/crates.io-index"
628
+ checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9"
629
+
630
+ [[package]]
631
+ name = "itoa"
632
+ version = "0.4.8"
633
+ source = "registry+https://github.com/rust-lang/crates.io-index"
634
+ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
635
+
636
+ [[package]]
637
+ name = "itoa"
638
+ version = "1.0.10"
639
+ source = "registry+https://github.com/rust-lang/crates.io-index"
640
+ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
641
+
642
+ [[package]]
643
+ name = "js-sys"
644
+ version = "0.3.53"
645
+ source = "registry+https://github.com/rust-lang/crates.io-index"
646
+ checksum = "e4bf49d50e2961077d9c99f4b7997d770a1114f087c3c2e0069b36c13fc2979d"
647
+ dependencies = [
648
+ "wasm-bindgen",
649
+ ]
650
+
651
+ [[package]]
652
+ name = "lazy_static"
653
+ version = "1.4.0"
654
+ source = "registry+https://github.com/rust-lang/crates.io-index"
655
+ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
656
+
657
+ [[package]]
658
+ name = "libc"
659
+ version = "0.2.151"
660
+ source = "registry+https://github.com/rust-lang/crates.io-index"
661
+ checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
662
+
663
+ [[package]]
664
+ name = "log"
665
+ version = "0.4.20"
666
+ source = "registry+https://github.com/rust-lang/crates.io-index"
667
+ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
668
+
669
+ [[package]]
670
+ name = "matches"
671
+ version = "0.1.9"
672
+ source = "registry+https://github.com/rust-lang/crates.io-index"
673
+ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
674
+
675
+ [[package]]
676
+ name = "matchit"
677
+ version = "0.7.0"
678
+ source = "registry+https://github.com/rust-lang/crates.io-index"
679
+ checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40"
680
+
681
+ [[package]]
682
+ name = "memchr"
683
+ version = "2.4.1"
684
+ source = "registry+https://github.com/rust-lang/crates.io-index"
685
+ checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
686
+
687
+ [[package]]
688
+ name = "mime"
689
+ version = "0.3.16"
690
+ source = "registry+https://github.com/rust-lang/crates.io-index"
691
+ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
692
+
693
+ [[package]]
694
+ name = "miniz_oxide"
695
+ version = "0.4.4"
696
+ source = "registry+https://github.com/rust-lang/crates.io-index"
697
+ checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
698
+ dependencies = [
699
+ "adler",
700
+ "autocfg",
701
+ ]
702
+
703
+ [[package]]
704
+ name = "miniz_oxide"
705
+ version = "0.7.1"
706
+ source = "registry+https://github.com/rust-lang/crates.io-index"
707
+ checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
708
+ dependencies = [
709
+ "adler",
710
+ ]
711
+
712
+ [[package]]
713
+ name = "mio"
714
+ version = "0.8.10"
715
+ source = "registry+https://github.com/rust-lang/crates.io-index"
716
+ checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
717
+ dependencies = [
718
+ "libc",
719
+ "wasi",
720
+ "windows-sys",
721
+ ]
722
+
723
+ [[package]]
724
+ name = "num_cpus"
725
+ version = "1.13.1"
726
+ source = "registry+https://github.com/rust-lang/crates.io-index"
727
+ checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
728
+ dependencies = [
729
+ "hermit-abi",
730
+ "libc",
731
+ ]
732
+
733
+ [[package]]
734
+ name = "object"
735
+ version = "0.32.2"
736
+ source = "registry+https://github.com/rust-lang/crates.io-index"
737
+ checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
738
+ dependencies = [
739
+ "memchr",
740
+ ]
741
+
742
+ [[package]]
743
+ name = "once_cell"
744
+ version = "1.19.0"
745
+ source = "registry+https://github.com/rust-lang/crates.io-index"
746
+ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
747
+
748
+ [[package]]
749
+ name = "percent-encoding"
750
+ version = "2.1.0"
751
+ source = "registry+https://github.com/rust-lang/crates.io-index"
752
+ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
753
+
754
+ [[package]]
755
+ name = "pin-project"
756
+ version = "1.0.12"
757
+ source = "registry+https://github.com/rust-lang/crates.io-index"
758
+ checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
759
+ dependencies = [
760
+ "pin-project-internal",
761
+ ]
762
+
763
+ [[package]]
764
+ name = "pin-project-internal"
765
+ version = "1.0.12"
766
+ source = "registry+https://github.com/rust-lang/crates.io-index"
767
+ checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
768
+ dependencies = [
769
+ "proc-macro2",
770
+ "quote",
771
+ "syn 1.0.99",
772
+ ]
773
+
774
+ [[package]]
775
+ name = "pin-project-lite"
776
+ version = "0.2.13"
777
+ source = "registry+https://github.com/rust-lang/crates.io-index"
778
+ checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
779
+
780
+ [[package]]
781
+ name = "pin-utils"
782
+ version = "0.1.0"
783
+ source = "registry+https://github.com/rust-lang/crates.io-index"
784
+ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
785
+
786
+ [[package]]
787
+ name = "proc-macro-hack"
788
+ version = "0.5.19"
789
+ source = "registry+https://github.com/rust-lang/crates.io-index"
790
+ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
791
+
792
+ [[package]]
793
+ name = "proc-macro-nested"
794
+ version = "0.1.7"
795
+ source = "registry+https://github.com/rust-lang/crates.io-index"
796
+ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
797
+
798
+ [[package]]
799
+ name = "proc-macro2"
800
+ version = "1.0.76"
801
+ source = "registry+https://github.com/rust-lang/crates.io-index"
802
+ checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
803
+ dependencies = [
804
+ "unicode-ident",
805
+ ]
806
+
807
+ [[package]]
808
+ name = "publicsuffix"
809
+ version = "1.5.6"
810
+ source = "registry+https://github.com/rust-lang/crates.io-index"
811
+ checksum = "95b4ce31ff0a27d93c8de1849cf58162283752f065a90d508f1105fa6c9a213f"
812
+ dependencies = [
813
+ "idna",
814
+ "url",
815
+ ]
816
+
817
+ [[package]]
818
+ name = "quote"
819
+ version = "1.0.35"
820
+ source = "registry+https://github.com/rust-lang/crates.io-index"
821
+ checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
822
+ dependencies = [
823
+ "proc-macro2",
824
+ ]
825
+
826
+ [[package]]
827
+ name = "reqwest"
828
+ version = "0.11.4"
829
+ source = "registry+https://github.com/rust-lang/crates.io-index"
830
+ checksum = "246e9f61b9bb77df069a947682be06e31ac43ea37862e244a69f177694ea6d22"
831
+ dependencies = [
832
+ "async-compression 0.3.8",
833
+ "base64",
834
+ "bytes",
835
+ "cookie",
836
+ "cookie_store",
837
+ "encoding_rs",
838
+ "futures-core",
839
+ "futures-util",
840
+ "http 0.2.8",
841
+ "http-body 0.4.5",
842
+ "hyper 0.14.20",
843
+ "hyper-rustls",
844
+ "ipnet",
845
+ "js-sys",
846
+ "lazy_static",
847
+ "log",
848
+ "mime",
849
+ "percent-encoding",
850
+ "pin-project-lite",
851
+ "rustls",
852
+ "serde",
853
+ "serde_json",
854
+ "serde_urlencoded",
855
+ "time",
856
+ "tokio",
857
+ "tokio-rustls",
858
+ "tokio-util 0.6.8",
859
+ "url",
860
+ "wasm-bindgen",
861
+ "wasm-bindgen-futures",
862
+ "web-sys",
863
+ "webpki-roots",
864
+ "winreg",
865
+ ]
866
+
867
+ [[package]]
868
+ name = "ring"
869
+ version = "0.16.20"
870
+ source = "registry+https://github.com/rust-lang/crates.io-index"
871
+ checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
872
+ dependencies = [
873
+ "cc",
874
+ "libc",
875
+ "once_cell",
876
+ "spin",
877
+ "untrusted",
878
+ "web-sys",
879
+ "winapi",
880
+ ]
881
+
882
+ [[package]]
883
+ name = "rustc-demangle"
884
+ version = "0.1.23"
885
+ source = "registry+https://github.com/rust-lang/crates.io-index"
886
+ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
887
+
888
+ [[package]]
889
+ name = "rustc_version"
890
+ version = "0.2.3"
891
+ source = "registry+https://github.com/rust-lang/crates.io-index"
892
+ checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
893
+ dependencies = [
894
+ "semver",
895
+ ]
896
+
897
+ [[package]]
898
+ name = "rustls"
899
+ version = "0.19.1"
900
+ source = "registry+https://github.com/rust-lang/crates.io-index"
901
+ checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7"
902
+ dependencies = [
903
+ "base64",
904
+ "log",
905
+ "ring",
906
+ "sct",
907
+ "webpki",
908
+ ]
909
+
910
+ [[package]]
911
+ name = "rustversion"
912
+ version = "1.0.9"
913
+ source = "registry+https://github.com/rust-lang/crates.io-index"
914
+ checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"
915
+
916
+ [[package]]
917
+ name = "ryu"
918
+ version = "1.0.5"
919
+ source = "registry+https://github.com/rust-lang/crates.io-index"
920
+ checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
921
+
922
+ [[package]]
923
+ name = "sct"
924
+ version = "0.6.1"
925
+ source = "registry+https://github.com/rust-lang/crates.io-index"
926
+ checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce"
927
+ dependencies = [
928
+ "ring",
929
+ "untrusted",
930
+ ]
931
+
932
+ [[package]]
933
+ name = "semver"
934
+ version = "0.9.0"
935
+ source = "registry+https://github.com/rust-lang/crates.io-index"
936
+ checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
937
+ dependencies = [
938
+ "semver-parser",
939
+ ]
940
+
941
+ [[package]]
942
+ name = "semver-parser"
943
+ version = "0.7.0"
944
+ source = "registry+https://github.com/rust-lang/crates.io-index"
945
+ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
946
+
947
+ [[package]]
948
+ name = "serde"
949
+ version = "1.0.130"
950
+ source = "registry+https://github.com/rust-lang/crates.io-index"
951
+ checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
952
+ dependencies = [
953
+ "serde_derive",
954
+ ]
955
+
956
+ [[package]]
957
+ name = "serde_derive"
958
+ version = "1.0.130"
959
+ source = "registry+https://github.com/rust-lang/crates.io-index"
960
+ checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
961
+ dependencies = [
962
+ "proc-macro2",
963
+ "quote",
964
+ "syn 1.0.99",
965
+ ]
966
+
967
+ [[package]]
968
+ name = "serde_json"
969
+ version = "1.0.67"
970
+ source = "registry+https://github.com/rust-lang/crates.io-index"
971
+ checksum = "a7f9e390c27c3c0ce8bc5d725f6e4d30a29d26659494aa4b17535f7522c5c950"
972
+ dependencies = [
973
+ "itoa 0.4.8",
974
+ "ryu",
975
+ "serde",
976
+ ]
977
+
978
+ [[package]]
979
+ name = "serde_path_to_error"
980
+ version = "0.1.8"
981
+ source = "registry+https://github.com/rust-lang/crates.io-index"
982
+ checksum = "184c643044780f7ceb59104cef98a5a6f12cb2288a7bc701ab93a362b49fd47d"
983
+ dependencies = [
984
+ "serde",
985
+ ]
986
+
987
+ [[package]]
988
+ name = "serde_urlencoded"
989
+ version = "0.7.0"
990
+ source = "registry+https://github.com/rust-lang/crates.io-index"
991
+ checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9"
992
+ dependencies = [
993
+ "form_urlencoded",
994
+ "itoa 0.4.8",
995
+ "ryu",
996
+ "serde",
997
+ ]
998
+
999
+ [[package]]
1000
+ name = "sha1"
1001
+ version = "0.6.0"
1002
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1003
+ checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
1004
+
1005
+ [[package]]
1006
+ name = "sharded-slab"
1007
+ version = "0.1.4"
1008
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1009
+ checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
1010
+ dependencies = [
1011
+ "lazy_static",
1012
+ ]
1013
+
1014
+ [[package]]
1015
+ name = "slab"
1016
+ version = "0.4.4"
1017
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1018
+ checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590"
1019
+
1020
+ [[package]]
1021
+ name = "smallvec"
1022
+ version = "1.9.0"
1023
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1024
+ checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
1025
+
1026
+ [[package]]
1027
+ name = "socket2"
1028
+ version = "0.4.4"
1029
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1030
+ checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
1031
+ dependencies = [
1032
+ "libc",
1033
+ "winapi",
1034
+ ]
1035
+
1036
+ [[package]]
1037
+ name = "socket2"
1038
+ version = "0.5.5"
1039
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1040
+ checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
1041
+ dependencies = [
1042
+ "libc",
1043
+ "windows-sys",
1044
+ ]
1045
+
1046
+ [[package]]
1047
+ name = "spin"
1048
+ version = "0.5.2"
1049
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1050
+ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
1051
+
1052
+ [[package]]
1053
+ name = "standback"
1054
+ version = "0.2.17"
1055
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1056
+ checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff"
1057
+ dependencies = [
1058
+ "version_check",
1059
+ ]
1060
+
1061
+ [[package]]
1062
+ name = "stdweb"
1063
+ version = "0.4.20"
1064
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1065
+ checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5"
1066
+ dependencies = [
1067
+ "discard",
1068
+ "rustc_version",
1069
+ "stdweb-derive",
1070
+ "stdweb-internal-macros",
1071
+ "stdweb-internal-runtime",
1072
+ "wasm-bindgen",
1073
+ ]
1074
+
1075
+ [[package]]
1076
+ name = "stdweb-derive"
1077
+ version = "0.5.3"
1078
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1079
+ checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
1080
+ dependencies = [
1081
+ "proc-macro2",
1082
+ "quote",
1083
+ "serde",
1084
+ "serde_derive",
1085
+ "syn 1.0.99",
1086
+ ]
1087
+
1088
+ [[package]]
1089
+ name = "stdweb-internal-macros"
1090
+ version = "0.2.9"
1091
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1092
+ checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
1093
+ dependencies = [
1094
+ "base-x",
1095
+ "proc-macro2",
1096
+ "quote",
1097
+ "serde",
1098
+ "serde_derive",
1099
+ "serde_json",
1100
+ "sha1",
1101
+ "syn 1.0.99",
1102
+ ]
1103
+
1104
+ [[package]]
1105
+ name = "stdweb-internal-runtime"
1106
+ version = "0.1.5"
1107
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1108
+ checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
1109
+
1110
+ [[package]]
1111
+ name = "syn"
1112
+ version = "1.0.99"
1113
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1114
+ checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
1115
+ dependencies = [
1116
+ "proc-macro2",
1117
+ "quote",
1118
+ "unicode-ident",
1119
+ ]
1120
+
1121
+ [[package]]
1122
+ name = "syn"
1123
+ version = "2.0.48"
1124
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1125
+ checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
1126
+ dependencies = [
1127
+ "proc-macro2",
1128
+ "quote",
1129
+ "unicode-ident",
1130
+ ]
1131
+
1132
+ [[package]]
1133
+ name = "sync_wrapper"
1134
+ version = "0.1.1"
1135
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1136
+ checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8"
1137
+
1138
+ [[package]]
1139
+ name = "thiserror"
1140
+ version = "1.0.29"
1141
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1142
+ checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88"
1143
+ dependencies = [
1144
+ "thiserror-impl",
1145
+ ]
1146
+
1147
+ [[package]]
1148
+ name = "thiserror-impl"
1149
+ version = "1.0.29"
1150
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1151
+ checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c"
1152
+ dependencies = [
1153
+ "proc-macro2",
1154
+ "quote",
1155
+ "syn 1.0.99",
1156
+ ]
1157
+
1158
+ [[package]]
1159
+ name = "thread_local"
1160
+ version = "1.1.4"
1161
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1162
+ checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
1163
+ dependencies = [
1164
+ "once_cell",
1165
+ ]
1166
+
1167
+ [[package]]
1168
+ name = "time"
1169
+ version = "0.2.27"
1170
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1171
+ checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242"
1172
+ dependencies = [
1173
+ "const_fn",
1174
+ "libc",
1175
+ "standback",
1176
+ "stdweb",
1177
+ "time-macros",
1178
+ "version_check",
1179
+ "winapi",
1180
+ ]
1181
+
1182
+ [[package]]
1183
+ name = "time-macros"
1184
+ version = "0.1.1"
1185
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1186
+ checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1"
1187
+ dependencies = [
1188
+ "proc-macro-hack",
1189
+ "time-macros-impl",
1190
+ ]
1191
+
1192
+ [[package]]
1193
+ name = "time-macros-impl"
1194
+ version = "0.1.2"
1195
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1196
+ checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f"
1197
+ dependencies = [
1198
+ "proc-macro-hack",
1199
+ "proc-macro2",
1200
+ "quote",
1201
+ "standback",
1202
+ "syn 1.0.99",
1203
+ ]
1204
+
1205
+ [[package]]
1206
+ name = "tinyvec"
1207
+ version = "1.3.1"
1208
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1209
+ checksum = "848a1e1181b9f6753b5e96a092749e29b11d19ede67dfbbd6c7dc7e0f49b5338"
1210
+ dependencies = [
1211
+ "tinyvec_macros",
1212
+ ]
1213
+
1214
+ [[package]]
1215
+ name = "tinyvec_macros"
1216
+ version = "0.1.0"
1217
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1218
+ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
1219
+
1220
+ [[package]]
1221
+ name = "tokio"
1222
+ version = "1.35.1"
1223
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1224
+ checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104"
1225
+ dependencies = [
1226
+ "backtrace",
1227
+ "bytes",
1228
+ "libc",
1229
+ "mio",
1230
+ "num_cpus",
1231
+ "pin-project-lite",
1232
+ "socket2 0.5.5",
1233
+ "tokio-macros",
1234
+ "windows-sys",
1235
+ ]
1236
+
1237
+ [[package]]
1238
+ name = "tokio-macros"
1239
+ version = "2.2.0"
1240
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1241
+ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
1242
+ dependencies = [
1243
+ "proc-macro2",
1244
+ "quote",
1245
+ "syn 2.0.48",
1246
+ ]
1247
+
1248
+ [[package]]
1249
+ name = "tokio-rustls"
1250
+ version = "0.22.0"
1251
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1252
+ checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6"
1253
+ dependencies = [
1254
+ "rustls",
1255
+ "tokio",
1256
+ "webpki",
1257
+ ]
1258
+
1259
+ [[package]]
1260
+ name = "tokio-util"
1261
+ version = "0.6.8"
1262
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1263
+ checksum = "08d3725d3efa29485e87311c5b699de63cde14b00ed4d256b8318aa30ca452cd"
1264
+ dependencies = [
1265
+ "bytes",
1266
+ "futures-core",
1267
+ "futures-sink",
1268
+ "log",
1269
+ "pin-project-lite",
1270
+ "tokio",
1271
+ ]
1272
+
1273
+ [[package]]
1274
+ name = "tokio-util"
1275
+ version = "0.7.10"
1276
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1277
+ checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
1278
+ dependencies = [
1279
+ "bytes",
1280
+ "futures-core",
1281
+ "futures-sink",
1282
+ "pin-project-lite",
1283
+ "tokio",
1284
+ "tracing",
1285
+ ]
1286
+
1287
+ [[package]]
1288
+ name = "tower"
1289
+ version = "0.4.13"
1290
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1291
+ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
1292
+ dependencies = [
1293
+ "futures-core",
1294
+ "futures-util",
1295
+ "pin-project",
1296
+ "pin-project-lite",
1297
+ "tokio",
1298
+ "tower-layer",
1299
+ "tower-service",
1300
+ "tracing",
1301
+ ]
1302
+
1303
+ [[package]]
1304
+ name = "tower-http"
1305
+ version = "0.5.0"
1306
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1307
+ checksum = "09e12e6351354851911bdf8c2b8f2ab15050c567d70a8b9a37ae7b8301a4080d"
1308
+ dependencies = [
1309
+ "async-compression 0.4.5",
1310
+ "bitflags",
1311
+ "bytes",
1312
+ "futures-util",
1313
+ "http 1.0.0",
1314
+ "http-body 1.0.0",
1315
+ "http-body-util",
1316
+ "pin-project-lite",
1317
+ "tokio",
1318
+ "tokio-util 0.7.10",
1319
+ "tower-layer",
1320
+ "tower-service",
1321
+ "tracing",
1322
+ ]
1323
+
1324
+ [[package]]
1325
+ name = "tower-layer"
1326
+ version = "0.3.2"
1327
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1328
+ checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
1329
+
1330
+ [[package]]
1331
+ name = "tower-service"
1332
+ version = "0.3.1"
1333
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1334
+ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
1335
+
1336
+ [[package]]
1337
+ name = "tracing"
1338
+ version = "0.1.40"
1339
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1340
+ checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
1341
+ dependencies = [
1342
+ "log",
1343
+ "pin-project-lite",
1344
+ "tracing-core",
1345
+ ]
1346
+
1347
+ [[package]]
1348
+ name = "tracing-core"
1349
+ version = "0.1.32"
1350
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1351
+ checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
1352
+ dependencies = [
1353
+ "once_cell",
1354
+ "valuable",
1355
+ ]
1356
+
1357
+ [[package]]
1358
+ name = "tracing-log"
1359
+ version = "0.1.3"
1360
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1361
+ checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
1362
+ dependencies = [
1363
+ "lazy_static",
1364
+ "log",
1365
+ "tracing-core",
1366
+ ]
1367
+
1368
+ [[package]]
1369
+ name = "tracing-subscriber"
1370
+ version = "0.3.11"
1371
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1372
+ checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596"
1373
+ dependencies = [
1374
+ "ansi_term",
1375
+ "sharded-slab",
1376
+ "smallvec",
1377
+ "thread_local",
1378
+ "tracing-core",
1379
+ "tracing-log",
1380
+ ]
1381
+
1382
+ [[package]]
1383
+ name = "try-lock"
1384
+ version = "0.2.3"
1385
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1386
+ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
1387
+
1388
+ [[package]]
1389
+ name = "unicode-bidi"
1390
+ version = "0.3.6"
1391
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1392
+ checksum = "246f4c42e67e7a4e3c6106ff716a5d067d4132a642840b242e357e468a2a0085"
1393
+
1394
+ [[package]]
1395
+ name = "unicode-ident"
1396
+ version = "1.0.3"
1397
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1398
+ checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
1399
+
1400
+ [[package]]
1401
+ name = "unicode-normalization"
1402
+ version = "0.1.19"
1403
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1404
+ checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9"
1405
+ dependencies = [
1406
+ "tinyvec",
1407
+ ]
1408
+
1409
+ [[package]]
1410
+ name = "untrusted"
1411
+ version = "0.7.1"
1412
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1413
+ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
1414
+
1415
+ [[package]]
1416
+ name = "url"
1417
+ version = "2.2.2"
1418
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1419
+ checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
1420
+ dependencies = [
1421
+ "form_urlencoded",
1422
+ "idna",
1423
+ "matches",
1424
+ "percent-encoding",
1425
+ ]
1426
+
1427
+ [[package]]
1428
+ name = "valuable"
1429
+ version = "0.1.0"
1430
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1431
+ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
1432
+
1433
+ [[package]]
1434
+ name = "version_check"
1435
+ version = "0.9.3"
1436
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1437
+ checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
1438
+
1439
+ [[package]]
1440
+ name = "want"
1441
+ version = "0.3.0"
1442
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1443
+ checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
1444
+ dependencies = [
1445
+ "log",
1446
+ "try-lock",
1447
+ ]
1448
+
1449
+ [[package]]
1450
+ name = "wasi"
1451
+ version = "0.11.0+wasi-snapshot-preview1"
1452
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1453
+ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
1454
+
1455
+ [[package]]
1456
+ name = "wasm-bindgen"
1457
+ version = "0.2.76"
1458
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1459
+ checksum = "8ce9b1b516211d33767048e5d47fa2a381ed8b76fc48d2ce4aa39877f9f183e0"
1460
+ dependencies = [
1461
+ "cfg-if",
1462
+ "serde",
1463
+ "serde_json",
1464
+ "wasm-bindgen-macro",
1465
+ ]
1466
+
1467
+ [[package]]
1468
+ name = "wasm-bindgen-backend"
1469
+ version = "0.2.76"
1470
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1471
+ checksum = "cfe8dc78e2326ba5f845f4b5bf548401604fa20b1dd1d365fb73b6c1d6364041"
1472
+ dependencies = [
1473
+ "bumpalo",
1474
+ "lazy_static",
1475
+ "log",
1476
+ "proc-macro2",
1477
+ "quote",
1478
+ "syn 1.0.99",
1479
+ "wasm-bindgen-shared",
1480
+ ]
1481
+
1482
+ [[package]]
1483
+ name = "wasm-bindgen-futures"
1484
+ version = "0.4.26"
1485
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1486
+ checksum = "95fded345a6559c2cfee778d562300c581f7d4ff3edb9b0d230d69800d213972"
1487
+ dependencies = [
1488
+ "cfg-if",
1489
+ "js-sys",
1490
+ "wasm-bindgen",
1491
+ "web-sys",
1492
+ ]
1493
+
1494
+ [[package]]
1495
+ name = "wasm-bindgen-macro"
1496
+ version = "0.2.76"
1497
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1498
+ checksum = "44468aa53335841d9d6b6c023eaab07c0cd4bddbcfdee3e2bb1e8d2cb8069fef"
1499
+ dependencies = [
1500
+ "quote",
1501
+ "wasm-bindgen-macro-support",
1502
+ ]
1503
+
1504
+ [[package]]
1505
+ name = "wasm-bindgen-macro-support"
1506
+ version = "0.2.76"
1507
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1508
+ checksum = "0195807922713af1e67dc66132c7328206ed9766af3858164fb583eedc25fbad"
1509
+ dependencies = [
1510
+ "proc-macro2",
1511
+ "quote",
1512
+ "syn 1.0.99",
1513
+ "wasm-bindgen-backend",
1514
+ "wasm-bindgen-shared",
1515
+ ]
1516
+
1517
+ [[package]]
1518
+ name = "wasm-bindgen-shared"
1519
+ version = "0.2.76"
1520
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1521
+ checksum = "acdb075a845574a1fa5f09fd77e43f7747599301ea3417a9fbffdeedfc1f4a29"
1522
+
1523
+ [[package]]
1524
+ name = "web-sys"
1525
+ version = "0.3.53"
1526
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1527
+ checksum = "224b2f6b67919060055ef1a67807367c2066ed520c3862cc013d26cf893a783c"
1528
+ dependencies = [
1529
+ "js-sys",
1530
+ "wasm-bindgen",
1531
+ ]
1532
+
1533
+ [[package]]
1534
+ name = "webpki"
1535
+ version = "0.21.4"
1536
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1537
+ checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea"
1538
+ dependencies = [
1539
+ "ring",
1540
+ "untrusted",
1541
+ ]
1542
+
1543
+ [[package]]
1544
+ name = "webpki-roots"
1545
+ version = "0.21.1"
1546
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1547
+ checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940"
1548
+ dependencies = [
1549
+ "webpki",
1550
+ ]
1551
+
1552
+ [[package]]
1553
+ name = "winapi"
1554
+ version = "0.3.9"
1555
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1556
+ checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
1557
+ dependencies = [
1558
+ "winapi-i686-pc-windows-gnu",
1559
+ "winapi-x86_64-pc-windows-gnu",
1560
+ ]
1561
+
1562
+ [[package]]
1563
+ name = "winapi-i686-pc-windows-gnu"
1564
+ version = "0.4.0"
1565
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1566
+ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
1567
+
1568
+ [[package]]
1569
+ name = "winapi-x86_64-pc-windows-gnu"
1570
+ version = "0.4.0"
1571
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1572
+ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
1573
+
1574
+ [[package]]
1575
+ name = "windows-sys"
1576
+ version = "0.48.0"
1577
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1578
+ checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
1579
+ dependencies = [
1580
+ "windows-targets",
1581
+ ]
1582
+
1583
+ [[package]]
1584
+ name = "windows-targets"
1585
+ version = "0.48.5"
1586
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1587
+ checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
1588
+ dependencies = [
1589
+ "windows_aarch64_gnullvm",
1590
+ "windows_aarch64_msvc",
1591
+ "windows_i686_gnu",
1592
+ "windows_i686_msvc",
1593
+ "windows_x86_64_gnu",
1594
+ "windows_x86_64_gnullvm",
1595
+ "windows_x86_64_msvc",
1596
+ ]
1597
+
1598
+ [[package]]
1599
+ name = "windows_aarch64_gnullvm"
1600
+ version = "0.48.5"
1601
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1602
+ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
1603
+
1604
+ [[package]]
1605
+ name = "windows_aarch64_msvc"
1606
+ version = "0.48.5"
1607
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1608
+ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
1609
+
1610
+ [[package]]
1611
+ name = "windows_i686_gnu"
1612
+ version = "0.48.5"
1613
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1614
+ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
1615
+
1616
+ [[package]]
1617
+ name = "windows_i686_msvc"
1618
+ version = "0.48.5"
1619
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1620
+ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
1621
+
1622
+ [[package]]
1623
+ name = "windows_x86_64_gnu"
1624
+ version = "0.48.5"
1625
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1626
+ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
1627
+
1628
+ [[package]]
1629
+ name = "windows_x86_64_gnullvm"
1630
+ version = "0.48.5"
1631
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1632
+ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
1633
+
1634
+ [[package]]
1635
+ name = "windows_x86_64_msvc"
1636
+ version = "0.48.5"
1637
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1638
+ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
1639
+
1640
+ [[package]]
1641
+ name = "winreg"
1642
+ version = "0.7.0"
1643
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1644
+ checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69"
1645
+ dependencies = [
1646
+ "winapi",
1647
+ ]
Cargo.toml ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [package]
2
+ name = "dzmedia"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+
6
+ # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7
+
8
+ [dependencies]
9
+ axum = "0.7"
10
+ http = "1.0"
11
+ tower-http = { version = "0.5", features = ["cors", "trace", "compression-br", "compression-deflate", "compression-gzip"] }
12
+ tracing-subscriber = "0.3"
13
+ tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
14
+ serde = { version = "1.0", features = ["derive"] }
15
+ reqwest = { version = "0.11", features = ["json", "rustls-tls", "cookies", "gzip"], default-features = false }
16
+ serde_json = "1.0"
17
+ thiserror = "1.0"
18
+ bytes = "1"
19
+ futures-util = "0.3"
20
+ blowfish = "0.9"
21
+ cbc = "0.1"
22
+ cipher = "0.4"
23
+ md5 = "0.7"
24
+ async-stream = "0.3"
Dockerfile ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM rust:latest as builder
2
+
3
+ WORKDIR /usr/src/app
4
+ COPY . .
5
+ RUN cargo build --release && mv ./target/release/dzmedia ./dzmedia
6
+
7
+ # Runtime image
8
+ FROM debian:bookworm-slim
9
+
10
+ RUN apt-get update \
11
+ && apt-get install -y --no-install-recommends ca-certificates \
12
+ && rm -rf /var/lib/apt/lists/* \
13
+ && useradd -ms /bin/bash app
14
+
15
+ USER app
16
+ WORKDIR /app
17
+
18
+ # Get compiled binaries from builder's cargo install directory
19
+ COPY --from=builder /usr/src/app/dzmedia /app/dzmedia
20
+
21
+ ENV BIND_ADDR=0.0.0.0
22
+ ENV PORT=7860
23
+ EXPOSE 7860
24
+ CMD ["/app/dzmedia"]
Procfile ADDED
@@ -0,0 +1 @@
 
 
1
+ web: ./target/release/dzmedia
dockerignore ADDED
@@ -0,0 +1 @@
 
 
1
+ /target
fly.toml ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # fly.toml app configuration file generated for dzmedia on 2023-05-26T01:51:41+02:00
2
+ #
3
+ # See https://fly.io/docs/reference/configuration/ for information about how to use this file.
4
+ #
5
+
6
+ app = "dzmedia"
7
+ primary_region = "fra"
8
+ kill_signal = "SIGINT"
9
+ kill_timeout = "5s"
10
+
11
+ [experimental]
12
+ cmd = ["./dzmedia"]
13
+
14
+ [env]
15
+ PORT = "8080"
16
+ RUST_LOG = "tower_http=trace"
17
+
18
+ [[services]]
19
+ protocol = "tcp"
20
+ internal_port = 8080
21
+
22
+ [[services.ports]]
23
+ port = 80
24
+ handlers = ["http"]
25
+
26
+ [[services.ports]]
27
+ port = 443
28
+ handlers = ["tls", "http"]
29
+ [services.concurrency]
30
+ type = "connections"
31
+ hard_limit = 25
32
+ soft_limit = 20
33
+
34
+ [[services.tcp_checks]]
35
+ interval = "15s"
36
+ timeout = "2s"
37
+ grace_period = "1s"
38
+ restart_limit = 6
gitignore ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Cargo
2
+ # will have compiled files and executables
3
+ debug/
4
+ target/
5
+
6
+ # These are backup files generated by rustfmt
7
+ **/*.rs.bk
8
+
9
+ # MSVC Windows builds of rustc generate these, which store debugging information
10
+ *.pdb
11
+
12
+ .vscode
src/api.rs ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ use serde::{Serialize, Deserialize, de::DeserializeOwned};
2
+ use std::{env, marker::Sized, time::Instant, sync::Arc};
3
+ use thiserror::Error;
4
+ use serde_json::{json, value::from_value};
5
+ use reqwest::{Client, Response, cookie::Jar, Url, header::ACCEPT};
6
+
7
+ #[derive(Deserialize)]
8
+ struct DeezerResponse {
9
+ error: serde_json::Value,
10
+ results: serde_json::Value,
11
+ }
12
+
13
+ #[derive(Deserialize, Serialize, Debug)]
14
+ #[allow(non_camel_case_types)]
15
+ pub enum Format {
16
+ AAC_64,
17
+ AAC_96,
18
+ FLAC,
19
+ MP3_MISC,
20
+ MP3_32,
21
+ MP3_64,
22
+ MP3_128,
23
+ MP3_192,
24
+ MP3_256,
25
+ MP3_320,
26
+ SBC_256,
27
+ MP4_RA1,
28
+ MP4_RA2,
29
+ MP4_RA3,
30
+ }
31
+
32
+ #[derive(Serialize)]
33
+ struct DeezerFormat<'a> {
34
+ cipher: &'a str,
35
+ format: &'a Format,
36
+ }
37
+
38
+ #[derive(Error, Debug)]
39
+ pub enum APIError {
40
+ #[error("reqwest error")]
41
+ Reqwest(#[from] reqwest::Error),
42
+
43
+ #[error("Deezer API error (code: {code:?}, message: {message:?})")]
44
+ DeezerError {
45
+ code: String,
46
+ message: String,
47
+ },
48
+
49
+ #[error("Couldn't deserialize JSON response")]
50
+ JSON(#[from] serde_json::error::Error)
51
+ }
52
+
53
+ #[derive(Clone)]
54
+ pub struct APIClient {
55
+ client: Client,
56
+ pub license_token: String,
57
+ check_form: String,
58
+ renew_instant: Option<Instant>,
59
+ }
60
+
61
+ impl APIClient {
62
+ pub fn new() -> Self {
63
+ let arl = env::var("ARL").expect("ARL environment variable required");
64
+ Self::new_with_arl(arl)
65
+ }
66
+
67
+ pub fn new_with_arl(arl: String) -> Self {
68
+ let builder = Client::builder();
69
+
70
+ let cookie = format!("arl={}; Domain=.deezer.com", arl);
71
+ let url = "https://www.deezer.com".parse::<Url>().unwrap();
72
+
73
+ let jar = Jar::default();
74
+ jar.add_cookie_str(&cookie, &url);
75
+ let builder = builder.cookie_provider(Arc::new(jar));
76
+
77
+ Self {
78
+ client: builder.build().unwrap(),
79
+ license_token: String::new(),
80
+ check_form: String::new(),
81
+ renew_instant: None,
82
+ }
83
+ }
84
+
85
+ pub async fn user_data(&mut self) -> Result<serde_json::Value, APIError> {
86
+ self.no_renew_api_call("deezer.getUserData", &json!({})).await
87
+ }
88
+
89
+ async fn no_renew_api_call<P, T>(&mut self, method: &str, params: &P) -> Result<T, APIError>
90
+ where P: Serialize + ?Sized,
91
+ T: DeserializeOwned
92
+ {
93
+ let check_form;
94
+ if method == "deezer.getUserData" {
95
+ check_form = ""
96
+ } else {
97
+ check_form = &self.check_form;
98
+ }
99
+
100
+ let json: DeezerResponse = self.client.post("https://www.deezer.com/ajax/gw-light.php")
101
+ .query(&[
102
+ ("method", method),
103
+ ("input", "3"),
104
+ ("api_version", "1.0"),
105
+ ("api_token", check_form)
106
+ ])
107
+ .header(ACCEPT, "*/*")
108
+ .json(params)
109
+ .send()
110
+ .await?
111
+ .json()
112
+ .await?;
113
+
114
+ if let Some(error) = json.error.as_object() {
115
+ for (code, message) in error {
116
+ return Err(APIError::DeezerError {
117
+ code: code.clone(),
118
+ message: message.as_str().unwrap().to_string()
119
+ })
120
+ }
121
+ }
122
+
123
+ Ok(from_value(json.results)?)
124
+ }
125
+
126
+ pub async fn api_call<P, T>(&mut self, method: &str, params: &P) -> Result<T, APIError>
127
+ where P: Serialize + ?Sized,
128
+ T: DeserializeOwned
129
+ {
130
+ if let Some(i) = self.renew_instant {
131
+ if i.elapsed().as_secs() >= 3600 {
132
+ self.renew().await?;
133
+ }
134
+ } else {
135
+ self.renew().await?;
136
+ }
137
+
138
+ self.no_renew_api_call(method, params).await
139
+ }
140
+
141
+ async fn renew(&mut self) -> Result<(), APIError> {
142
+ let user_data: serde_json::Value = self.user_data().await?;
143
+
144
+ self.check_form = user_data["checkForm"].as_str().unwrap().to_string();
145
+ self.license_token = user_data["USER"]["OPTIONS"]["license_token"].as_str().unwrap().to_string();
146
+
147
+ self.renew_instant = Some(Instant::now());
148
+
149
+ Ok(())
150
+ }
151
+
152
+ pub async fn get_media(&self, formats: &Vec<Format>, track_tokens: Vec<&str>) -> Result<Response, reqwest::Error> {
153
+ let formats: Vec<DeezerFormat> = formats.iter().map(|f| DeezerFormat { cipher: "BF_CBC_STRIPE", format: f }).collect();
154
+
155
+ let req = json!({
156
+ "license_token": self.license_token,
157
+ "media": [{
158
+ "formats": formats,
159
+ "type": "FULL"
160
+ }],
161
+ "track_tokens": track_tokens
162
+ });
163
+
164
+ self.client.post("https://media.deezer.com/v1/get_url")
165
+ .json(&req)
166
+ .send()
167
+ .await
168
+ }
169
+ }
src/main.rs ADDED
@@ -0,0 +1,451 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ use axum::{
2
+ routing::{get, post},
3
+ http::StatusCode,
4
+ response::IntoResponse,
5
+ extract::{Json, State, Query},
6
+ Router,
7
+ };
8
+ use tower_http::{cors::{CorsLayer, Any}, compression::CompressionLayer, trace::TraceLayer};
9
+ use http::{Method, header::CONTENT_TYPE};
10
+ use serde_json::json;
11
+ use serde::Deserialize;
12
+ use std::sync::{Arc, RwLock};
13
+ use bytes::Bytes;
14
+ use futures_util::StreamExt;
15
+ use axum::body::Body;
16
+ use blowfish::Blowfish;
17
+ use cipher::{KeyIvInit, BlockDecryptMut};
18
+ use cipher::block_padding::NoPadding;
19
+ use cbc::Decryptor;
20
+ use reqwest::{cookie::Jar, Url};
21
+
22
+ mod api;
23
+ use api::{APIClient, APIError, Format};
24
+
25
+ #[derive(Deserialize)]
26
+ struct DeezerTrackList {
27
+ data: Vec<DeezerTrack>
28
+ }
29
+
30
+ #[derive(Deserialize)]
31
+ #[allow(non_snake_case)]
32
+ struct DeezerTrack {
33
+ TRACK_TOKEN: String
34
+ }
35
+
36
+ async fn root() -> &'static str {
37
+ "marecchione gay af"
38
+ }
39
+
40
+ #[derive(Debug, Deserialize)]
41
+ struct RequestParams {
42
+ formats: Vec<Format>,
43
+ ids: Vec<u32>,
44
+ arl: Option<String>,
45
+ }
46
+
47
+ async fn get_url(State(state): State<Arc<RwLock<APIClient>>>, Json(req): Json<RequestParams>) -> impl IntoResponse {
48
+ if req.formats.is_empty() {
49
+ return (StatusCode::BAD_REQUEST, "Format list cannot be empty".to_string());
50
+ }
51
+ if req.ids.is_empty() {
52
+ return (StatusCode::BAD_REQUEST, "ID list cannot be empty".to_string());
53
+ }
54
+
55
+ let mut client = if let Some(arl) = req.arl.clone().filter(|s| !s.trim().is_empty()) {
56
+ APIClient::new_with_arl(arl)
57
+ } else {
58
+ state.read().unwrap().clone()
59
+ };
60
+ let old_license = client.license_token.clone();
61
+
62
+ let resp: Result<DeezerTrackList, APIError> = client.api_call("song.getListData", &json!({"sng_ids":req.ids,"array_default":["SNG_ID","TRACK_TOKEN"]})).await;
63
+ let track_list;
64
+ match resp {
65
+ Ok(t) => track_list = t,
66
+ Err(e) => return (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
67
+ };
68
+
69
+ if track_list.data.is_empty() {
70
+ return (StatusCode::BAD_REQUEST, "No valid IDs found".to_string());
71
+ }
72
+
73
+ let track_tokens: Vec<&str> = track_list.data.iter().map(|t| t.TRACK_TOKEN.as_str()).collect();
74
+
75
+ let media_result = client.get_media(&req.formats, track_tokens).await;
76
+ let media_resp;
77
+ match media_result {
78
+ Ok(r) => media_resp = r,
79
+ Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "Error while getting response from media.deezer.com".to_string()),
80
+ };
81
+
82
+ if req.arl.is_none() && client.license_token != old_license {
83
+ let mut client_write = state.write().unwrap();
84
+ *client_write = client;
85
+ }
86
+
87
+ (StatusCode::OK, media_resp.text().await.unwrap())
88
+ }
89
+
90
+ #[derive(Debug, Deserialize)]
91
+ struct FetchParams {
92
+ url: String,
93
+ }
94
+
95
+ async fn fetch(Query(q): Query<FetchParams>) -> impl IntoResponse {
96
+ let parsed = match q.url.parse::<Url>() {
97
+ Ok(u) => u,
98
+ Err(_) => return (StatusCode::BAD_REQUEST, "Invalid url".to_string()).into_response(),
99
+ };
100
+
101
+ let host = parsed.host_str().unwrap_or("");
102
+ if !(host.ends_with(".dzcdn.net")) {
103
+ return (StatusCode::FORBIDDEN, "Host not allowed".to_string()).into_response();
104
+ }
105
+
106
+ let client = reqwest::Client::builder()
107
+ .timeout(std::time::Duration::from_secs(60))
108
+ .build()
109
+ .unwrap();
110
+
111
+ let resp = match client.get(parsed).send().await {
112
+ Ok(r) => r,
113
+ Err(_) => return (StatusCode::BAD_GATEWAY, "Upstream request failed".to_string()).into_response(),
114
+ };
115
+
116
+ let status = resp.status();
117
+ if !status.is_success() {
118
+ return (StatusCode::BAD_GATEWAY, format!("Upstream status: {}", status)).into_response();
119
+ }
120
+
121
+ let bytes = match resp.bytes().await {
122
+ Ok(b) => b,
123
+ Err(_) => return (StatusCode::BAD_GATEWAY, "Upstream read failed".to_string()).into_response(),
124
+ };
125
+
126
+ (
127
+ StatusCode::OK,
128
+ [(CONTENT_TYPE, "audio/mpeg")],
129
+ Bytes::from(bytes),
130
+ )
131
+ .into_response()
132
+ }
133
+
134
+ const SECRET: &str = "g4el58wc0zvf9na1";
135
+
136
+ fn blowfish_key(track_id: u32) -> [u8; 16] {
137
+ let md5hex = format!("{:x}", md5::compute(track_id.to_string().as_bytes()));
138
+ let md5hex = md5hex.as_bytes();
139
+ let secret = SECRET.as_bytes();
140
+ let mut out = [0u8; 16];
141
+ for i in 0..16 {
142
+ out[i] = md5hex[i] ^ md5hex[i + 16] ^ secret[i];
143
+ }
144
+ out
145
+ }
146
+
147
+ fn decrypt_stripe(block: &mut [u8], key: &[u8; 16]) -> Result<(), ()> {
148
+ let iv = [0u8, 1, 2, 3, 4, 5, 6, 7];
149
+ let mut dec = Decryptor::<Blowfish>::new_from_slices(key, &iv).map_err(|_| ())?;
150
+ dec.decrypt_padded_mut::<NoPadding>(block).map_err(|_| ())?;
151
+ Ok(())
152
+ }
153
+
154
+ #[derive(Debug, Deserialize)]
155
+ struct StreamParams {
156
+ id: u32,
157
+ format: Option<String>,
158
+ arl: Option<String>,
159
+ }
160
+
161
+ async fn stream(State(state): State<Arc<RwLock<APIClient>>>, Query(q): Query<StreamParams>) -> impl IntoResponse {
162
+ let formats = match q.format.as_deref().unwrap_or("MP3_128") {
163
+ "MP3_320" => vec![Format::MP3_320],
164
+ "MP3_MISC" => vec![Format::MP3_MISC],
165
+ "MP3_128" | _ => vec![Format::MP3_128],
166
+ };
167
+
168
+ let mut client = if let Some(arl) = q.arl.clone().filter(|s| !s.trim().is_empty()) {
169
+ APIClient::new_with_arl(arl)
170
+ } else {
171
+ state.read().unwrap().clone()
172
+ };
173
+
174
+ let resp: Result<DeezerTrackList, APIError> = client
175
+ .api_call(
176
+ "song.getListData",
177
+ &json!({"sng_ids":[q.id],"array_default":["SNG_ID","TRACK_TOKEN"]}),
178
+ )
179
+ .await;
180
+
181
+ let track_list = match resp {
182
+ Ok(t) => t,
183
+ Err(e) => return (StatusCode::BAD_GATEWAY, e.to_string()).into_response(),
184
+ };
185
+
186
+ if track_list.data.is_empty() {
187
+ return (StatusCode::BAD_REQUEST, "No valid ID".to_string()).into_response();
188
+ }
189
+
190
+ let track_token = track_list.data[0].TRACK_TOKEN.as_str();
191
+ let media_resp = match client.get_media(&formats, vec![track_token]).await {
192
+ Ok(r) => r,
193
+ Err(e) => return (StatusCode::BAD_GATEWAY, e.to_string()).into_response(),
194
+ };
195
+
196
+ let media_json: serde_json::Value = match media_resp.json().await {
197
+ Ok(v) => v,
198
+ Err(_) => return (StatusCode::BAD_GATEWAY, "Bad media response".to_string()).into_response(),
199
+ };
200
+
201
+ let url = media_json["data"][0]["media"][0]["sources"][0]["url"]
202
+ .as_str()
203
+ .unwrap_or("")
204
+ .to_string();
205
+
206
+ if url.is_empty() {
207
+ return (StatusCode::BAD_GATEWAY, "No url in media response".to_string()).into_response();
208
+ }
209
+
210
+ let http = reqwest::Client::builder()
211
+ .timeout(std::time::Duration::from_secs(60))
212
+ .build()
213
+ .unwrap();
214
+
215
+ let upstream = match http.get(url).send().await {
216
+ Ok(r) => r,
217
+ Err(_) => return (StatusCode::BAD_GATEWAY, "Upstream request failed".to_string()).into_response(),
218
+ };
219
+
220
+ if !upstream.status().is_success() {
221
+ return (StatusCode::BAD_GATEWAY, "Upstream status not OK".to_string()).into_response();
222
+ }
223
+
224
+ let key = blowfish_key(q.id);
225
+ let mut carry: Vec<u8> = Vec::with_capacity(4096);
226
+ let mut block_index: u64 = 0;
227
+
228
+ let mut upstream = upstream.bytes_stream().map_err(|_| ());
229
+
230
+ let out = async_stream::try_stream! {
231
+ while let Some(chunk) = upstream.next().await {
232
+ let chunk = chunk.map_err(|_| std::io::Error::new(std::io::ErrorKind::Other, "upstream"))?;
233
+ carry.extend_from_slice(&chunk);
234
+
235
+ while carry.len() >= 2048 {
236
+ let mut block = carry.drain(0..2048).collect::<Vec<u8>>();
237
+ if block_index % 3 == 0 {
238
+ let _ = decrypt_stripe(&mut block, &key);
239
+ }
240
+ block_index += 1;
241
+ yield Bytes::from(block);
242
+ }
243
+ }
244
+
245
+ if !carry.is_empty() {
246
+ yield Bytes::from(carry);
247
+ }
248
+ };
249
+
250
+ let body = Body::from_stream(out);
251
+ (StatusCode::OK, [(CONTENT_TYPE, "audio/mpeg")], body).into_response()
252
+ }
253
+
254
+ #[derive(Debug, Deserialize)]
255
+ struct UserDataReq {
256
+ arl: String,
257
+ }
258
+
259
+ async fn user_data(Json(req): Json<UserDataReq>) -> impl IntoResponse {
260
+ let arl = req.arl.trim().to_string();
261
+ if arl.is_empty() {
262
+ return (StatusCode::BAD_REQUEST, "ARL required".to_string()).into_response();
263
+ }
264
+
265
+ let mut client = APIClient::new_with_arl(arl);
266
+ let data = match client.user_data().await {
267
+ Ok(v) => v,
268
+ Err(e) => return (StatusCode::BAD_GATEWAY, e.to_string()).into_response(),
269
+ };
270
+
271
+ let token = data["checkForm"].as_str().unwrap_or("").to_string();
272
+ let uid = data["USER"]["USER_ID"].as_i64().map(|n| n.to_string()).unwrap_or_default();
273
+
274
+ (StatusCode::OK, Json(json!({ "token": token, "uid": uid }))).into_response()
275
+ }
276
+
277
+ #[derive(Debug, Deserialize)]
278
+ struct PlaylistsReq {
279
+ arl: String,
280
+ start: Option<u32>,
281
+ nb: Option<u32>,
282
+ }
283
+
284
+ async fn playlists(Json(req): Json<PlaylistsReq>) -> impl IntoResponse {
285
+ let arl = req.arl.trim().to_string();
286
+ if arl.is_empty() {
287
+ return (StatusCode::BAD_REQUEST, "ARL required".to_string()).into_response();
288
+ }
289
+
290
+ let mut client = APIClient::new_with_arl(arl);
291
+ let ud = match client.user_data().await {
292
+ Ok(v) => v,
293
+ Err(e) => return (StatusCode::BAD_GATEWAY, e.to_string()).into_response(),
294
+ };
295
+
296
+ let uid = ud["USER"]["USER_ID"].as_i64().unwrap_or(0);
297
+ if uid <= 0 {
298
+ return (StatusCode::BAD_GATEWAY, "No USER_ID".to_string()).into_response();
299
+ }
300
+
301
+ let start = req.start.unwrap_or(0);
302
+ let nb = req.nb.unwrap_or(50);
303
+
304
+ let res: Result<serde_json::Value, APIError> = client
305
+ .api_call("playlist.getList", &json!({"user_id":uid,"nb":nb,"start":start}))
306
+ .await;
307
+
308
+ match res {
309
+ Ok(v) => (StatusCode::OK, Json(v)).into_response(),
310
+ Err(e) => (StatusCode::BAD_GATEWAY, e.to_string()).into_response(),
311
+ }
312
+ }
313
+
314
+ #[derive(Debug, Deserialize)]
315
+ struct LoginReq {
316
+ email: String,
317
+ password_md5: String,
318
+ }
319
+
320
+ #[derive(Deserialize)]
321
+ struct GwResp {
322
+ error: serde_json::Value,
323
+ results: serde_json::Value,
324
+ }
325
+
326
+ async fn gw_light_call(
327
+ client: &reqwest::Client,
328
+ method: &str,
329
+ api_token: &str,
330
+ params: serde_json::Value,
331
+ ) -> Result<serde_json::Value, String> {
332
+ let r = client
333
+ .post("https://www.deezer.com/ajax/gw-light.php")
334
+ .query(&[
335
+ ("method", method),
336
+ ("input", "3"),
337
+ ("api_version", "1.0"),
338
+ ("api_token", api_token),
339
+ ])
340
+ .header(http::header::ACCEPT, "*/*")
341
+ .json(&params)
342
+ .send()
343
+ .await
344
+ .map_err(|_| "network".to_string())?;
345
+
346
+ let json: GwResp = r.json().await.map_err(|_| "parse".to_string())?;
347
+
348
+ if let Some(error) = json.error.as_object() {
349
+ for (code, message) in error {
350
+ let msg = message.as_str().unwrap_or("");
351
+ return Err(format!("{}:{}", code, msg));
352
+ }
353
+ }
354
+
355
+ Ok(json.results)
356
+ }
357
+
358
+ async fn login(Json(req): Json<LoginReq>) -> impl IntoResponse {
359
+ let email = req.email.trim().to_string();
360
+ let pass = req.password_md5.trim().to_string();
361
+
362
+ if email.is_empty() || pass.is_empty() {
363
+ return (StatusCode::BAD_REQUEST, "Email and password_md5 required".to_string()).into_response();
364
+ }
365
+
366
+ let url = "https://www.deezer.com".parse::<Url>().unwrap();
367
+ let jar = Jar::default();
368
+ let client = reqwest::Client::builder()
369
+ .cookie_provider(Arc::new(jar))
370
+ .timeout(std::time::Duration::from_secs(15))
371
+ .build()
372
+ .unwrap();
373
+
374
+ let ud = match gw_light_call(&client, "deezer.getUserData", "null", json!({})).await {
375
+ Ok(v) => v,
376
+ Err(e) => return (StatusCode::BAD_GATEWAY, e).into_response(),
377
+ };
378
+
379
+ let token = ud["checkForm"].as_str().unwrap_or("").to_string();
380
+ if token.is_empty() {
381
+ return (StatusCode::BAD_GATEWAY, "no checkForm".to_string()).into_response();
382
+ }
383
+
384
+ let cred = match gw_light_call(
385
+ &client,
386
+ "user.checkCredentials",
387
+ &token,
388
+ json!({
389
+ "login": email,
390
+ "password": pass,
391
+ "checkFormLogin": token
392
+ }),
393
+ )
394
+ .await
395
+ {
396
+ Ok(v) => v,
397
+ Err(e) => return (StatusCode::UNAUTHORIZED, e).into_response(),
398
+ };
399
+
400
+ let uid = cred["USER"]["USER_ID"].as_i64().map(|n| n.to_string()).unwrap_or_default();
401
+
402
+ let arl_v = match gw_light_call(&client, "user.getArl", &token, json!({})).await {
403
+ Ok(v) => v,
404
+ Err(e) => return (StatusCode::BAD_GATEWAY, e).into_response(),
405
+ };
406
+
407
+ let arl = arl_v.as_str().unwrap_or("").to_string();
408
+ if arl.len() < 20 {
409
+ return (StatusCode::BAD_GATEWAY, "no arl".to_string()).into_response();
410
+ }
411
+
412
+ (StatusCode::OK, Json(json!({ "arl": arl, "token": token, "uid": uid }))).into_response()
413
+ }
414
+
415
+ #[tokio::main]
416
+ async fn main() {
417
+ let bind_addr = std::env::var("BIND_ADDR").unwrap_or("[::]".to_string());
418
+ let port = std::env::var("PORT").unwrap_or("8000".to_string());
419
+ let port: u16 = port.parse().unwrap_or(8000);
420
+
421
+ let shared_state = Arc::new(RwLock::new(APIClient::new()));
422
+
423
+ let cors = CorsLayer::new()
424
+ .allow_origin(Any)
425
+ .allow_methods([Method::GET, Method::POST, Method::OPTIONS, Method::HEAD])
426
+ .allow_headers([CONTENT_TYPE]);
427
+
428
+ tracing_subscriber::fmt::init();
429
+
430
+ let app = Router::new()
431
+ .route("/", get(root))
432
+ .route("/get_url", post(get_url))
433
+ .route("/fetch", get(fetch))
434
+ .route("/stream", get(stream))
435
+ .route("/user_data", post(user_data))
436
+ .route("/playlists", post(playlists))
437
+ .route("/login", post(login))
438
+ .with_state(shared_state)
439
+ .layer(cors)
440
+ .layer(CompressionLayer::new())
441
+ .layer(TraceLayer::new_for_http());
442
+
443
+ let bind_addr = format!("{bind_addr}:{port}");
444
+ println!("Listening on {bind_addr}");
445
+
446
+ let listener = tokio::net::TcpListener::bind(bind_addr).await.unwrap();
447
+
448
+ axum::serve(listener, app)
449
+ .await
450
+ .unwrap();
451
+ }