Commit
Author: Kevin Schoon [me@kevinschoon.com]
Hash: 0853a1a1bbf99d937dae55e35c71e65ab63d1a58
Timestamp: Thu, 30 Nov 2023 18:25:25 +0000 (1 year ago)

+3281 -0 +/-17 browse
init
1diff --git a/Cargo.lock b/Cargo.lock
2new file mode 100644
3index 0000000..6bd3ec6
4--- /dev/null
5+++ b/Cargo.lock
6 @@ -0,0 +1,2407 @@
7+ # This file is automatically @generated by Cargo.
8+ # It is not intended for manual editing.
9+ version = 3
10+
11+ [[package]]
12+ name = "activitypub_federation"
13+ version = "0.4.7"
14+ source = "registry+https://github.com/rust-lang/crates.io-index"
15+ checksum = "41a0b760e573d41d9f6aec4280e4c0d273d4ce724eb00c3e4c9fb1b98d3ede47"
16+ dependencies = [
17+ "activitystreams-kinds",
18+ "anyhow",
19+ "async-trait",
20+ "axum",
21+ "base64 0.21.5",
22+ "bytes",
23+ "chrono",
24+ "derive_builder",
25+ "dyn-clone",
26+ "enum_delegate",
27+ "futures-core",
28+ "http",
29+ "http-signature-normalization",
30+ "http-signature-normalization-reqwest",
31+ "httpdate",
32+ "hyper",
33+ "itertools",
34+ "once_cell",
35+ "openssl",
36+ "pin-project-lite",
37+ "regex",
38+ "reqwest",
39+ "reqwest-middleware",
40+ "serde",
41+ "serde_json",
42+ "sha2",
43+ "thiserror",
44+ "tokio",
45+ "tower",
46+ "tracing",
47+ "url",
48+ ]
49+
50+ [[package]]
51+ name = "activitystreams-kinds"
52+ version = "0.3.0"
53+ source = "registry+https://github.com/rust-lang/crates.io-index"
54+ checksum = "e97dfe76efd8c0b113cc3580a6b5f4acba47662e3cfbbfcce081c9ac89798990"
55+ dependencies = [
56+ "serde",
57+ "url",
58+ ]
59+
60+ [[package]]
61+ name = "addr2line"
62+ version = "0.21.0"
63+ source = "registry+https://github.com/rust-lang/crates.io-index"
64+ checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
65+ dependencies = [
66+ "gimli",
67+ ]
68+
69+ [[package]]
70+ name = "adler"
71+ version = "1.0.2"
72+ source = "registry+https://github.com/rust-lang/crates.io-index"
73+ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
74+
75+ [[package]]
76+ name = "aho-corasick"
77+ version = "1.1.2"
78+ source = "registry+https://github.com/rust-lang/crates.io-index"
79+ checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
80+ dependencies = [
81+ "memchr",
82+ ]
83+
84+ [[package]]
85+ name = "android-tzdata"
86+ version = "0.1.1"
87+ source = "registry+https://github.com/rust-lang/crates.io-index"
88+ checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
89+
90+ [[package]]
91+ name = "android_system_properties"
92+ version = "0.1.5"
93+ source = "registry+https://github.com/rust-lang/crates.io-index"
94+ checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
95+ dependencies = [
96+ "libc",
97+ ]
98+
99+ [[package]]
100+ name = "anstream"
101+ version = "0.6.4"
102+ source = "registry+https://github.com/rust-lang/crates.io-index"
103+ checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44"
104+ dependencies = [
105+ "anstyle",
106+ "anstyle-parse",
107+ "anstyle-query",
108+ "anstyle-wincon",
109+ "colorchoice",
110+ "utf8parse",
111+ ]
112+
113+ [[package]]
114+ name = "anstyle"
115+ version = "1.0.4"
116+ source = "registry+https://github.com/rust-lang/crates.io-index"
117+ checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
118+
119+ [[package]]
120+ name = "anstyle-parse"
121+ version = "0.2.2"
122+ source = "registry+https://github.com/rust-lang/crates.io-index"
123+ checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140"
124+ dependencies = [
125+ "utf8parse",
126+ ]
127+
128+ [[package]]
129+ name = "anstyle-query"
130+ version = "1.0.0"
131+ source = "registry+https://github.com/rust-lang/crates.io-index"
132+ checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
133+ dependencies = [
134+ "windows-sys",
135+ ]
136+
137+ [[package]]
138+ name = "anstyle-wincon"
139+ version = "3.0.1"
140+ source = "registry+https://github.com/rust-lang/crates.io-index"
141+ checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
142+ dependencies = [
143+ "anstyle",
144+ "windows-sys",
145+ ]
146+
147+ [[package]]
148+ name = "anyhow"
149+ version = "1.0.75"
150+ source = "registry+https://github.com/rust-lang/crates.io-index"
151+ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
152+
153+ [[package]]
154+ name = "async-trait"
155+ version = "0.1.74"
156+ source = "registry+https://github.com/rust-lang/crates.io-index"
157+ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"
158+ dependencies = [
159+ "proc-macro2",
160+ "quote",
161+ "syn 2.0.39",
162+ ]
163+
164+ [[package]]
165+ name = "autocfg"
166+ version = "1.1.0"
167+ source = "registry+https://github.com/rust-lang/crates.io-index"
168+ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
169+
170+ [[package]]
171+ name = "axum"
172+ version = "0.6.20"
173+ source = "registry+https://github.com/rust-lang/crates.io-index"
174+ checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf"
175+ dependencies = [
176+ "async-trait",
177+ "axum-core",
178+ "axum-macros",
179+ "bitflags 1.3.2",
180+ "bytes",
181+ "futures-util",
182+ "headers",
183+ "http",
184+ "http-body",
185+ "hyper",
186+ "itoa",
187+ "matchit",
188+ "memchr",
189+ "mime",
190+ "percent-encoding",
191+ "pin-project-lite",
192+ "rustversion",
193+ "serde",
194+ "serde_json",
195+ "serde_path_to_error",
196+ "serde_urlencoded",
197+ "sync_wrapper",
198+ "tokio",
199+ "tower",
200+ "tower-layer",
201+ "tower-service",
202+ ]
203+
204+ [[package]]
205+ name = "axum-core"
206+ version = "0.3.4"
207+ source = "registry+https://github.com/rust-lang/crates.io-index"
208+ checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c"
209+ dependencies = [
210+ "async-trait",
211+ "bytes",
212+ "futures-util",
213+ "http",
214+ "http-body",
215+ "mime",
216+ "rustversion",
217+ "tower-layer",
218+ "tower-service",
219+ ]
220+
221+ [[package]]
222+ name = "axum-macros"
223+ version = "0.3.8"
224+ source = "registry+https://github.com/rust-lang/crates.io-index"
225+ checksum = "cdca6a10ecad987bda04e95606ef85a5417dcaac1a78455242d72e031e2b6b62"
226+ dependencies = [
227+ "heck",
228+ "proc-macro2",
229+ "quote",
230+ "syn 2.0.39",
231+ ]
232+
233+ [[package]]
234+ name = "backtrace"
235+ version = "0.3.69"
236+ source = "registry+https://github.com/rust-lang/crates.io-index"
237+ checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
238+ dependencies = [
239+ "addr2line",
240+ "cc",
241+ "cfg-if",
242+ "libc",
243+ "miniz_oxide",
244+ "object",
245+ "rustc-demangle",
246+ ]
247+
248+ [[package]]
249+ name = "base64"
250+ version = "0.13.1"
251+ source = "registry+https://github.com/rust-lang/crates.io-index"
252+ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
253+
254+ [[package]]
255+ name = "base64"
256+ version = "0.21.5"
257+ source = "registry+https://github.com/rust-lang/crates.io-index"
258+ checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"
259+
260+ [[package]]
261+ name = "bitflags"
262+ version = "1.3.2"
263+ source = "registry+https://github.com/rust-lang/crates.io-index"
264+ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
265+
266+ [[package]]
267+ name = "bitflags"
268+ version = "2.4.1"
269+ source = "registry+https://github.com/rust-lang/crates.io-index"
270+ checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
271+
272+ [[package]]
273+ name = "block-buffer"
274+ version = "0.10.4"
275+ source = "registry+https://github.com/rust-lang/crates.io-index"
276+ checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
277+ dependencies = [
278+ "generic-array",
279+ ]
280+
281+ [[package]]
282+ name = "bstr"
283+ version = "1.8.0"
284+ source = "registry+https://github.com/rust-lang/crates.io-index"
285+ checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c"
286+ dependencies = [
287+ "memchr",
288+ "serde",
289+ ]
290+
291+ [[package]]
292+ name = "bumpalo"
293+ version = "3.14.0"
294+ source = "registry+https://github.com/rust-lang/crates.io-index"
295+ checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
296+
297+ [[package]]
298+ name = "bytes"
299+ version = "1.5.0"
300+ source = "registry+https://github.com/rust-lang/crates.io-index"
301+ checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
302+
303+ [[package]]
304+ name = "cc"
305+ version = "1.0.83"
306+ source = "registry+https://github.com/rust-lang/crates.io-index"
307+ checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
308+ dependencies = [
309+ "libc",
310+ ]
311+
312+ [[package]]
313+ name = "cfg-if"
314+ version = "1.0.0"
315+ source = "registry+https://github.com/rust-lang/crates.io-index"
316+ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
317+
318+ [[package]]
319+ name = "chrono"
320+ version = "0.4.31"
321+ source = "registry+https://github.com/rust-lang/crates.io-index"
322+ checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
323+ dependencies = [
324+ "android-tzdata",
325+ "iana-time-zone",
326+ "js-sys",
327+ "num-traits",
328+ "wasm-bindgen",
329+ "windows-targets",
330+ ]
331+
332+ [[package]]
333+ name = "chrono-tz"
334+ version = "0.8.4"
335+ source = "registry+https://github.com/rust-lang/crates.io-index"
336+ checksum = "e23185c0e21df6ed832a12e2bda87c7d1def6842881fb634a8511ced741b0d76"
337+ dependencies = [
338+ "chrono",
339+ "chrono-tz-build",
340+ "phf",
341+ ]
342+
343+ [[package]]
344+ name = "chrono-tz-build"
345+ version = "0.2.1"
346+ source = "registry+https://github.com/rust-lang/crates.io-index"
347+ checksum = "433e39f13c9a060046954e0592a8d0a4bcb1040125cbf91cb8ee58964cfb350f"
348+ dependencies = [
349+ "parse-zoneinfo",
350+ "phf",
351+ "phf_codegen",
352+ ]
353+
354+ [[package]]
355+ name = "clap"
356+ version = "4.4.8"
357+ source = "registry+https://github.com/rust-lang/crates.io-index"
358+ checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64"
359+ dependencies = [
360+ "clap_builder",
361+ ]
362+
363+ [[package]]
364+ name = "clap_builder"
365+ version = "4.4.8"
366+ source = "registry+https://github.com/rust-lang/crates.io-index"
367+ checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc"
368+ dependencies = [
369+ "anstream",
370+ "anstyle",
371+ "clap_lex",
372+ "strsim",
373+ ]
374+
375+ [[package]]
376+ name = "clap_lex"
377+ version = "0.6.0"
378+ source = "registry+https://github.com/rust-lang/crates.io-index"
379+ checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
380+
381+ [[package]]
382+ name = "colorchoice"
383+ version = "1.0.0"
384+ source = "registry+https://github.com/rust-lang/crates.io-index"
385+ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
386+
387+ [[package]]
388+ name = "core-foundation"
389+ version = "0.9.3"
390+ source = "registry+https://github.com/rust-lang/crates.io-index"
391+ checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
392+ dependencies = [
393+ "core-foundation-sys",
394+ "libc",
395+ ]
396+
397+ [[package]]
398+ name = "core-foundation-sys"
399+ version = "0.8.4"
400+ source = "registry+https://github.com/rust-lang/crates.io-index"
401+ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
402+
403+ [[package]]
404+ name = "cpufeatures"
405+ version = "0.2.11"
406+ source = "registry+https://github.com/rust-lang/crates.io-index"
407+ checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0"
408+ dependencies = [
409+ "libc",
410+ ]
411+
412+ [[package]]
413+ name = "crypto-common"
414+ version = "0.1.6"
415+ source = "registry+https://github.com/rust-lang/crates.io-index"
416+ checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
417+ dependencies = [
418+ "generic-array",
419+ "typenum",
420+ ]
421+
422+ [[package]]
423+ name = "darling"
424+ version = "0.14.4"
425+ source = "registry+https://github.com/rust-lang/crates.io-index"
426+ checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
427+ dependencies = [
428+ "darling_core",
429+ "darling_macro",
430+ ]
431+
432+ [[package]]
433+ name = "darling_core"
434+ version = "0.14.4"
435+ source = "registry+https://github.com/rust-lang/crates.io-index"
436+ checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
437+ dependencies = [
438+ "fnv",
439+ "ident_case",
440+ "proc-macro2",
441+ "quote",
442+ "strsim",
443+ "syn 1.0.109",
444+ ]
445+
446+ [[package]]
447+ name = "darling_macro"
448+ version = "0.14.4"
449+ source = "registry+https://github.com/rust-lang/crates.io-index"
450+ checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
451+ dependencies = [
452+ "darling_core",
453+ "quote",
454+ "syn 1.0.109",
455+ ]
456+
457+ [[package]]
458+ name = "derive_builder"
459+ version = "0.12.0"
460+ source = "registry+https://github.com/rust-lang/crates.io-index"
461+ checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8"
462+ dependencies = [
463+ "derive_builder_macro",
464+ ]
465+
466+ [[package]]
467+ name = "derive_builder_core"
468+ version = "0.12.0"
469+ source = "registry+https://github.com/rust-lang/crates.io-index"
470+ checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f"
471+ dependencies = [
472+ "darling",
473+ "proc-macro2",
474+ "quote",
475+ "syn 1.0.109",
476+ ]
477+
478+ [[package]]
479+ name = "derive_builder_macro"
480+ version = "0.12.0"
481+ source = "registry+https://github.com/rust-lang/crates.io-index"
482+ checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e"
483+ dependencies = [
484+ "derive_builder_core",
485+ "syn 1.0.109",
486+ ]
487+
488+ [[package]]
489+ name = "deunicode"
490+ version = "1.4.1"
491+ source = "registry+https://github.com/rust-lang/crates.io-index"
492+ checksum = "6a1abaf4d861455be59f64fd2b55606cb151fce304ede7165f410243ce96bde6"
493+
494+ [[package]]
495+ name = "digest"
496+ version = "0.10.7"
497+ source = "registry+https://github.com/rust-lang/crates.io-index"
498+ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
499+ dependencies = [
500+ "block-buffer",
501+ "crypto-common",
502+ ]
503+
504+ [[package]]
505+ name = "dyn-clone"
506+ version = "1.0.16"
507+ source = "registry+https://github.com/rust-lang/crates.io-index"
508+ checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d"
509+
510+ [[package]]
511+ name = "either"
512+ version = "1.9.0"
513+ source = "registry+https://github.com/rust-lang/crates.io-index"
514+ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
515+
516+ [[package]]
517+ name = "encoding_rs"
518+ version = "0.8.33"
519+ source = "registry+https://github.com/rust-lang/crates.io-index"
520+ checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
521+ dependencies = [
522+ "cfg-if",
523+ ]
524+
525+ [[package]]
526+ name = "enum_delegate"
527+ version = "0.2.0"
528+ source = "registry+https://github.com/rust-lang/crates.io-index"
529+ checksum = "a8ea75f31022cba043afe037940d73684327e915f88f62478e778c3de914cd0a"
530+ dependencies = [
531+ "enum_delegate_lib",
532+ "proc-macro2",
533+ "quote",
534+ "syn 1.0.109",
535+ ]
536+
537+ [[package]]
538+ name = "enum_delegate_lib"
539+ version = "0.2.0"
540+ source = "registry+https://github.com/rust-lang/crates.io-index"
541+ checksum = "2e1f6c3800b304a6be0012039e2a45a322a093539c45ab818d9e6895a39c90fe"
542+ dependencies = [
543+ "proc-macro2",
544+ "quote",
545+ "rand",
546+ "syn 1.0.109",
547+ ]
548+
549+ [[package]]
550+ name = "env_logger"
551+ version = "0.10.1"
552+ source = "registry+https://github.com/rust-lang/crates.io-index"
553+ checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece"
554+ dependencies = [
555+ "humantime",
556+ "is-terminal",
557+ "log",
558+ "regex",
559+ "termcolor",
560+ ]
561+
562+ [[package]]
563+ name = "equivalent"
564+ version = "1.0.1"
565+ source = "registry+https://github.com/rust-lang/crates.io-index"
566+ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
567+
568+ [[package]]
569+ name = "errno"
570+ version = "0.3.7"
571+ source = "registry+https://github.com/rust-lang/crates.io-index"
572+ checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8"
573+ dependencies = [
574+ "libc",
575+ "windows-sys",
576+ ]
577+
578+ [[package]]
579+ name = "fastrand"
580+ version = "2.0.1"
581+ source = "registry+https://github.com/rust-lang/crates.io-index"
582+ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
583+
584+ [[package]]
585+ name = "fnv"
586+ version = "1.0.7"
587+ source = "registry+https://github.com/rust-lang/crates.io-index"
588+ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
589+
590+ [[package]]
591+ name = "foreign-types"
592+ version = "0.3.2"
593+ source = "registry+https://github.com/rust-lang/crates.io-index"
594+ checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
595+ dependencies = [
596+ "foreign-types-shared",
597+ ]
598+
599+ [[package]]
600+ name = "foreign-types-shared"
601+ version = "0.1.1"
602+ source = "registry+https://github.com/rust-lang/crates.io-index"
603+ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
604+
605+ [[package]]
606+ name = "form_urlencoded"
607+ version = "1.2.0"
608+ source = "registry+https://github.com/rust-lang/crates.io-index"
609+ checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
610+ dependencies = [
611+ "percent-encoding",
612+ ]
613+
614+ [[package]]
615+ name = "futures-channel"
616+ version = "0.3.29"
617+ source = "registry+https://github.com/rust-lang/crates.io-index"
618+ checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
619+ dependencies = [
620+ "futures-core",
621+ ]
622+
623+ [[package]]
624+ name = "futures-core"
625+ version = "0.3.29"
626+ source = "registry+https://github.com/rust-lang/crates.io-index"
627+ checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
628+
629+ [[package]]
630+ name = "futures-io"
631+ version = "0.3.29"
632+ source = "registry+https://github.com/rust-lang/crates.io-index"
633+ checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
634+
635+ [[package]]
636+ name = "futures-macro"
637+ version = "0.3.29"
638+ source = "registry+https://github.com/rust-lang/crates.io-index"
639+ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
640+ dependencies = [
641+ "proc-macro2",
642+ "quote",
643+ "syn 2.0.39",
644+ ]
645+
646+ [[package]]
647+ name = "futures-sink"
648+ version = "0.3.29"
649+ source = "registry+https://github.com/rust-lang/crates.io-index"
650+ checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
651+
652+ [[package]]
653+ name = "futures-task"
654+ version = "0.3.29"
655+ source = "registry+https://github.com/rust-lang/crates.io-index"
656+ checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
657+
658+ [[package]]
659+ name = "futures-util"
660+ version = "0.3.29"
661+ source = "registry+https://github.com/rust-lang/crates.io-index"
662+ checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
663+ dependencies = [
664+ "futures-core",
665+ "futures-io",
666+ "futures-macro",
667+ "futures-sink",
668+ "futures-task",
669+ "memchr",
670+ "pin-project-lite",
671+ "pin-utils",
672+ "slab",
673+ ]
674+
675+ [[package]]
676+ name = "generic-array"
677+ version = "0.14.7"
678+ source = "registry+https://github.com/rust-lang/crates.io-index"
679+ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
680+ dependencies = [
681+ "typenum",
682+ "version_check",
683+ ]
684+
685+ [[package]]
686+ name = "getrandom"
687+ version = "0.2.11"
688+ source = "registry+https://github.com/rust-lang/crates.io-index"
689+ checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
690+ dependencies = [
691+ "cfg-if",
692+ "libc",
693+ "wasi",
694+ ]
695+
696+ [[package]]
697+ name = "gimli"
698+ version = "0.28.0"
699+ source = "registry+https://github.com/rust-lang/crates.io-index"
700+ checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
701+
702+ [[package]]
703+ name = "globset"
704+ version = "0.4.13"
705+ source = "registry+https://github.com/rust-lang/crates.io-index"
706+ checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d"
707+ dependencies = [
708+ "aho-corasick",
709+ "bstr",
710+ "fnv",
711+ "log",
712+ "regex",
713+ ]
714+
715+ [[package]]
716+ name = "globwalk"
717+ version = "0.8.1"
718+ source = "registry+https://github.com/rust-lang/crates.io-index"
719+ checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc"
720+ dependencies = [
721+ "bitflags 1.3.2",
722+ "ignore",
723+ "walkdir",
724+ ]
725+
726+ [[package]]
727+ name = "h2"
728+ version = "0.3.22"
729+ source = "registry+https://github.com/rust-lang/crates.io-index"
730+ checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178"
731+ dependencies = [
732+ "bytes",
733+ "fnv",
734+ "futures-core",
735+ "futures-sink",
736+ "futures-util",
737+ "http",
738+ "indexmap",
739+ "slab",
740+ "tokio",
741+ "tokio-util",
742+ "tracing",
743+ ]
744+
745+ [[package]]
746+ name = "hashbrown"
747+ version = "0.14.2"
748+ source = "registry+https://github.com/rust-lang/crates.io-index"
749+ checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
750+
751+ [[package]]
752+ name = "headers"
753+ version = "0.3.9"
754+ source = "registry+https://github.com/rust-lang/crates.io-index"
755+ checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270"
756+ dependencies = [
757+ "base64 0.21.5",
758+ "bytes",
759+ "headers-core",
760+ "http",
761+ "httpdate",
762+ "mime",
763+ "sha1",
764+ ]
765+
766+ [[package]]
767+ name = "headers-core"
768+ version = "0.2.0"
769+ source = "registry+https://github.com/rust-lang/crates.io-index"
770+ checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
771+ dependencies = [
772+ "http",
773+ ]
774+
775+ [[package]]
776+ name = "heck"
777+ version = "0.4.1"
778+ source = "registry+https://github.com/rust-lang/crates.io-index"
779+ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
780+
781+ [[package]]
782+ name = "hermit-abi"
783+ version = "0.3.3"
784+ source = "registry+https://github.com/rust-lang/crates.io-index"
785+ checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
786+
787+ [[package]]
788+ name = "http"
789+ version = "0.2.11"
790+ source = "registry+https://github.com/rust-lang/crates.io-index"
791+ checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb"
792+ dependencies = [
793+ "bytes",
794+ "fnv",
795+ "itoa",
796+ ]
797+
798+ [[package]]
799+ name = "http-body"
800+ version = "0.4.5"
801+ source = "registry+https://github.com/rust-lang/crates.io-index"
802+ checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
803+ dependencies = [
804+ "bytes",
805+ "http",
806+ "pin-project-lite",
807+ ]
808+
809+ [[package]]
810+ name = "http-signature-normalization"
811+ version = "0.7.0"
812+ source = "registry+https://github.com/rust-lang/crates.io-index"
813+ checksum = "b95e3149194de5f3f9d5225bcc6a8677979f8ff8ce39c85654730ad4824f101e"
814+ dependencies = [
815+ "httpdate",
816+ ]
817+
818+ [[package]]
819+ name = "http-signature-normalization-reqwest"
820+ version = "0.8.0"
821+ source = "registry+https://github.com/rust-lang/crates.io-index"
822+ checksum = "3c382c69a07b21accae86298d520579403af6479b1cd1c389e3ee11f01d48627"
823+ dependencies = [
824+ "base64 0.13.1",
825+ "http-signature-normalization",
826+ "httpdate",
827+ "reqwest",
828+ "reqwest-middleware",
829+ "sha2",
830+ "thiserror",
831+ "tokio",
832+ ]
833+
834+ [[package]]
835+ name = "httparse"
836+ version = "1.8.0"
837+ source = "registry+https://github.com/rust-lang/crates.io-index"
838+ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
839+
840+ [[package]]
841+ name = "httpdate"
842+ version = "1.0.3"
843+ source = "registry+https://github.com/rust-lang/crates.io-index"
844+ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
845+
846+ [[package]]
847+ name = "humansize"
848+ version = "2.1.3"
849+ source = "registry+https://github.com/rust-lang/crates.io-index"
850+ checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7"
851+ dependencies = [
852+ "libm",
853+ ]
854+
855+ [[package]]
856+ name = "humantime"
857+ version = "2.1.0"
858+ source = "registry+https://github.com/rust-lang/crates.io-index"
859+ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
860+
861+ [[package]]
862+ name = "hyper"
863+ version = "0.14.27"
864+ source = "registry+https://github.com/rust-lang/crates.io-index"
865+ checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
866+ dependencies = [
867+ "bytes",
868+ "futures-channel",
869+ "futures-core",
870+ "futures-util",
871+ "h2",
872+ "http",
873+ "http-body",
874+ "httparse",
875+ "httpdate",
876+ "itoa",
877+ "pin-project-lite",
878+ "socket2 0.4.10",
879+ "tokio",
880+ "tower-service",
881+ "tracing",
882+ "want",
883+ ]
884+
885+ [[package]]
886+ name = "hyper-tls"
887+ version = "0.5.0"
888+ source = "registry+https://github.com/rust-lang/crates.io-index"
889+ checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
890+ dependencies = [
891+ "bytes",
892+ "hyper",
893+ "native-tls",
894+ "tokio",
895+ "tokio-native-tls",
896+ ]
897+
898+ [[package]]
899+ name = "iana-time-zone"
900+ version = "0.1.58"
901+ source = "registry+https://github.com/rust-lang/crates.io-index"
902+ checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20"
903+ dependencies = [
904+ "android_system_properties",
905+ "core-foundation-sys",
906+ "iana-time-zone-haiku",
907+ "js-sys",
908+ "wasm-bindgen",
909+ "windows-core",
910+ ]
911+
912+ [[package]]
913+ name = "iana-time-zone-haiku"
914+ version = "0.1.2"
915+ source = "registry+https://github.com/rust-lang/crates.io-index"
916+ checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
917+ dependencies = [
918+ "cc",
919+ ]
920+
921+ [[package]]
922+ name = "ident_case"
923+ version = "1.0.1"
924+ source = "registry+https://github.com/rust-lang/crates.io-index"
925+ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
926+
927+ [[package]]
928+ name = "idna"
929+ version = "0.4.0"
930+ source = "registry+https://github.com/rust-lang/crates.io-index"
931+ checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
932+ dependencies = [
933+ "unicode-bidi",
934+ "unicode-normalization",
935+ ]
936+
937+ [[package]]
938+ name = "ignore"
939+ version = "0.4.20"
940+ source = "registry+https://github.com/rust-lang/crates.io-index"
941+ checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492"
942+ dependencies = [
943+ "globset",
944+ "lazy_static",
945+ "log",
946+ "memchr",
947+ "regex",
948+ "same-file",
949+ "thread_local",
950+ "walkdir",
951+ "winapi-util",
952+ ]
953+
954+ [[package]]
955+ name = "indexmap"
956+ version = "2.1.0"
957+ source = "registry+https://github.com/rust-lang/crates.io-index"
958+ checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
959+ dependencies = [
960+ "equivalent",
961+ "hashbrown",
962+ ]
963+
964+ [[package]]
965+ name = "ipnet"
966+ version = "2.9.0"
967+ source = "registry+https://github.com/rust-lang/crates.io-index"
968+ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
969+
970+ [[package]]
971+ name = "is-terminal"
972+ version = "0.4.9"
973+ source = "registry+https://github.com/rust-lang/crates.io-index"
974+ checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
975+ dependencies = [
976+ "hermit-abi",
977+ "rustix",
978+ "windows-sys",
979+ ]
980+
981+ [[package]]
982+ name = "itertools"
983+ version = "0.10.5"
984+ source = "registry+https://github.com/rust-lang/crates.io-index"
985+ checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
986+ dependencies = [
987+ "either",
988+ ]
989+
990+ [[package]]
991+ name = "itoa"
992+ version = "1.0.9"
993+ source = "registry+https://github.com/rust-lang/crates.io-index"
994+ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
995+
996+ [[package]]
997+ name = "js-sys"
998+ version = "0.3.65"
999+ source = "registry+https://github.com/rust-lang/crates.io-index"
1000+ checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8"
1001+ dependencies = [
1002+ "wasm-bindgen",
1003+ ]
1004+
1005+ [[package]]
1006+ name = "lazy_static"
1007+ version = "1.4.0"
1008+ source = "registry+https://github.com/rust-lang/crates.io-index"
1009+ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
1010+
1011+ [[package]]
1012+ name = "libc"
1013+ version = "0.2.150"
1014+ source = "registry+https://github.com/rust-lang/crates.io-index"
1015+ checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
1016+
1017+ [[package]]
1018+ name = "libm"
1019+ version = "0.2.8"
1020+ source = "registry+https://github.com/rust-lang/crates.io-index"
1021+ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
1022+
1023+ [[package]]
1024+ name = "linux-raw-sys"
1025+ version = "0.4.11"
1026+ source = "registry+https://github.com/rust-lang/crates.io-index"
1027+ checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829"
1028+
1029+ [[package]]
1030+ name = "lock_api"
1031+ version = "0.4.11"
1032+ source = "registry+https://github.com/rust-lang/crates.io-index"
1033+ checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
1034+ dependencies = [
1035+ "autocfg",
1036+ "scopeguard",
1037+ ]
1038+
1039+ [[package]]
1040+ name = "log"
1041+ version = "0.4.20"
1042+ source = "registry+https://github.com/rust-lang/crates.io-index"
1043+ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
1044+
1045+ [[package]]
1046+ name = "matchit"
1047+ version = "0.7.3"
1048+ source = "registry+https://github.com/rust-lang/crates.io-index"
1049+ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
1050+
1051+ [[package]]
1052+ name = "memchr"
1053+ version = "2.6.4"
1054+ source = "registry+https://github.com/rust-lang/crates.io-index"
1055+ checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
1056+
1057+ [[package]]
1058+ name = "mime"
1059+ version = "0.3.17"
1060+ source = "registry+https://github.com/rust-lang/crates.io-index"
1061+ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
1062+
1063+ [[package]]
1064+ name = "mime_guess"
1065+ version = "2.0.4"
1066+ source = "registry+https://github.com/rust-lang/crates.io-index"
1067+ checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
1068+ dependencies = [
1069+ "mime",
1070+ "unicase",
1071+ ]
1072+
1073+ [[package]]
1074+ name = "miniz_oxide"
1075+ version = "0.7.1"
1076+ source = "registry+https://github.com/rust-lang/crates.io-index"
1077+ checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
1078+ dependencies = [
1079+ "adler",
1080+ ]
1081+
1082+ [[package]]
1083+ name = "mio"
1084+ version = "0.8.9"
1085+ source = "registry+https://github.com/rust-lang/crates.io-index"
1086+ checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
1087+ dependencies = [
1088+ "libc",
1089+ "wasi",
1090+ "windows-sys",
1091+ ]
1092+
1093+ [[package]]
1094+ name = "native-tls"
1095+ version = "0.2.11"
1096+ source = "registry+https://github.com/rust-lang/crates.io-index"
1097+ checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
1098+ dependencies = [
1099+ "lazy_static",
1100+ "libc",
1101+ "log",
1102+ "openssl",
1103+ "openssl-probe",
1104+ "openssl-sys",
1105+ "schannel",
1106+ "security-framework",
1107+ "security-framework-sys",
1108+ "tempfile",
1109+ ]
1110+
1111+ [[package]]
1112+ name = "nu-ansi-term"
1113+ version = "0.46.0"
1114+ source = "registry+https://github.com/rust-lang/crates.io-index"
1115+ checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
1116+ dependencies = [
1117+ "overload",
1118+ "winapi",
1119+ ]
1120+
1121+ [[package]]
1122+ name = "num-traits"
1123+ version = "0.2.17"
1124+ source = "registry+https://github.com/rust-lang/crates.io-index"
1125+ checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
1126+ dependencies = [
1127+ "autocfg",
1128+ ]
1129+
1130+ [[package]]
1131+ name = "num_cpus"
1132+ version = "1.16.0"
1133+ source = "registry+https://github.com/rust-lang/crates.io-index"
1134+ checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
1135+ dependencies = [
1136+ "hermit-abi",
1137+ "libc",
1138+ ]
1139+
1140+ [[package]]
1141+ name = "object"
1142+ version = "0.32.1"
1143+ source = "registry+https://github.com/rust-lang/crates.io-index"
1144+ checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
1145+ dependencies = [
1146+ "memchr",
1147+ ]
1148+
1149+ [[package]]
1150+ name = "once_cell"
1151+ version = "1.18.0"
1152+ source = "registry+https://github.com/rust-lang/crates.io-index"
1153+ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
1154+
1155+ [[package]]
1156+ name = "openssl"
1157+ version = "0.10.59"
1158+ source = "registry+https://github.com/rust-lang/crates.io-index"
1159+ checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33"
1160+ dependencies = [
1161+ "bitflags 2.4.1",
1162+ "cfg-if",
1163+ "foreign-types",
1164+ "libc",
1165+ "once_cell",
1166+ "openssl-macros",
1167+ "openssl-sys",
1168+ ]
1169+
1170+ [[package]]
1171+ name = "openssl-macros"
1172+ version = "0.1.1"
1173+ source = "registry+https://github.com/rust-lang/crates.io-index"
1174+ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
1175+ dependencies = [
1176+ "proc-macro2",
1177+ "quote",
1178+ "syn 2.0.39",
1179+ ]
1180+
1181+ [[package]]
1182+ name = "openssl-probe"
1183+ version = "0.1.5"
1184+ source = "registry+https://github.com/rust-lang/crates.io-index"
1185+ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
1186+
1187+ [[package]]
1188+ name = "openssl-sys"
1189+ version = "0.9.95"
1190+ source = "registry+https://github.com/rust-lang/crates.io-index"
1191+ checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9"
1192+ dependencies = [
1193+ "cc",
1194+ "libc",
1195+ "pkg-config",
1196+ "vcpkg",
1197+ ]
1198+
1199+ [[package]]
1200+ name = "overload"
1201+ version = "0.1.1"
1202+ source = "registry+https://github.com/rust-lang/crates.io-index"
1203+ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
1204+
1205+ [[package]]
1206+ name = "parking_lot"
1207+ version = "0.12.1"
1208+ source = "registry+https://github.com/rust-lang/crates.io-index"
1209+ checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
1210+ dependencies = [
1211+ "lock_api",
1212+ "parking_lot_core",
1213+ ]
1214+
1215+ [[package]]
1216+ name = "parking_lot_core"
1217+ version = "0.9.9"
1218+ source = "registry+https://github.com/rust-lang/crates.io-index"
1219+ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
1220+ dependencies = [
1221+ "cfg-if",
1222+ "libc",
1223+ "redox_syscall",
1224+ "smallvec",
1225+ "windows-targets",
1226+ ]
1227+
1228+ [[package]]
1229+ name = "parse-zoneinfo"
1230+ version = "0.3.0"
1231+ source = "registry+https://github.com/rust-lang/crates.io-index"
1232+ checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41"
1233+ dependencies = [
1234+ "regex",
1235+ ]
1236+
1237+ [[package]]
1238+ name = "percent-encoding"
1239+ version = "2.3.0"
1240+ source = "registry+https://github.com/rust-lang/crates.io-index"
1241+ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
1242+
1243+ [[package]]
1244+ name = "pest"
1245+ version = "2.7.5"
1246+ source = "registry+https://github.com/rust-lang/crates.io-index"
1247+ checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5"
1248+ dependencies = [
1249+ "memchr",
1250+ "thiserror",
1251+ "ucd-trie",
1252+ ]
1253+
1254+ [[package]]
1255+ name = "pest_derive"
1256+ version = "2.7.5"
1257+ source = "registry+https://github.com/rust-lang/crates.io-index"
1258+ checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2"
1259+ dependencies = [
1260+ "pest",
1261+ "pest_generator",
1262+ ]
1263+
1264+ [[package]]
1265+ name = "pest_generator"
1266+ version = "2.7.5"
1267+ source = "registry+https://github.com/rust-lang/crates.io-index"
1268+ checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227"
1269+ dependencies = [
1270+ "pest",
1271+ "pest_meta",
1272+ "proc-macro2",
1273+ "quote",
1274+ "syn 2.0.39",
1275+ ]
1276+
1277+ [[package]]
1278+ name = "pest_meta"
1279+ version = "2.7.5"
1280+ source = "registry+https://github.com/rust-lang/crates.io-index"
1281+ checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6"
1282+ dependencies = [
1283+ "once_cell",
1284+ "pest",
1285+ "sha2",
1286+ ]
1287+
1288+ [[package]]
1289+ name = "phf"
1290+ version = "0.11.2"
1291+ source = "registry+https://github.com/rust-lang/crates.io-index"
1292+ checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
1293+ dependencies = [
1294+ "phf_shared",
1295+ ]
1296+
1297+ [[package]]
1298+ name = "phf_codegen"
1299+ version = "0.11.2"
1300+ source = "registry+https://github.com/rust-lang/crates.io-index"
1301+ checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a"
1302+ dependencies = [
1303+ "phf_generator",
1304+ "phf_shared",
1305+ ]
1306+
1307+ [[package]]
1308+ name = "phf_generator"
1309+ version = "0.11.2"
1310+ source = "registry+https://github.com/rust-lang/crates.io-index"
1311+ checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
1312+ dependencies = [
1313+ "phf_shared",
1314+ "rand",
1315+ ]
1316+
1317+ [[package]]
1318+ name = "phf_shared"
1319+ version = "0.11.2"
1320+ source = "registry+https://github.com/rust-lang/crates.io-index"
1321+ checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
1322+ dependencies = [
1323+ "siphasher",
1324+ ]
1325+
1326+ [[package]]
1327+ name = "pin-project"
1328+ version = "1.1.3"
1329+ source = "registry+https://github.com/rust-lang/crates.io-index"
1330+ checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422"
1331+ dependencies = [
1332+ "pin-project-internal",
1333+ ]
1334+
1335+ [[package]]
1336+ name = "pin-project-internal"
1337+ version = "1.1.3"
1338+ source = "registry+https://github.com/rust-lang/crates.io-index"
1339+ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
1340+ dependencies = [
1341+ "proc-macro2",
1342+ "quote",
1343+ "syn 2.0.39",
1344+ ]
1345+
1346+ [[package]]
1347+ name = "pin-project-lite"
1348+ version = "0.2.13"
1349+ source = "registry+https://github.com/rust-lang/crates.io-index"
1350+ checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
1351+
1352+ [[package]]
1353+ name = "pin-utils"
1354+ version = "0.1.0"
1355+ source = "registry+https://github.com/rust-lang/crates.io-index"
1356+ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
1357+
1358+ [[package]]
1359+ name = "ping-pong"
1360+ version = "0.1.0"
1361+ dependencies = [
1362+ "activitypub_federation",
1363+ "anyhow",
1364+ "async-trait",
1365+ "axum",
1366+ "axum-macros",
1367+ "chrono",
1368+ "clap",
1369+ "enum_delegate",
1370+ "env_logger",
1371+ "lazy_static",
1372+ "rand",
1373+ "serde",
1374+ "tera",
1375+ "tokio",
1376+ "tracing",
1377+ "tracing-subscriber",
1378+ "url",
1379+ ]
1380+
1381+ [[package]]
1382+ name = "pkg-config"
1383+ version = "0.3.27"
1384+ source = "registry+https://github.com/rust-lang/crates.io-index"
1385+ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
1386+
1387+ [[package]]
1388+ name = "ppv-lite86"
1389+ version = "0.2.17"
1390+ source = "registry+https://github.com/rust-lang/crates.io-index"
1391+ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
1392+
1393+ [[package]]
1394+ name = "proc-macro2"
1395+ version = "1.0.69"
1396+ source = "registry+https://github.com/rust-lang/crates.io-index"
1397+ checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
1398+ dependencies = [
1399+ "unicode-ident",
1400+ ]
1401+
1402+ [[package]]
1403+ name = "quote"
1404+ version = "1.0.33"
1405+ source = "registry+https://github.com/rust-lang/crates.io-index"
1406+ checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
1407+ dependencies = [
1408+ "proc-macro2",
1409+ ]
1410+
1411+ [[package]]
1412+ name = "rand"
1413+ version = "0.8.5"
1414+ source = "registry+https://github.com/rust-lang/crates.io-index"
1415+ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
1416+ dependencies = [
1417+ "libc",
1418+ "rand_chacha",
1419+ "rand_core",
1420+ ]
1421+
1422+ [[package]]
1423+ name = "rand_chacha"
1424+ version = "0.3.1"
1425+ source = "registry+https://github.com/rust-lang/crates.io-index"
1426+ checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
1427+ dependencies = [
1428+ "ppv-lite86",
1429+ "rand_core",
1430+ ]
1431+
1432+ [[package]]
1433+ name = "rand_core"
1434+ version = "0.6.4"
1435+ source = "registry+https://github.com/rust-lang/crates.io-index"
1436+ checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
1437+ dependencies = [
1438+ "getrandom",
1439+ ]
1440+
1441+ [[package]]
1442+ name = "redox_syscall"
1443+ version = "0.4.1"
1444+ source = "registry+https://github.com/rust-lang/crates.io-index"
1445+ checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
1446+ dependencies = [
1447+ "bitflags 1.3.2",
1448+ ]
1449+
1450+ [[package]]
1451+ name = "regex"
1452+ version = "1.10.2"
1453+ source = "registry+https://github.com/rust-lang/crates.io-index"
1454+ checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
1455+ dependencies = [
1456+ "aho-corasick",
1457+ "memchr",
1458+ "regex-automata",
1459+ "regex-syntax",
1460+ ]
1461+
1462+ [[package]]
1463+ name = "regex-automata"
1464+ version = "0.4.3"
1465+ source = "registry+https://github.com/rust-lang/crates.io-index"
1466+ checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
1467+ dependencies = [
1468+ "aho-corasick",
1469+ "memchr",
1470+ "regex-syntax",
1471+ ]
1472+
1473+ [[package]]
1474+ name = "regex-syntax"
1475+ version = "0.8.2"
1476+ source = "registry+https://github.com/rust-lang/crates.io-index"
1477+ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
1478+
1479+ [[package]]
1480+ name = "reqwest"
1481+ version = "0.11.22"
1482+ source = "registry+https://github.com/rust-lang/crates.io-index"
1483+ checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b"
1484+ dependencies = [
1485+ "base64 0.21.5",
1486+ "bytes",
1487+ "encoding_rs",
1488+ "futures-core",
1489+ "futures-util",
1490+ "h2",
1491+ "http",
1492+ "http-body",
1493+ "hyper",
1494+ "hyper-tls",
1495+ "ipnet",
1496+ "js-sys",
1497+ "log",
1498+ "mime",
1499+ "mime_guess",
1500+ "native-tls",
1501+ "once_cell",
1502+ "percent-encoding",
1503+ "pin-project-lite",
1504+ "serde",
1505+ "serde_json",
1506+ "serde_urlencoded",
1507+ "system-configuration",
1508+ "tokio",
1509+ "tokio-native-tls",
1510+ "tokio-util",
1511+ "tower-service",
1512+ "url",
1513+ "wasm-bindgen",
1514+ "wasm-bindgen-futures",
1515+ "wasm-streams",
1516+ "web-sys",
1517+ "winreg",
1518+ ]
1519+
1520+ [[package]]
1521+ name = "reqwest-middleware"
1522+ version = "0.2.4"
1523+ source = "registry+https://github.com/rust-lang/crates.io-index"
1524+ checksum = "88a3e86aa6053e59030e7ce2d2a3b258dd08fc2d337d52f73f6cb480f5858690"
1525+ dependencies = [
1526+ "anyhow",
1527+ "async-trait",
1528+ "http",
1529+ "reqwest",
1530+ "serde",
1531+ "task-local-extensions",
1532+ "thiserror",
1533+ ]
1534+
1535+ [[package]]
1536+ name = "rustc-demangle"
1537+ version = "0.1.23"
1538+ source = "registry+https://github.com/rust-lang/crates.io-index"
1539+ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
1540+
1541+ [[package]]
1542+ name = "rustix"
1543+ version = "0.38.24"
1544+ source = "registry+https://github.com/rust-lang/crates.io-index"
1545+ checksum = "9ad981d6c340a49cdc40a1028d9c6084ec7e9fa33fcb839cab656a267071e234"
1546+ dependencies = [
1547+ "bitflags 2.4.1",
1548+ "errno",
1549+ "libc",
1550+ "linux-raw-sys",
1551+ "windows-sys",
1552+ ]
1553+
1554+ [[package]]
1555+ name = "rustversion"
1556+ version = "1.0.14"
1557+ source = "registry+https://github.com/rust-lang/crates.io-index"
1558+ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
1559+
1560+ [[package]]
1561+ name = "ryu"
1562+ version = "1.0.15"
1563+ source = "registry+https://github.com/rust-lang/crates.io-index"
1564+ checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
1565+
1566+ [[package]]
1567+ name = "same-file"
1568+ version = "1.0.6"
1569+ source = "registry+https://github.com/rust-lang/crates.io-index"
1570+ checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
1571+ dependencies = [
1572+ "winapi-util",
1573+ ]
1574+
1575+ [[package]]
1576+ name = "schannel"
1577+ version = "0.1.22"
1578+ source = "registry+https://github.com/rust-lang/crates.io-index"
1579+ checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88"
1580+ dependencies = [
1581+ "windows-sys",
1582+ ]
1583+
1584+ [[package]]
1585+ name = "scopeguard"
1586+ version = "1.2.0"
1587+ source = "registry+https://github.com/rust-lang/crates.io-index"
1588+ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
1589+
1590+ [[package]]
1591+ name = "security-framework"
1592+ version = "2.9.2"
1593+ source = "registry+https://github.com/rust-lang/crates.io-index"
1594+ checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de"
1595+ dependencies = [
1596+ "bitflags 1.3.2",
1597+ "core-foundation",
1598+ "core-foundation-sys",
1599+ "libc",
1600+ "security-framework-sys",
1601+ ]
1602+
1603+ [[package]]
1604+ name = "security-framework-sys"
1605+ version = "2.9.1"
1606+ source = "registry+https://github.com/rust-lang/crates.io-index"
1607+ checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a"
1608+ dependencies = [
1609+ "core-foundation-sys",
1610+ "libc",
1611+ ]
1612+
1613+ [[package]]
1614+ name = "serde"
1615+ version = "1.0.192"
1616+ source = "registry+https://github.com/rust-lang/crates.io-index"
1617+ checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001"
1618+ dependencies = [
1619+ "serde_derive",
1620+ ]
1621+
1622+ [[package]]
1623+ name = "serde_derive"
1624+ version = "1.0.192"
1625+ source = "registry+https://github.com/rust-lang/crates.io-index"
1626+ checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1"
1627+ dependencies = [
1628+ "proc-macro2",
1629+ "quote",
1630+ "syn 2.0.39",
1631+ ]
1632+
1633+ [[package]]
1634+ name = "serde_json"
1635+ version = "1.0.108"
1636+ source = "registry+https://github.com/rust-lang/crates.io-index"
1637+ checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
1638+ dependencies = [
1639+ "indexmap",
1640+ "itoa",
1641+ "ryu",
1642+ "serde",
1643+ ]
1644+
1645+ [[package]]
1646+ name = "serde_path_to_error"
1647+ version = "0.1.14"
1648+ source = "registry+https://github.com/rust-lang/crates.io-index"
1649+ checksum = "4beec8bce849d58d06238cb50db2e1c417cfeafa4c63f692b15c82b7c80f8335"
1650+ dependencies = [
1651+ "itoa",
1652+ "serde",
1653+ ]
1654+
1655+ [[package]]
1656+ name = "serde_urlencoded"
1657+ version = "0.7.1"
1658+ source = "registry+https://github.com/rust-lang/crates.io-index"
1659+ checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
1660+ dependencies = [
1661+ "form_urlencoded",
1662+ "itoa",
1663+ "ryu",
1664+ "serde",
1665+ ]
1666+
1667+ [[package]]
1668+ name = "sha1"
1669+ version = "0.10.6"
1670+ source = "registry+https://github.com/rust-lang/crates.io-index"
1671+ checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
1672+ dependencies = [
1673+ "cfg-if",
1674+ "cpufeatures",
1675+ "digest",
1676+ ]
1677+
1678+ [[package]]
1679+ name = "sha2"
1680+ version = "0.10.8"
1681+ source = "registry+https://github.com/rust-lang/crates.io-index"
1682+ checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
1683+ dependencies = [
1684+ "cfg-if",
1685+ "cpufeatures",
1686+ "digest",
1687+ ]
1688+
1689+ [[package]]
1690+ name = "sharded-slab"
1691+ version = "0.1.7"
1692+ source = "registry+https://github.com/rust-lang/crates.io-index"
1693+ checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
1694+ dependencies = [
1695+ "lazy_static",
1696+ ]
1697+
1698+ [[package]]
1699+ name = "signal-hook-registry"
1700+ version = "1.4.1"
1701+ source = "registry+https://github.com/rust-lang/crates.io-index"
1702+ checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
1703+ dependencies = [
1704+ "libc",
1705+ ]
1706+
1707+ [[package]]
1708+ name = "siphasher"
1709+ version = "0.3.11"
1710+ source = "registry+https://github.com/rust-lang/crates.io-index"
1711+ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
1712+
1713+ [[package]]
1714+ name = "slab"
1715+ version = "0.4.9"
1716+ source = "registry+https://github.com/rust-lang/crates.io-index"
1717+ checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
1718+ dependencies = [
1719+ "autocfg",
1720+ ]
1721+
1722+ [[package]]
1723+ name = "slug"
1724+ version = "0.1.5"
1725+ source = "registry+https://github.com/rust-lang/crates.io-index"
1726+ checksum = "3bd94acec9c8da640005f8e135a39fc0372e74535e6b368b7a04b875f784c8c4"
1727+ dependencies = [
1728+ "deunicode",
1729+ "wasm-bindgen",
1730+ ]
1731+
1732+ [[package]]
1733+ name = "smallvec"
1734+ version = "1.11.2"
1735+ source = "registry+https://github.com/rust-lang/crates.io-index"
1736+ checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
1737+
1738+ [[package]]
1739+ name = "socket2"
1740+ version = "0.4.10"
1741+ source = "registry+https://github.com/rust-lang/crates.io-index"
1742+ checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
1743+ dependencies = [
1744+ "libc",
1745+ "winapi",
1746+ ]
1747+
1748+ [[package]]
1749+ name = "socket2"
1750+ version = "0.5.5"
1751+ source = "registry+https://github.com/rust-lang/crates.io-index"
1752+ checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
1753+ dependencies = [
1754+ "libc",
1755+ "windows-sys",
1756+ ]
1757+
1758+ [[package]]
1759+ name = "strsim"
1760+ version = "0.10.0"
1761+ source = "registry+https://github.com/rust-lang/crates.io-index"
1762+ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
1763+
1764+ [[package]]
1765+ name = "syn"
1766+ version = "1.0.109"
1767+ source = "registry+https://github.com/rust-lang/crates.io-index"
1768+ checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
1769+ dependencies = [
1770+ "proc-macro2",
1771+ "quote",
1772+ "unicode-ident",
1773+ ]
1774+
1775+ [[package]]
1776+ name = "syn"
1777+ version = "2.0.39"
1778+ source = "registry+https://github.com/rust-lang/crates.io-index"
1779+ checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
1780+ dependencies = [
1781+ "proc-macro2",
1782+ "quote",
1783+ "unicode-ident",
1784+ ]
1785+
1786+ [[package]]
1787+ name = "sync_wrapper"
1788+ version = "0.1.2"
1789+ source = "registry+https://github.com/rust-lang/crates.io-index"
1790+ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
1791+
1792+ [[package]]
1793+ name = "system-configuration"
1794+ version = "0.5.1"
1795+ source = "registry+https://github.com/rust-lang/crates.io-index"
1796+ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
1797+ dependencies = [
1798+ "bitflags 1.3.2",
1799+ "core-foundation",
1800+ "system-configuration-sys",
1801+ ]
1802+
1803+ [[package]]
1804+ name = "system-configuration-sys"
1805+ version = "0.5.0"
1806+ source = "registry+https://github.com/rust-lang/crates.io-index"
1807+ checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
1808+ dependencies = [
1809+ "core-foundation-sys",
1810+ "libc",
1811+ ]
1812+
1813+ [[package]]
1814+ name = "task-local-extensions"
1815+ version = "0.1.4"
1816+ source = "registry+https://github.com/rust-lang/crates.io-index"
1817+ checksum = "ba323866e5d033818e3240feeb9f7db2c4296674e4d9e16b97b7bf8f490434e8"
1818+ dependencies = [
1819+ "pin-utils",
1820+ ]
1821+
1822+ [[package]]
1823+ name = "tempfile"
1824+ version = "3.8.1"
1825+ source = "registry+https://github.com/rust-lang/crates.io-index"
1826+ checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5"
1827+ dependencies = [
1828+ "cfg-if",
1829+ "fastrand",
1830+ "redox_syscall",
1831+ "rustix",
1832+ "windows-sys",
1833+ ]
1834+
1835+ [[package]]
1836+ name = "tera"
1837+ version = "1.19.1"
1838+ source = "registry+https://github.com/rust-lang/crates.io-index"
1839+ checksum = "970dff17c11e884a4a09bc76e3a17ef71e01bb13447a11e85226e254fe6d10b8"
1840+ dependencies = [
1841+ "chrono",
1842+ "chrono-tz",
1843+ "globwalk",
1844+ "humansize",
1845+ "lazy_static",
1846+ "percent-encoding",
1847+ "pest",
1848+ "pest_derive",
1849+ "rand",
1850+ "regex",
1851+ "serde",
1852+ "serde_json",
1853+ "slug",
1854+ "unic-segment",
1855+ ]
1856+
1857+ [[package]]
1858+ name = "termcolor"
1859+ version = "1.4.0"
1860+ source = "registry+https://github.com/rust-lang/crates.io-index"
1861+ checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449"
1862+ dependencies = [
1863+ "winapi-util",
1864+ ]
1865+
1866+ [[package]]
1867+ name = "thiserror"
1868+ version = "1.0.50"
1869+ source = "registry+https://github.com/rust-lang/crates.io-index"
1870+ checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
1871+ dependencies = [
1872+ "thiserror-impl",
1873+ ]
1874+
1875+ [[package]]
1876+ name = "thiserror-impl"
1877+ version = "1.0.50"
1878+ source = "registry+https://github.com/rust-lang/crates.io-index"
1879+ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
1880+ dependencies = [
1881+ "proc-macro2",
1882+ "quote",
1883+ "syn 2.0.39",
1884+ ]
1885+
1886+ [[package]]
1887+ name = "thread_local"
1888+ version = "1.1.7"
1889+ source = "registry+https://github.com/rust-lang/crates.io-index"
1890+ checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
1891+ dependencies = [
1892+ "cfg-if",
1893+ "once_cell",
1894+ ]
1895+
1896+ [[package]]
1897+ name = "tinyvec"
1898+ version = "1.6.0"
1899+ source = "registry+https://github.com/rust-lang/crates.io-index"
1900+ checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
1901+ dependencies = [
1902+ "tinyvec_macros",
1903+ ]
1904+
1905+ [[package]]
1906+ name = "tinyvec_macros"
1907+ version = "0.1.1"
1908+ source = "registry+https://github.com/rust-lang/crates.io-index"
1909+ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
1910+
1911+ [[package]]
1912+ name = "tokio"
1913+ version = "1.34.0"
1914+ source = "registry+https://github.com/rust-lang/crates.io-index"
1915+ checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9"
1916+ dependencies = [
1917+ "backtrace",
1918+ "bytes",
1919+ "libc",
1920+ "mio",
1921+ "num_cpus",
1922+ "parking_lot",
1923+ "pin-project-lite",
1924+ "signal-hook-registry",
1925+ "socket2 0.5.5",
1926+ "tokio-macros",
1927+ "windows-sys",
1928+ ]
1929+
1930+ [[package]]
1931+ name = "tokio-macros"
1932+ version = "2.2.0"
1933+ source = "registry+https://github.com/rust-lang/crates.io-index"
1934+ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
1935+ dependencies = [
1936+ "proc-macro2",
1937+ "quote",
1938+ "syn 2.0.39",
1939+ ]
1940+
1941+ [[package]]
1942+ name = "tokio-native-tls"
1943+ version = "0.3.1"
1944+ source = "registry+https://github.com/rust-lang/crates.io-index"
1945+ checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
1946+ dependencies = [
1947+ "native-tls",
1948+ "tokio",
1949+ ]
1950+
1951+ [[package]]
1952+ name = "tokio-util"
1953+ version = "0.7.10"
1954+ source = "registry+https://github.com/rust-lang/crates.io-index"
1955+ checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
1956+ dependencies = [
1957+ "bytes",
1958+ "futures-core",
1959+ "futures-sink",
1960+ "pin-project-lite",
1961+ "tokio",
1962+ "tracing",
1963+ ]
1964+
1965+ [[package]]
1966+ name = "tower"
1967+ version = "0.4.13"
1968+ source = "registry+https://github.com/rust-lang/crates.io-index"
1969+ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
1970+ dependencies = [
1971+ "futures-core",
1972+ "futures-util",
1973+ "pin-project",
1974+ "pin-project-lite",
1975+ "tokio",
1976+ "tower-layer",
1977+ "tower-service",
1978+ "tracing",
1979+ ]
1980+
1981+ [[package]]
1982+ name = "tower-layer"
1983+ version = "0.3.2"
1984+ source = "registry+https://github.com/rust-lang/crates.io-index"
1985+ checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
1986+
1987+ [[package]]
1988+ name = "tower-service"
1989+ version = "0.3.2"
1990+ source = "registry+https://github.com/rust-lang/crates.io-index"
1991+ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
1992+
1993+ [[package]]
1994+ name = "tracing"
1995+ version = "0.1.40"
1996+ source = "registry+https://github.com/rust-lang/crates.io-index"
1997+ checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
1998+ dependencies = [
1999+ "log",
2000+ "pin-project-lite",
2001+ "tracing-attributes",
2002+ "tracing-core",
2003+ ]
2004+
2005+ [[package]]
2006+ name = "tracing-attributes"
2007+ version = "0.1.27"
2008+ source = "registry+https://github.com/rust-lang/crates.io-index"
2009+ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
2010+ dependencies = [
2011+ "proc-macro2",
2012+ "quote",
2013+ "syn 2.0.39",
2014+ ]
2015+
2016+ [[package]]
2017+ name = "tracing-core"
2018+ version = "0.1.32"
2019+ source = "registry+https://github.com/rust-lang/crates.io-index"
2020+ checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
2021+ dependencies = [
2022+ "once_cell",
2023+ "valuable",
2024+ ]
2025+
2026+ [[package]]
2027+ name = "tracing-log"
2028+ version = "0.2.0"
2029+ source = "registry+https://github.com/rust-lang/crates.io-index"
2030+ checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
2031+ dependencies = [
2032+ "log",
2033+ "once_cell",
2034+ "tracing-core",
2035+ ]
2036+
2037+ [[package]]
2038+ name = "tracing-subscriber"
2039+ version = "0.3.18"
2040+ source = "registry+https://github.com/rust-lang/crates.io-index"
2041+ checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
2042+ dependencies = [
2043+ "nu-ansi-term",
2044+ "sharded-slab",
2045+ "smallvec",
2046+ "thread_local",
2047+ "tracing-core",
2048+ "tracing-log",
2049+ ]
2050+
2051+ [[package]]
2052+ name = "try-lock"
2053+ version = "0.2.4"
2054+ source = "registry+https://github.com/rust-lang/crates.io-index"
2055+ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
2056+
2057+ [[package]]
2058+ name = "typenum"
2059+ version = "1.17.0"
2060+ source = "registry+https://github.com/rust-lang/crates.io-index"
2061+ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
2062+
2063+ [[package]]
2064+ name = "ucd-trie"
2065+ version = "0.1.6"
2066+ source = "registry+https://github.com/rust-lang/crates.io-index"
2067+ checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
2068+
2069+ [[package]]
2070+ name = "unic-char-property"
2071+ version = "0.9.0"
2072+ source = "registry+https://github.com/rust-lang/crates.io-index"
2073+ checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221"
2074+ dependencies = [
2075+ "unic-char-range",
2076+ ]
2077+
2078+ [[package]]
2079+ name = "unic-char-range"
2080+ version = "0.9.0"
2081+ source = "registry+https://github.com/rust-lang/crates.io-index"
2082+ checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc"
2083+
2084+ [[package]]
2085+ name = "unic-common"
2086+ version = "0.9.0"
2087+ source = "registry+https://github.com/rust-lang/crates.io-index"
2088+ checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc"
2089+
2090+ [[package]]
2091+ name = "unic-segment"
2092+ version = "0.9.0"
2093+ source = "registry+https://github.com/rust-lang/crates.io-index"
2094+ checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23"
2095+ dependencies = [
2096+ "unic-ucd-segment",
2097+ ]
2098+
2099+ [[package]]
2100+ name = "unic-ucd-segment"
2101+ version = "0.9.0"
2102+ source = "registry+https://github.com/rust-lang/crates.io-index"
2103+ checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700"
2104+ dependencies = [
2105+ "unic-char-property",
2106+ "unic-char-range",
2107+ "unic-ucd-version",
2108+ ]
2109+
2110+ [[package]]
2111+ name = "unic-ucd-version"
2112+ version = "0.9.0"
2113+ source = "registry+https://github.com/rust-lang/crates.io-index"
2114+ checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4"
2115+ dependencies = [
2116+ "unic-common",
2117+ ]
2118+
2119+ [[package]]
2120+ name = "unicase"
2121+ version = "2.7.0"
2122+ source = "registry+https://github.com/rust-lang/crates.io-index"
2123+ checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
2124+ dependencies = [
2125+ "version_check",
2126+ ]
2127+
2128+ [[package]]
2129+ name = "unicode-bidi"
2130+ version = "0.3.13"
2131+ source = "registry+https://github.com/rust-lang/crates.io-index"
2132+ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
2133+
2134+ [[package]]
2135+ name = "unicode-ident"
2136+ version = "1.0.12"
2137+ source = "registry+https://github.com/rust-lang/crates.io-index"
2138+ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
2139+
2140+ [[package]]
2141+ name = "unicode-normalization"
2142+ version = "0.1.22"
2143+ source = "registry+https://github.com/rust-lang/crates.io-index"
2144+ checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
2145+ dependencies = [
2146+ "tinyvec",
2147+ ]
2148+
2149+ [[package]]
2150+ name = "url"
2151+ version = "2.4.1"
2152+ source = "registry+https://github.com/rust-lang/crates.io-index"
2153+ checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"
2154+ dependencies = [
2155+ "form_urlencoded",
2156+ "idna",
2157+ "percent-encoding",
2158+ "serde",
2159+ ]
2160+
2161+ [[package]]
2162+ name = "utf8parse"
2163+ version = "0.2.1"
2164+ source = "registry+https://github.com/rust-lang/crates.io-index"
2165+ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
2166+
2167+ [[package]]
2168+ name = "valuable"
2169+ version = "0.1.0"
2170+ source = "registry+https://github.com/rust-lang/crates.io-index"
2171+ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
2172+
2173+ [[package]]
2174+ name = "vcpkg"
2175+ version = "0.2.15"
2176+ source = "registry+https://github.com/rust-lang/crates.io-index"
2177+ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
2178+
2179+ [[package]]
2180+ name = "version_check"
2181+ version = "0.9.4"
2182+ source = "registry+https://github.com/rust-lang/crates.io-index"
2183+ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
2184+
2185+ [[package]]
2186+ name = "walkdir"
2187+ version = "2.4.0"
2188+ source = "registry+https://github.com/rust-lang/crates.io-index"
2189+ checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
2190+ dependencies = [
2191+ "same-file",
2192+ "winapi-util",
2193+ ]
2194+
2195+ [[package]]
2196+ name = "want"
2197+ version = "0.3.1"
2198+ source = "registry+https://github.com/rust-lang/crates.io-index"
2199+ checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
2200+ dependencies = [
2201+ "try-lock",
2202+ ]
2203+
2204+ [[package]]
2205+ name = "wasi"
2206+ version = "0.11.0+wasi-snapshot-preview1"
2207+ source = "registry+https://github.com/rust-lang/crates.io-index"
2208+ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
2209+
2210+ [[package]]
2211+ name = "wasm-bindgen"
2212+ version = "0.2.88"
2213+ source = "registry+https://github.com/rust-lang/crates.io-index"
2214+ checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce"
2215+ dependencies = [
2216+ "cfg-if",
2217+ "wasm-bindgen-macro",
2218+ ]
2219+
2220+ [[package]]
2221+ name = "wasm-bindgen-backend"
2222+ version = "0.2.88"
2223+ source = "registry+https://github.com/rust-lang/crates.io-index"
2224+ checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217"
2225+ dependencies = [
2226+ "bumpalo",
2227+ "log",
2228+ "once_cell",
2229+ "proc-macro2",
2230+ "quote",
2231+ "syn 2.0.39",
2232+ "wasm-bindgen-shared",
2233+ ]
2234+
2235+ [[package]]
2236+ name = "wasm-bindgen-futures"
2237+ version = "0.4.38"
2238+ source = "registry+https://github.com/rust-lang/crates.io-index"
2239+ checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02"
2240+ dependencies = [
2241+ "cfg-if",
2242+ "js-sys",
2243+ "wasm-bindgen",
2244+ "web-sys",
2245+ ]
2246+
2247+ [[package]]
2248+ name = "wasm-bindgen-macro"
2249+ version = "0.2.88"
2250+ source = "registry+https://github.com/rust-lang/crates.io-index"
2251+ checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2"
2252+ dependencies = [
2253+ "quote",
2254+ "wasm-bindgen-macro-support",
2255+ ]
2256+
2257+ [[package]]
2258+ name = "wasm-bindgen-macro-support"
2259+ version = "0.2.88"
2260+ source = "registry+https://github.com/rust-lang/crates.io-index"
2261+ checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907"
2262+ dependencies = [
2263+ "proc-macro2",
2264+ "quote",
2265+ "syn 2.0.39",
2266+ "wasm-bindgen-backend",
2267+ "wasm-bindgen-shared",
2268+ ]
2269+
2270+ [[package]]
2271+ name = "wasm-bindgen-shared"
2272+ version = "0.2.88"
2273+ source = "registry+https://github.com/rust-lang/crates.io-index"
2274+ checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b"
2275+
2276+ [[package]]
2277+ name = "wasm-streams"
2278+ version = "0.3.0"
2279+ source = "registry+https://github.com/rust-lang/crates.io-index"
2280+ checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7"
2281+ dependencies = [
2282+ "futures-util",
2283+ "js-sys",
2284+ "wasm-bindgen",
2285+ "wasm-bindgen-futures",
2286+ "web-sys",
2287+ ]
2288+
2289+ [[package]]
2290+ name = "web-sys"
2291+ version = "0.3.65"
2292+ source = "registry+https://github.com/rust-lang/crates.io-index"
2293+ checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85"
2294+ dependencies = [
2295+ "js-sys",
2296+ "wasm-bindgen",
2297+ ]
2298+
2299+ [[package]]
2300+ name = "winapi"
2301+ version = "0.3.9"
2302+ source = "registry+https://github.com/rust-lang/crates.io-index"
2303+ checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
2304+ dependencies = [
2305+ "winapi-i686-pc-windows-gnu",
2306+ "winapi-x86_64-pc-windows-gnu",
2307+ ]
2308+
2309+ [[package]]
2310+ name = "winapi-i686-pc-windows-gnu"
2311+ version = "0.4.0"
2312+ source = "registry+https://github.com/rust-lang/crates.io-index"
2313+ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
2314+
2315+ [[package]]
2316+ name = "winapi-util"
2317+ version = "0.1.6"
2318+ source = "registry+https://github.com/rust-lang/crates.io-index"
2319+ checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
2320+ dependencies = [
2321+ "winapi",
2322+ ]
2323+
2324+ [[package]]
2325+ name = "winapi-x86_64-pc-windows-gnu"
2326+ version = "0.4.0"
2327+ source = "registry+https://github.com/rust-lang/crates.io-index"
2328+ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
2329+
2330+ [[package]]
2331+ name = "windows-core"
2332+ version = "0.51.1"
2333+ source = "registry+https://github.com/rust-lang/crates.io-index"
2334+ checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64"
2335+ dependencies = [
2336+ "windows-targets",
2337+ ]
2338+
2339+ [[package]]
2340+ name = "windows-sys"
2341+ version = "0.48.0"
2342+ source = "registry+https://github.com/rust-lang/crates.io-index"
2343+ checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
2344+ dependencies = [
2345+ "windows-targets",
2346+ ]
2347+
2348+ [[package]]
2349+ name = "windows-targets"
2350+ version = "0.48.5"
2351+ source = "registry+https://github.com/rust-lang/crates.io-index"
2352+ checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
2353+ dependencies = [
2354+ "windows_aarch64_gnullvm",
2355+ "windows_aarch64_msvc",
2356+ "windows_i686_gnu",
2357+ "windows_i686_msvc",
2358+ "windows_x86_64_gnu",
2359+ "windows_x86_64_gnullvm",
2360+ "windows_x86_64_msvc",
2361+ ]
2362+
2363+ [[package]]
2364+ name = "windows_aarch64_gnullvm"
2365+ version = "0.48.5"
2366+ source = "registry+https://github.com/rust-lang/crates.io-index"
2367+ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
2368+
2369+ [[package]]
2370+ name = "windows_aarch64_msvc"
2371+ version = "0.48.5"
2372+ source = "registry+https://github.com/rust-lang/crates.io-index"
2373+ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
2374+
2375+ [[package]]
2376+ name = "windows_i686_gnu"
2377+ version = "0.48.5"
2378+ source = "registry+https://github.com/rust-lang/crates.io-index"
2379+ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
2380+
2381+ [[package]]
2382+ name = "windows_i686_msvc"
2383+ version = "0.48.5"
2384+ source = "registry+https://github.com/rust-lang/crates.io-index"
2385+ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
2386+
2387+ [[package]]
2388+ name = "windows_x86_64_gnu"
2389+ version = "0.48.5"
2390+ source = "registry+https://github.com/rust-lang/crates.io-index"
2391+ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
2392+
2393+ [[package]]
2394+ name = "windows_x86_64_gnullvm"
2395+ version = "0.48.5"
2396+ source = "registry+https://github.com/rust-lang/crates.io-index"
2397+ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
2398+
2399+ [[package]]
2400+ name = "windows_x86_64_msvc"
2401+ version = "0.48.5"
2402+ source = "registry+https://github.com/rust-lang/crates.io-index"
2403+ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
2404+
2405+ [[package]]
2406+ name = "winreg"
2407+ version = "0.50.0"
2408+ source = "registry+https://github.com/rust-lang/crates.io-index"
2409+ checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
2410+ dependencies = [
2411+ "cfg-if",
2412+ "windows-sys",
2413+ ]
2414 diff --git a/Cargo.toml b/Cargo.toml
2415new file mode 100644
2416index 0000000..53aad40
2417--- /dev/null
2418+++ b/Cargo.toml
2419 @@ -0,0 +1,25 @@
2420+ [package]
2421+ name = "ping-pong"
2422+ version = "0.1.0"
2423+ edition = "2021"
2424+
2425+ # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
2426+
2427+ [dependencies]
2428+ activitypub_federation = { version = "0.4.7", features = ["axum"], default-features = false }
2429+ anyhow = "1.0.75"
2430+ async-trait = "0.1.74"
2431+ axum = { version = "0.6.20", features = ["macros", "headers"] }
2432+ axum-macros = "0.3.8"
2433+ chrono = "0.4.31"
2434+ clap = { version = "4.4.8", features = ["cargo"] }
2435+ enum_delegate = "0.2.0"
2436+ env_logger = "0.10.1"
2437+ lazy_static = "1.4.0"
2438+ rand = "0.8.5"
2439+ serde = "1.0.192"
2440+ tera = "1.19.1"
2441+ tokio = { version = "1.34.0", features = ["full"] }
2442+ tracing = "0.1.40"
2443+ tracing-subscriber = "0.3.18"
2444+ url = "2.4.1"
2445 diff --git a/README.md b/README.md
2446new file mode 100644
2447index 0000000..5e23e47
2448--- /dev/null
2449+++ b/README.md
2450 @@ -0,0 +1,8 @@
2451+ # ping-pong
2452+
2453+ The world's least interesting social media network, **ping-pong**!
2454+
2455+ **ping-pong** is the network where you post PINGs and optionally receive PONGs.
2456+
2457+ Created with [activitypub-federation-rust](https://github.com/LemmyNet/activitypub-federation-rust) from the Lemmy project. Written as an exercise to attempt to wrap my head
2458+ around ActivityPub in general.
2459 diff --git a/logo.svg b/logo.svg
2460new file mode 100644
2461index 0000000..8efef17
2462--- /dev/null
2463+++ b/logo.svg
2464 @@ -0,0 +1,19 @@
2465+ <svg id="emoji" viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg">
2466+ <g id="color">
2467+ <path fill="#a57939" stroke="none" d="M14.0839,33l31.4611,16.8688c0,0-8.6284,3.6312-19.2951-1.1188C26.25,48.75,17.3333,43.3333,14.0839,33z"/>
2468+ <path fill="#EA5A47" stroke="none" d="M50.1114,48.3225c-0.1236,0.1086-0.2469,0.217-0.3769,0.3162 c-4.8051,3.6711-12.1026,3.2038-18.6455,1.6809l-0.0783-0.0091c0,0-1.1392-0.1871-1.6246,0.8975l-6.9608-3.7043 c0.6236-1.0115-0.113-1.7932-0.113-1.7932l-0.0365-0.0382c-7.2736-6.6788-10.9673-14.9122-5.7359-24.7998 C22.6383,9.3458,34.4924-0.9163,48.5632,6.5283c11.3007,5.9789,13.3979,16.7366,10.5849,26.4292 C59.1482,32.9575,56.6567,42.568,50.1114,48.3225z"/>
2469+ <line x1="45.5451" x2="14.4533" y1="49.8688" y2="33.4189" fill="#EA5A47" stroke="none"/>
2470+ <path fill="#A57939" stroke="none" d="M21.8392,70.1686l4.099-8.886l7.7953-17.6631l-6.5343-3.4572L16.9616,56.5333l-4.6434,7.3673 c-0.2881,0.4836-0.2898,0.7463-0.2181,1.1494l0,0c0.0742,0.4167,0.4308,0.8499,0.9015,1.2571c0,0,1.3685,1.4157,4.1297,2.6315 C17.1313,68.9387,21.1333,70.8118,21.8392,70.1686z"/>
2471+ <circle cx="54.8215" cy="40.8811" r="5" fill="#FFFFFF" stroke="none" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
2472+ </g>
2473+ <g id="hair"/>
2474+ <g id="skin"/>
2475+ <g id="skin-shadow"/>
2476+ <g id="line">
2477+ <path fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2" d="M29.3861,51.208c0.4854-1.0846,1.6246-0.8975,1.6246-0.8975l0.0783,0.0091c6.7209,1.5643,13.0483,1.2476,18.0324-2.4671"/>
2478+ <path fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2" d="M22.4252,47.5037c0.6236-1.0115-0.113-1.7932-0.113-1.7932l-0.0365-0.0382c-7.2736-6.6788-10.9673-14.9122-5.7359-24.7998 C22.6383,9.3458,34.4924-0.9163,48.5632,6.5283c11.3007,5.9789,12.4779,16.3166,9.6649,26.0092"/>
2479+ <line x1="45.5451" x2="14.4533" y1="49.8688" y2="33.4189" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
2480+ <path fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2" d="M21.3523,69.3163l3.9927-9.0477l7.6176-17.0568l-5.9312-3.138l-9.8345,15.8839l-4.4591,7.1491 c-0.2774,0.4689-0.2854,0.7197-0.2294,1.1028v0c0.0579,0.396,0.3755,0.8007,0.7988,1.1777c0,0,1.6564,1.5208,4.1689,2.6128"/>
2481+ <circle cx="54.8215" cy="40.8811" r="5" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
2482+ </g>
2483+ </svg>
2484 diff --git a/main.css b/main.css
2485new file mode 100644
2486index 0000000..7a81833
2487--- /dev/null
2488+++ b/main.css
2489 @@ -0,0 +1,6 @@
2490+ .logo {
2491+ width: 100px;
2492+ }
2493+
2494+ button {
2495+ }
2496 diff --git a/pico.min.css b/pico.min.css
2497new file mode 100644
2498index 0000000..4971b2d
2499--- /dev/null
2500+++ b/pico.min.css
2501 @@ -0,0 +1,5 @@
2502+ @charset "UTF-8";/*!
2503+ * Pico CSS v1.5.10 (https://picocss.com)
2504+ * Copyright 2019-2023 - Licensed under MIT
2505+ */:root{--font-family:system-ui,-apple-system,"Segoe UI","Roboto","Ubuntu","Cantarell","Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--line-height:1.5;--font-weight:400;--font-size:16px;--border-radius:0.25rem;--border-width:1px;--outline-width:3px;--spacing:1rem;--typography-spacing-vertical:1.5rem;--block-spacing-vertical:calc(var(--spacing) * 2);--block-spacing-horizontal:var(--spacing);--grid-spacing-vertical:0;--grid-spacing-horizontal:var(--spacing);--form-element-spacing-vertical:0.75rem;--form-element-spacing-horizontal:1rem;--nav-element-spacing-vertical:1rem;--nav-element-spacing-horizontal:0.5rem;--nav-link-spacing-vertical:0.5rem;--nav-link-spacing-horizontal:0.5rem;--form-label-font-weight:var(--font-weight);--transition:0.2s ease-in-out;--modal-overlay-backdrop-filter:blur(0.25rem)}@media (min-width:576px){:root{--font-size:17px}}@media (min-width:768px){:root{--font-size:18px}}@media (min-width:992px){:root{--font-size:19px}}@media (min-width:1200px){:root{--font-size:20px}}@media (min-width:576px){body>footer,body>header,body>main,section{--block-spacing-vertical:calc(var(--spacing) * 2.5)}}@media (min-width:768px){body>footer,body>header,body>main,section{--block-spacing-vertical:calc(var(--spacing) * 3)}}@media (min-width:992px){body>footer,body>header,body>main,section{--block-spacing-vertical:calc(var(--spacing) * 3.5)}}@media (min-width:1200px){body>footer,body>header,body>main,section{--block-spacing-vertical:calc(var(--spacing) * 4)}}@media (min-width:576px){article{--block-spacing-horizontal:calc(var(--spacing) * 1.25)}}@media (min-width:768px){article{--block-spacing-horizontal:calc(var(--spacing) * 1.5)}}@media (min-width:992px){article{--block-spacing-horizontal:calc(var(--spacing) * 1.75)}}@media (min-width:1200px){article{--block-spacing-horizontal:calc(var(--spacing) * 2)}}dialog>article{--block-spacing-vertical:calc(var(--spacing) * 2);--block-spacing-horizontal:var(--spacing)}@media (min-width:576px){dialog>article{--block-spacing-vertical:calc(var(--spacing) * 2.5);--block-spacing-horizontal:calc(var(--spacing) * 1.25)}}@media (min-width:768px){dialog>article{--block-spacing-vertical:calc(var(--spacing) * 3);--block-spacing-horizontal:calc(var(--spacing) * 1.5)}}a{--text-decoration:none}a.contrast,a.secondary{--text-decoration:underline}small{--font-size:0.875em}h1,h2,h3,h4,h5,h6{--font-weight:700}h1{--font-size:2rem;--typography-spacing-vertical:3rem}h2{--font-size:1.75rem;--typography-spacing-vertical:2.625rem}h3{--font-size:1.5rem;--typography-spacing-vertical:2.25rem}h4{--font-size:1.25rem;--typography-spacing-vertical:1.874rem}h5{--font-size:1.125rem;--typography-spacing-vertical:1.6875rem}[type=checkbox],[type=radio]{--border-width:2px}[type=checkbox][role=switch]{--border-width:3px}tfoot td,tfoot th,thead td,thead th{--border-width:3px}:not(thead,tfoot)>*>td{--font-size:0.875em}code,kbd,pre,samp{--font-family:"Menlo","Consolas","Roboto Mono","Ubuntu Monospace","Noto Mono","Oxygen Mono","Liberation Mono",monospace,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"}kbd{--font-weight:bolder}:root:not([data-theme=dark]),[data-theme=light]{--background-color:#fff;--color:hsl(205, 20%, 32%);--h1-color:hsl(205, 30%, 15%);--h2-color:#24333e;--h3-color:hsl(205, 25%, 23%);--h4-color:#374956;--h5-color:hsl(205, 20%, 32%);--h6-color:#4d606d;--muted-color:hsl(205, 10%, 50%);--muted-border-color:hsl(205, 20%, 94%);--primary:hsl(195, 85%, 41%);--primary-hover:hsl(195, 90%, 32%);--primary-focus:rgba(16, 149, 193, 0.125);--primary-inverse:#fff;--secondary:hsl(205, 15%, 41%);--secondary-hover:hsl(205, 20%, 32%);--secondary-focus:rgba(89, 107, 120, 0.125);--secondary-inverse:#fff;--contrast:hsl(205, 30%, 15%);--contrast-hover:#000;--contrast-focus:rgba(89, 107, 120, 0.125);--contrast-inverse:#fff;--mark-background-color:#fff2ca;--mark-color:#543a26;--ins-color:#388e3c;--del-color:#c62828;--blockquote-border-color:var(--muted-border-color);--blockquote-footer-color:var(--muted-color);--button-box-shadow:0 0 0 rgba(0, 0, 0, 0);--button-hover-box-shadow:0 0 0 rgba(0, 0, 0, 0);--form-element-background-color:transparent;--form-element-border-color:hsl(205, 14%, 68%);--form-element-color:var(--color);--form-element-placeholder-color:var(--muted-color);--form-element-active-background-color:transparent;--form-element-active-border-color:var(--primary);--form-element-focus-color:var(--primary-focus);--form-element-disabled-background-color:hsl(205, 18%, 86%);--form-element-disabled-border-color:hsl(205, 14%, 68%);--form-element-disabled-opacity:0.5;--form-element-invalid-border-color:#c62828;--form-element-invalid-active-border-color:#d32f2f;--form-element-invalid-focus-color:rgba(211, 47, 47, 0.125);--form-element-valid-border-color:#388e3c;--form-element-valid-active-border-color:#43a047;--form-element-valid-focus-color:rgba(67, 160, 71, 0.125);--switch-background-color:hsl(205, 16%, 77%);--switch-color:var(--primary-inverse);--switch-checked-background-color:var(--primary);--range-border-color:hsl(205, 18%, 86%);--range-active-border-color:hsl(205, 16%, 77%);--range-thumb-border-color:var(--background-color);--range-thumb-color:var(--secondary);--range-thumb-hover-color:var(--secondary-hover);--range-thumb-active-color:var(--primary);--table-border-color:var(--muted-border-color);--table-row-stripped-background-color:#f6f8f9;--code-background-color:hsl(205, 20%, 94%);--code-color:var(--muted-color);--code-kbd-background-color:var(--contrast);--code-kbd-color:var(--contrast-inverse);--code-tag-color:hsl(330, 40%, 50%);--code-property-color:hsl(185, 40%, 40%);--code-value-color:hsl(40, 20%, 50%);--code-comment-color:hsl(205, 14%, 68%);--accordion-border-color:var(--muted-border-color);--accordion-close-summary-color:var(--color);--accordion-open-summary-color:var(--muted-color);--card-background-color:var(--background-color);--card-border-color:var(--muted-border-color);--card-box-shadow:0.0145rem 0.029rem 0.174rem rgba(27, 40, 50, 0.01698),0.0335rem 0.067rem 0.402rem rgba(27, 40, 50, 0.024),0.0625rem 0.125rem 0.75rem rgba(27, 40, 50, 0.03),0.1125rem 0.225rem 1.35rem rgba(27, 40, 50, 0.036),0.2085rem 0.417rem 2.502rem rgba(27, 40, 50, 0.04302),0.5rem 1rem 6rem rgba(27, 40, 50, 0.06),0 0 0 0.0625rem rgba(27, 40, 50, 0.015);--card-sectionning-background-color:#fbfbfc;--dropdown-background-color:#fbfbfc;--dropdown-border-color:#e1e6eb;--dropdown-box-shadow:var(--card-box-shadow);--dropdown-color:var(--color);--dropdown-hover-background-color:hsl(205, 20%, 94%);--modal-overlay-background-color:rgba(213, 220, 226, 0.7);--progress-background-color:hsl(205, 18%, 86%);--progress-color:var(--primary);--loading-spinner-opacity:0.5;--tooltip-background-color:var(--contrast);--tooltip-color:var(--contrast-inverse);--icon-checkbox:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65, 84, 98)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron-button:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron-button-inverse:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-close:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(115, 130, 140)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");--icon-date:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65, 84, 98)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");--icon-invalid:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(198, 40, 40)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");--icon-minus:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");--icon-search:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65, 84, 98)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");--icon-time:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65, 84, 98)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");--icon-valid:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(56, 142, 60)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");color-scheme:light}@media only screen and (prefers-color-scheme:dark){:root:not([data-theme]){--background-color:#11191f;--color:hsl(205, 16%, 77%);--h1-color:hsl(205, 20%, 94%);--h2-color:#e1e6eb;--h3-color:hsl(205, 18%, 86%);--h4-color:#c8d1d8;--h5-color:hsl(205, 16%, 77%);--h6-color:#afbbc4;--muted-color:hsl(205, 10%, 50%);--muted-border-color:#1f2d38;--primary:hsl(195, 85%, 41%);--primary-hover:hsl(195, 80%, 50%);--primary-focus:rgba(16, 149, 193, 0.25);--primary-inverse:#fff;--secondary:hsl(205, 15%, 41%);--secondary-hover:hsl(205, 10%, 50%);--secondary-focus:rgba(115, 130, 140, 0.25);--secondary-inverse:#fff;--contrast:hsl(205, 20%, 94%);--contrast-hover:#fff;--contrast-focus:rgba(115, 130, 140, 0.25);--contrast-inverse:#000;--mark-background-color:#d1c284;--mark-color:#11191f;--ins-color:#388e3c;--del-color:#c62828;--blockquote-border-color:var(--muted-border-color);--blockquote-footer-color:var(--muted-color);--button-box-shadow:0 0 0 rgba(0, 0, 0, 0);--button-hover-box-shadow:0 0 0 rgba(0, 0, 0, 0);--form-element-background-color:#11191f;--form-element-border-color:#374956;--form-element-color:var(--color);--form-element-placeholder-color:var(--muted-color);--form-element-active-background-color:var(--form-element-background-color);--form-element-active-border-color:var(--primary);--form-element-focus-color:var(--primary-focus);--form-element-disabled-background-color:hsl(205, 25%, 23%);--form-element-disabled-border-color:hsl(205, 20%, 32%);--form-element-disabled-opacity:0.5;--form-element-invalid-border-color:#b71c1c;--form-element-invalid-active-border-color:#c62828;--form-element-invalid-focus-color:rgba(198, 40, 40, 0.25);--form-element-valid-border-color:#2e7d32;--form-element-valid-active-border-color:#388e3c;--form-element-valid-focus-color:rgba(56, 142, 60, 0.25);--switch-background-color:#374956;--switch-color:var(--primary-inverse);--switch-checked-background-color:var(--primary);--range-border-color:#24333e;--range-active-border-color:hsl(205, 25%, 23%);--range-thumb-border-color:var(--background-color);--range-thumb-color:var(--secondary);--range-thumb-hover-color:var(--secondary-hover);--range-thumb-active-color:var(--primary);--table-border-color:var(--muted-border-color);--table-row-stripped-background-color:rgba(115, 130, 140, 0.05);--code-background-color:#18232c;--code-color:var(--muted-color);--code-kbd-background-color:var(--contrast);--code-kbd-color:var(--contrast-inverse);--code-tag-color:hsl(330, 30%, 50%);--code-property-color:hsl(185, 30%, 50%);--code-value-color:hsl(40, 10%, 50%);--code-comment-color:#4d606d;--accordion-border-color:var(--muted-border-color);--accordion-active-summary-color:var(--primary);--accordion-close-summary-color:var(--color);--accordion-open-summary-color:var(--muted-color);--card-background-color:#141e26;--card-border-color:var(--card-background-color);--card-box-shadow:0.0145rem 0.029rem 0.174rem rgba(0, 0, 0, 0.01698),0.0335rem 0.067rem 0.402rem rgba(0, 0, 0, 0.024),0.0625rem 0.125rem 0.75rem rgba(0, 0, 0, 0.03),0.1125rem 0.225rem 1.35rem rgba(0, 0, 0, 0.036),0.2085rem 0.417rem 2.502rem rgba(0, 0, 0, 0.04302),0.5rem 1rem 6rem rgba(0, 0, 0, 0.06),0 0 0 0.0625rem rgba(0, 0, 0, 0.015);--card-sectionning-background-color:#18232c;--dropdown-background-color:hsl(205, 30%, 15%);--dropdown-border-color:#24333e;--dropdown-box-shadow:var(--card-box-shadow);--dropdown-color:var(--color);--dropdown-hover-background-color:rgba(36, 51, 62, 0.75);--modal-overlay-background-color:rgba(36, 51, 62, 0.8);--progress-background-color:#24333e;--progress-color:var(--primary);--loading-spinner-opacity:0.5;--tooltip-background-color:var(--contrast);--tooltip-color:var(--contrast-inverse);--icon-checkbox:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron-button:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron-button-inverse:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(0, 0, 0)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-close:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(115, 130, 140)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");--icon-date:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");--icon-invalid:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(183, 28, 28)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");--icon-minus:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");--icon-search:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");--icon-time:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");--icon-valid:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(46, 125, 50)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");color-scheme:dark}}[data-theme=dark]{--background-color:#11191f;--color:hsl(205, 16%, 77%);--h1-color:hsl(205, 20%, 94%);--h2-color:#e1e6eb;--h3-color:hsl(205, 18%, 86%);--h4-color:#c8d1d8;--h5-color:hsl(205, 16%, 77%);--h6-color:#afbbc4;--muted-color:hsl(205, 10%, 50%);--muted-border-color:#1f2d38;--primary:hsl(195, 85%, 41%);--primary-hover:hsl(195, 80%, 50%);--primary-focus:rgba(16, 149, 193, 0.25);--primary-inverse:#fff;--secondary:hsl(205, 15%, 41%);--secondary-hover:hsl(205, 10%, 50%);--secondary-focus:rgba(115, 130, 140, 0.25);--secondary-inverse:#fff;--contrast:hsl(205, 20%, 94%);--contrast-hover:#fff;--contrast-focus:rgba(115, 130, 140, 0.25);--contrast-inverse:#000;--mark-background-color:#d1c284;--mark-color:#11191f;--ins-color:#388e3c;--del-color:#c62828;--blockquote-border-color:var(--muted-border-color);--blockquote-footer-color:var(--muted-color);--button-box-shadow:0 0 0 rgba(0, 0, 0, 0);--button-hover-box-shadow:0 0 0 rgba(0, 0, 0, 0);--form-element-background-color:#11191f;--form-element-border-color:#374956;--form-element-color:var(--color);--form-element-placeholder-color:var(--muted-color);--form-element-active-background-color:var(--form-element-background-color);--form-element-active-border-color:var(--primary);--form-element-focus-color:var(--primary-focus);--form-element-disabled-background-color:hsl(205, 25%, 23%);--form-element-disabled-border-color:hsl(205, 20%, 32%);--form-element-disabled-opacity:0.5;--form-element-invalid-border-color:#b71c1c;--form-element-invalid-active-border-color:#c62828;--form-element-invalid-focus-color:rgba(198, 40, 40, 0.25);--form-element-valid-border-color:#2e7d32;--form-element-valid-active-border-color:#388e3c;--form-element-valid-focus-color:rgba(56, 142, 60, 0.25);--switch-background-color:#374956;--switch-color:var(--primary-inverse);--switch-checked-background-color:var(--primary);--range-border-color:#24333e;--range-active-border-color:hsl(205, 25%, 23%);--range-thumb-border-color:var(--background-color);--range-thumb-color:var(--secondary);--range-thumb-hover-color:var(--secondary-hover);--range-thumb-active-color:var(--primary);--table-border-color:var(--muted-border-color);--table-row-stripped-background-color:rgba(115, 130, 140, 0.05);--code-background-color:#18232c;--code-color:var(--muted-color);--code-kbd-background-color:var(--contrast);--code-kbd-color:var(--contrast-inverse);--code-tag-color:hsl(330, 30%, 50%);--code-property-color:hsl(185, 30%, 50%);--code-value-color:hsl(40, 10%, 50%);--code-comment-color:#4d606d;--accordion-border-color:var(--muted-border-color);--accordion-active-summary-color:var(--primary);--accordion-close-summary-color:var(--color);--accordion-open-summary-color:var(--muted-color);--card-background-color:#141e26;--card-border-color:var(--card-background-color);--card-box-shadow:0.0145rem 0.029rem 0.174rem rgba(0, 0, 0, 0.01698),0.0335rem 0.067rem 0.402rem rgba(0, 0, 0, 0.024),0.0625rem 0.125rem 0.75rem rgba(0, 0, 0, 0.03),0.1125rem 0.225rem 1.35rem rgba(0, 0, 0, 0.036),0.2085rem 0.417rem 2.502rem rgba(0, 0, 0, 0.04302),0.5rem 1rem 6rem rgba(0, 0, 0, 0.06),0 0 0 0.0625rem rgba(0, 0, 0, 0.015);--card-sectionning-background-color:#18232c;--dropdown-background-color:hsl(205, 30%, 15%);--dropdown-border-color:#24333e;--dropdown-box-shadow:var(--card-box-shadow);--dropdown-color:var(--color);--dropdown-hover-background-color:rgba(36, 51, 62, 0.75);--modal-overlay-background-color:rgba(36, 51, 62, 0.8);--progress-background-color:#24333e;--progress-color:var(--primary);--loading-spinner-opacity:0.5;--tooltip-background-color:var(--contrast);--tooltip-color:var(--contrast-inverse);--icon-checkbox:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron-button:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron-button-inverse:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(0, 0, 0)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-close:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(115, 130, 140)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");--icon-date:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");--icon-invalid:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(183, 28, 28)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");--icon-minus:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");--icon-search:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");--icon-time:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");--icon-valid:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(46, 125, 50)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");color-scheme:dark}[type=checkbox],[type=radio],[type=range],progress{accent-color:var(--primary)}*,::after,::before{box-sizing:border-box;background-repeat:no-repeat}::after,::before{text-decoration:inherit;vertical-align:inherit}:where(:root){-webkit-tap-highlight-color:transparent;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%;background-color:var(--background-color);color:var(--color);font-weight:var(--font-weight);font-size:var(--font-size);line-height:var(--line-height);font-family:var(--font-family);text-rendering:optimizeLegibility;overflow-wrap:break-word;cursor:default;-moz-tab-size:4;-o-tab-size:4;tab-size:4}main{display:block}body{width:100%;margin:0}body>footer,body>header,body>main{width:100%;margin-right:auto;margin-left:auto;padding:var(--block-spacing-vertical) 0}.container,.container-fluid{width:100%;margin-right:auto;margin-left:auto;padding-right:var(--spacing);padding-left:var(--spacing)}@media (min-width:576px){.container{max-width:510px;padding-right:0;padding-left:0}}@media (min-width:768px){.container{max-width:700px}}@media (min-width:992px){.container{max-width:920px}}@media (min-width:1200px){.container{max-width:1130px}}section{margin-bottom:var(--block-spacing-vertical)}.grid{grid-column-gap:var(--grid-spacing-horizontal);grid-row-gap:var(--grid-spacing-vertical);display:grid;grid-template-columns:1fr;margin:0}@media (min-width:992px){.grid{grid-template-columns:repeat(auto-fit,minmax(0%,1fr))}}.grid>*{min-width:0}figure{display:block;margin:0;padding:0;overflow-x:auto}figure figcaption{padding:calc(var(--spacing) * .5) 0;color:var(--muted-color)}b,strong{font-weight:bolder}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}address,blockquote,dl,figure,form,ol,p,pre,table,ul{margin-top:0;margin-bottom:var(--typography-spacing-vertical);color:var(--color);font-style:normal;font-weight:var(--font-weight);font-size:var(--font-size)}[role=link],a{--color:var(--primary);--background-color:transparent;outline:0;background-color:var(--background-color);color:var(--color);-webkit-text-decoration:var(--text-decoration);text-decoration:var(--text-decoration);transition:background-color var(--transition),color var(--transition),box-shadow var(--transition),-webkit-text-decoration var(--transition);transition:background-color var(--transition),color var(--transition),text-decoration var(--transition),box-shadow var(--transition);transition:background-color var(--transition),color var(--transition),text-decoration var(--transition),box-shadow var(--transition),-webkit-text-decoration var(--transition)}[role=link]:is([aria-current],:hover,:active,:focus),a:is([aria-current],:hover,:active,:focus){--color:var(--primary-hover);--text-decoration:underline}[role=link]:focus,a:focus{--background-color:var(--primary-focus)}[role=link].secondary,a.secondary{--color:var(--secondary)}[role=link].secondary:is([aria-current],:hover,:active,:focus),a.secondary:is([aria-current],:hover,:active,:focus){--color:var(--secondary-hover)}[role=link].secondary:focus,a.secondary:focus{--background-color:var(--secondary-focus)}[role=link].contrast,a.contrast{--color:var(--contrast)}[role=link].contrast:is([aria-current],:hover,:active,:focus),a.contrast:is([aria-current],:hover,:active,:focus){--color:var(--contrast-hover)}[role=link].contrast:focus,a.contrast:focus{--background-color:var(--contrast-focus)}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:var(--typography-spacing-vertical);color:var(--color);font-weight:var(--font-weight);font-size:var(--font-size);font-family:var(--font-family)}h1{--color:var(--h1-color)}h2{--color:var(--h2-color)}h3{--color:var(--h3-color)}h4{--color:var(--h4-color)}h5{--color:var(--h5-color)}h6{--color:var(--h6-color)}:where(address,blockquote,dl,figure,form,ol,p,pre,table,ul)~:is(h1,h2,h3,h4,h5,h6){margin-top:var(--typography-spacing-vertical)}.headings,hgroup{margin-bottom:var(--typography-spacing-vertical)}.headings>*,hgroup>*{margin-bottom:0}.headings>:last-child,hgroup>:last-child{--color:var(--muted-color);--font-weight:unset;font-size:1rem;font-family:unset}p{margin-bottom:var(--typography-spacing-vertical)}small{font-size:var(--font-size)}:where(dl,ol,ul){padding-right:0;padding-left:var(--spacing);-webkit-padding-start:var(--spacing);padding-inline-start:var(--spacing);-webkit-padding-end:0;padding-inline-end:0}:where(dl,ol,ul) li{margin-bottom:calc(var(--typography-spacing-vertical) * .25)}:where(dl,ol,ul) :is(dl,ol,ul){margin:0;margin-top:calc(var(--typography-spacing-vertical) * .25)}ul li{list-style:square}mark{padding:.125rem .25rem;background-color:var(--mark-background-color);color:var(--mark-color);vertical-align:baseline}blockquote{display:block;margin:var(--typography-spacing-vertical) 0;padding:var(--spacing);border-right:none;border-left:.25rem solid var(--blockquote-border-color);-webkit-border-start:0.25rem solid var(--blockquote-border-color);border-inline-start:0.25rem solid var(--blockquote-border-color);-webkit-border-end:none;border-inline-end:none}blockquote footer{margin-top:calc(var(--typography-spacing-vertical) * .5);color:var(--blockquote-footer-color)}abbr[title]{border-bottom:1px dotted;text-decoration:none;cursor:help}ins{color:var(--ins-color);text-decoration:none}del{color:var(--del-color)}::-moz-selection{background-color:var(--primary-focus)}::selection{background-color:var(--primary-focus)}:where(audio,canvas,iframe,img,svg,video){vertical-align:middle}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}:where(iframe){border-style:none}img{max-width:100%;height:auto;border-style:none}:where(svg:not([fill])){fill:currentColor}svg:not(:root){overflow:hidden}button{margin:0;overflow:visible;font-family:inherit;text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}button{display:block;width:100%;margin-bottom:var(--spacing)}[role=button]{display:inline-block;text-decoration:none}[role=button],button,input[type=button],input[type=reset],input[type=submit]{--background-color:var(--primary);--border-color:var(--primary);--color:var(--primary-inverse);--box-shadow:var(--button-box-shadow, 0 0 0 rgba(0, 0, 0, 0));padding:var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal);border:var(--border-width) solid var(--border-color);border-radius:var(--border-radius);outline:0;background-color:var(--background-color);box-shadow:var(--box-shadow);color:var(--color);font-weight:var(--font-weight);font-size:1rem;line-height:var(--line-height);text-align:center;cursor:pointer;transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)}[role=button]:is([aria-current],:hover,:active,:focus),button:is([aria-current],:hover,:active,:focus),input[type=button]:is([aria-current],:hover,:active,:focus),input[type=reset]:is([aria-current],:hover,:active,:focus),input[type=submit]:is([aria-current],:hover,:active,:focus){--background-color:var(--primary-hover);--border-color:var(--primary-hover);--box-shadow:var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0));--color:var(--primary-inverse)}[role=button]:focus,button:focus,input[type=button]:focus,input[type=reset]:focus,input[type=submit]:focus{--box-shadow:var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)),0 0 0 var(--outline-width) var(--primary-focus)}:is(button,input[type=submit],input[type=button],[role=button]).secondary,input[type=reset]{--background-color:var(--secondary);--border-color:var(--secondary);--color:var(--secondary-inverse);cursor:pointer}:is(button,input[type=submit],input[type=button],[role=button]).secondary:is([aria-current],:hover,:active,:focus),input[type=reset]:is([aria-current],:hover,:active,:focus){--background-color:var(--secondary-hover);--border-color:var(--secondary-hover);--color:var(--secondary-inverse)}:is(button,input[type=submit],input[type=button],[role=button]).secondary:focus,input[type=reset]:focus{--box-shadow:var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)),0 0 0 var(--outline-width) var(--secondary-focus)}:is(button,input[type=submit],input[type=button],[role=button]).contrast{--background-color:var(--contrast);--border-color:var(--contrast);--color:var(--contrast-inverse)}:is(button,input[type=submit],input[type=button],[role=button]).contrast:is([aria-current],:hover,:active,:focus){--background-color:var(--contrast-hover);--border-color:var(--contrast-hover);--color:var(--contrast-inverse)}:is(button,input[type=submit],input[type=button],[role=button]).contrast:focus{--box-shadow:var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)),0 0 0 var(--outline-width) var(--contrast-focus)}:is(button,input[type=submit],input[type=button],[role=button]).outline,input[type=reset].outline{--background-color:transparent;--color:var(--primary)}:is(button,input[type=submit],input[type=button],[role=button]).outline:is([aria-current],:hover,:active,:focus),input[type=reset].outline:is([aria-current],:hover,:active,:focus){--background-color:transparent;--color:var(--primary-hover)}:is(button,input[type=submit],input[type=button],[role=button]).outline.secondary,input[type=reset].outline{--color:var(--secondary)}:is(button,input[type=submit],input[type=button],[role=button]).outline.secondary:is([aria-current],:hover,:active,:focus),input[type=reset].outline:is([aria-current],:hover,:active,:focus){--color:var(--secondary-hover)}:is(button,input[type=submit],input[type=button],[role=button]).outline.contrast{--color:var(--contrast)}:is(button,input[type=submit],input[type=button],[role=button]).outline.contrast:is([aria-current],:hover,:active,:focus){--color:var(--contrast-hover)}:where(button,[type=submit],[type=button],[type=reset],[role=button])[disabled],:where(fieldset[disabled]) :is(button,[type=submit],[type=button],[type=reset],[role=button]),a[role=button]:not([href]){opacity:.5;pointer-events:none}input,optgroup,select,textarea{margin:0;font-size:1rem;line-height:var(--line-height);font-family:inherit;letter-spacing:inherit}input{overflow:visible}select{text-transform:none}legend{max-width:100%;padding:0;color:inherit;white-space:normal}textarea{overflow:auto}[type=checkbox],[type=radio]{padding:0}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}::-moz-focus-inner{padding:0;border-style:none}:-moz-focusring{outline:0}:-moz-ui-invalid{box-shadow:none}::-ms-expand{display:none}[type=file],[type=range]{padding:0;border-width:0}input:not([type=checkbox],[type=radio],[type=range]){height:calc(1rem * var(--line-height) + var(--form-element-spacing-vertical) * 2 + var(--border-width) * 2)}fieldset{margin:0;margin-bottom:var(--spacing);padding:0;border:0}fieldset legend,label{display:block;margin-bottom:calc(var(--spacing) * .25);font-weight:var(--form-label-font-weight,var(--font-weight))}input:not([type=checkbox],[type=radio]),select,textarea{width:100%}input:not([type=checkbox],[type=radio],[type=range],[type=file]),select,textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal)}input,select,textarea{--background-color:var(--form-element-background-color);--border-color:var(--form-element-border-color);--color:var(--form-element-color);--box-shadow:none;border:var(--border-width) solid var(--border-color);border-radius:var(--border-radius);outline:0;background-color:var(--background-color);box-shadow:var(--box-shadow);color:var(--color);font-weight:var(--font-weight);transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)}:where(select,textarea):is(:active,:focus),input:not([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[readonly]):is(:active,:focus){--background-color:var(--form-element-active-background-color)}:where(select,textarea):is(:active,:focus),input:not([type=submit],[type=button],[type=reset],[role=switch],[readonly]):is(:active,:focus){--border-color:var(--form-element-active-border-color)}input:not([type=submit],[type=button],[type=reset],[type=range],[type=file],[readonly]):focus,select:focus,textarea:focus{--box-shadow:0 0 0 var(--outline-width) var(--form-element-focus-color)}:where(fieldset[disabled]) :is(input:not([type=submit],[type=button],[type=reset]),select,textarea),input:not([type=submit],[type=button],[type=reset])[disabled],select[disabled],textarea[disabled]{--background-color:var(--form-element-disabled-background-color);--border-color:var(--form-element-disabled-border-color);opacity:var(--form-element-disabled-opacity);pointer-events:none}:where(input,select,textarea):not([type=checkbox],[type=radio],[type=date],[type=datetime-local],[type=month],[type=time],[type=week])[aria-invalid]{padding-right:calc(var(--form-element-spacing-horizontal) + 1.5rem)!important;padding-left:var(--form-element-spacing-horizontal);-webkit-padding-start:var(--form-element-spacing-horizontal)!important;padding-inline-start:var(--form-element-spacing-horizontal)!important;-webkit-padding-end:calc(var(--form-element-spacing-horizontal) + 1.5rem)!important;padding-inline-end:calc(var(--form-element-spacing-horizontal) + 1.5rem)!important;background-position:center right .75rem;background-size:1rem auto;background-repeat:no-repeat}:where(input,select,textarea):not([type=checkbox],[type=radio],[type=date],[type=datetime-local],[type=month],[type=time],[type=week])[aria-invalid=false]{background-image:var(--icon-valid)}:where(input,select,textarea):not([type=checkbox],[type=radio],[type=date],[type=datetime-local],[type=month],[type=time],[type=week])[aria-invalid=true]{background-image:var(--icon-invalid)}:where(input,select,textarea)[aria-invalid=false]{--border-color:var(--form-element-valid-border-color)}:where(input,select,textarea)[aria-invalid=false]:is(:active,:focus){--border-color:var(--form-element-valid-active-border-color)!important;--box-shadow:0 0 0 var(--outline-width) var(--form-element-valid-focus-color)!important}:where(input,select,textarea)[aria-invalid=true]{--border-color:var(--form-element-invalid-border-color)}:where(input,select,textarea)[aria-invalid=true]:is(:active,:focus){--border-color:var(--form-element-invalid-active-border-color)!important;--box-shadow:0 0 0 var(--outline-width) var(--form-element-invalid-focus-color)!important}[dir=rtl] :where(input,select,textarea):not([type=checkbox],[type=radio]):is([aria-invalid],[aria-invalid=true],[aria-invalid=false]){background-position:center left .75rem}input::-webkit-input-placeholder,input::placeholder,select:invalid,textarea::-webkit-input-placeholder,textarea::placeholder{color:var(--form-element-placeholder-color);opacity:1}input:not([type=checkbox],[type=radio]),select,textarea{margin-bottom:var(--spacing)}select::-ms-expand{border:0;background-color:transparent}select:not([multiple],[size]){padding-right:calc(var(--form-element-spacing-horizontal) + 1.5rem);padding-left:var(--form-element-spacing-horizontal);-webkit-padding-start:var(--form-element-spacing-horizontal);padding-inline-start:var(--form-element-spacing-horizontal);-webkit-padding-end:calc(var(--form-element-spacing-horizontal) + 1.5rem);padding-inline-end:calc(var(--form-element-spacing-horizontal) + 1.5rem);background-image:var(--icon-chevron);background-position:center right .75rem;background-size:1rem auto;background-repeat:no-repeat}[dir=rtl] select:not([multiple],[size]){background-position:center left .75rem}:where(input,select,textarea,.grid)+small{display:block;width:100%;margin-top:calc(var(--spacing) * -.75);margin-bottom:var(--spacing);color:var(--muted-color)}label>:where(input,select,textarea){margin-top:calc(var(--spacing) * .25)}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:1.25em;height:1.25em;margin-top:-.125em;margin-right:.375em;margin-left:0;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:.375em;margin-inline-end:.375em;border-width:var(--border-width);font-size:inherit;vertical-align:middle;cursor:pointer}[type=checkbox]::-ms-check,[type=radio]::-ms-check{display:none}[type=checkbox]:checked,[type=checkbox]:checked:active,[type=checkbox]:checked:focus,[type=radio]:checked,[type=radio]:checked:active,[type=radio]:checked:focus{--background-color:var(--primary);--border-color:var(--primary);background-image:var(--icon-checkbox);background-position:center;background-size:.75em auto;background-repeat:no-repeat}[type=checkbox]~label,[type=radio]~label{display:inline-block;margin-right:.375em;margin-bottom:0;cursor:pointer}[type=checkbox]:indeterminate{--background-color:var(--primary);--border-color:var(--primary);background-image:var(--icon-minus);background-position:center;background-size:.75em auto;background-repeat:no-repeat}[type=radio]{border-radius:50%}[type=radio]:checked,[type=radio]:checked:active,[type=radio]:checked:focus{--background-color:var(--primary-inverse);border-width:.35em;background-image:none}[type=checkbox][role=switch]{--background-color:var(--switch-background-color);--border-color:var(--switch-background-color);--color:var(--switch-color);width:2.25em;height:1.25em;border:var(--border-width) solid var(--border-color);border-radius:1.25em;background-color:var(--background-color);line-height:1.25em}[type=checkbox][role=switch]:focus{--background-color:var(--switch-background-color);--border-color:var(--switch-background-color)}[type=checkbox][role=switch]:checked{--background-color:var(--switch-checked-background-color);--border-color:var(--switch-checked-background-color)}[type=checkbox][role=switch]:before{display:block;width:calc(1.25em - (var(--border-width) * 2));height:100%;border-radius:50%;background-color:var(--color);content:"";transition:margin .1s ease-in-out}[type=checkbox][role=switch]:checked{background-image:none}[type=checkbox][role=switch]:checked::before{margin-left:calc(1.125em - var(--border-width));-webkit-margin-start:calc(1.125em - var(--border-width));margin-inline-start:calc(1.125em - var(--border-width))}[type=checkbox]:checked[aria-invalid=false],[type=checkbox][aria-invalid=false],[type=checkbox][role=switch]:checked[aria-invalid=false],[type=checkbox][role=switch][aria-invalid=false],[type=radio]:checked[aria-invalid=false],[type=radio][aria-invalid=false]{--border-color:var(--form-element-valid-border-color)}[type=checkbox]:checked[aria-invalid=true],[type=checkbox][aria-invalid=true],[type=checkbox][role=switch]:checked[aria-invalid=true],[type=checkbox][role=switch][aria-invalid=true],[type=radio]:checked[aria-invalid=true],[type=radio][aria-invalid=true]{--border-color:var(--form-element-invalid-border-color)}[type=color]::-webkit-color-swatch-wrapper{padding:0}[type=color]::-moz-focus-inner{padding:0}[type=color]::-webkit-color-swatch{border:0;border-radius:calc(var(--border-radius) * .5)}[type=color]::-moz-color-swatch{border:0;border-radius:calc(var(--border-radius) * .5)}input:not([type=checkbox],[type=radio],[type=range],[type=file]):is([type=date],[type=datetime-local],[type=month],[type=time],[type=week]){--icon-position:0.75rem;--icon-width:1rem;padding-right:calc(var(--icon-width) + var(--icon-position));background-image:var(--icon-date);background-position:center right var(--icon-position);background-size:var(--icon-width) auto;background-repeat:no-repeat}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=time]{background-image:var(--icon-time)}[type=date]::-webkit-calendar-picker-indicator,[type=datetime-local]::-webkit-calendar-picker-indicator,[type=month]::-webkit-calendar-picker-indicator,[type=time]::-webkit-calendar-picker-indicator,[type=week]::-webkit-calendar-picker-indicator{width:var(--icon-width);margin-right:calc(var(--icon-width) * -1);margin-left:var(--icon-position);opacity:0}[dir=rtl] :is([type=date],[type=datetime-local],[type=month],[type=time],[type=week]){text-align:right}@-moz-document url-prefix(){[type=date],[type=datetime-local],[type=month],[type=time],[type=week]{padding-right:var(--form-element-spacing-horizontal)!important;background-image:none!important}}[type=file]{--color:var(--muted-color);padding:calc(var(--form-element-spacing-vertical) * .5) 0;border:0;border-radius:0;background:0 0}[type=file]::file-selector-button{--background-color:var(--secondary);--border-color:var(--secondary);--color:var(--secondary-inverse);margin-right:calc(var(--spacing)/ 2);margin-left:0;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:calc(var(--spacing)/ 2);margin-inline-end:calc(var(--spacing)/ 2);padding:calc(var(--form-element-spacing-vertical) * .5) calc(var(--form-element-spacing-horizontal) * .5);border:var(--border-width) solid var(--border-color);border-radius:var(--border-radius);outline:0;background-color:var(--background-color);box-shadow:var(--box-shadow);color:var(--color);font-weight:var(--font-weight);font-size:1rem;line-height:var(--line-height);text-align:center;cursor:pointer;transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)}[type=file]::file-selector-button:is(:hover,:active,:focus){--background-color:var(--secondary-hover);--border-color:var(--secondary-hover)}[type=file]::-webkit-file-upload-button{--background-color:var(--secondary);--border-color:var(--secondary);--color:var(--secondary-inverse);margin-right:calc(var(--spacing)/ 2);margin-left:0;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:calc(var(--spacing)/ 2);margin-inline-end:calc(var(--spacing)/ 2);padding:calc(var(--form-element-spacing-vertical) * .5) calc(var(--form-element-spacing-horizontal) * .5);border:var(--border-width) solid var(--border-color);border-radius:var(--border-radius);outline:0;background-color:var(--background-color);box-shadow:var(--box-shadow);color:var(--color);font-weight:var(--font-weight);font-size:1rem;line-height:var(--line-height);text-align:center;cursor:pointer;-webkit-transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition);transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)}[type=file]::-webkit-file-upload-button:is(:hover,:active,:focus){--background-color:var(--secondary-hover);--border-color:var(--secondary-hover)}[type=file]::-ms-browse{--background-color:var(--secondary);--border-color:var(--secondary);--color:var(--secondary-inverse);margin-right:calc(var(--spacing)/ 2);margin-left:0;margin-inline-start:0;margin-inline-end:calc(var(--spacing)/ 2);padding:calc(var(--form-element-spacing-vertical) * .5) calc(var(--form-element-spacing-horizontal) * .5);border:var(--border-width) solid var(--border-color);border-radius:var(--border-radius);outline:0;background-color:var(--background-color);box-shadow:var(--box-shadow);color:var(--color);font-weight:var(--font-weight);font-size:1rem;line-height:var(--line-height);text-align:center;cursor:pointer;-ms-transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition);transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)}[type=file]::-ms-browse:is(:hover,:active,:focus){--background-color:var(--secondary-hover);--border-color:var(--secondary-hover)}[type=range]{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;height:1.25rem;background:0 0}[type=range]::-webkit-slider-runnable-track{width:100%;height:.25rem;border-radius:var(--border-radius);background-color:var(--range-border-color);-webkit-transition:background-color var(--transition),box-shadow var(--transition);transition:background-color var(--transition),box-shadow var(--transition)}[type=range]::-moz-range-track{width:100%;height:.25rem;border-radius:var(--border-radius);background-color:var(--range-border-color);-moz-transition:background-color var(--transition),box-shadow var(--transition);transition:background-color var(--transition),box-shadow var(--transition)}[type=range]::-ms-track{width:100%;height:.25rem;border-radius:var(--border-radius);background-color:var(--range-border-color);-ms-transition:background-color var(--transition),box-shadow var(--transition);transition:background-color var(--transition),box-shadow var(--transition)}[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:1.25rem;height:1.25rem;margin-top:-.5rem;border:2px solid var(--range-thumb-border-color);border-radius:50%;background-color:var(--range-thumb-color);cursor:pointer;-webkit-transition:background-color var(--transition),transform var(--transition);transition:background-color var(--transition),transform var(--transition)}[type=range]::-moz-range-thumb{-webkit-appearance:none;width:1.25rem;height:1.25rem;margin-top:-.5rem;border:2px solid var(--range-thumb-border-color);border-radius:50%;background-color:var(--range-thumb-color);cursor:pointer;-moz-transition:background-color var(--transition),transform var(--transition);transition:background-color var(--transition),transform var(--transition)}[type=range]::-ms-thumb{-webkit-appearance:none;width:1.25rem;height:1.25rem;margin-top:-.5rem;border:2px solid var(--range-thumb-border-color);border-radius:50%;background-color:var(--range-thumb-color);cursor:pointer;-ms-transition:background-color var(--transition),transform var(--transition);transition:background-color var(--transition),transform var(--transition)}[type=range]:focus,[type=range]:hover{--range-border-color:var(--range-active-border-color);--range-thumb-color:var(--range-thumb-hover-color)}[type=range]:active{--range-thumb-color:var(--range-thumb-active-color)}[type=range]:active::-webkit-slider-thumb{transform:scale(1.25)}[type=range]:active::-moz-range-thumb{transform:scale(1.25)}[type=range]:active::-ms-thumb{transform:scale(1.25)}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search]{-webkit-padding-start:calc(var(--form-element-spacing-horizontal) + 1.75rem);padding-inline-start:calc(var(--form-element-spacing-horizontal) + 1.75rem);border-radius:5rem;background-image:var(--icon-search);background-position:center left 1.125rem;background-size:1rem auto;background-repeat:no-repeat}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid]{-webkit-padding-start:calc(var(--form-element-spacing-horizontal) + 1.75rem)!important;padding-inline-start:calc(var(--form-element-spacing-horizontal) + 1.75rem)!important;background-position:center left 1.125rem,center right .75rem}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid=false]{background-image:var(--icon-search),var(--icon-valid)}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid=true]{background-image:var(--icon-search),var(--icon-invalid)}[type=search]::-webkit-search-cancel-button{-webkit-appearance:none;display:none}[dir=rtl] :where(input):not([type=checkbox],[type=radio],[type=range],[type=file])[type=search]{background-position:center right 1.125rem}[dir=rtl] :where(input):not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid]{background-position:center right 1.125rem,center left .75rem}:where(table){width:100%;border-collapse:collapse;border-spacing:0;text-indent:0}td,th{padding:calc(var(--spacing)/ 2) var(--spacing);border-bottom:var(--border-width) solid var(--table-border-color);color:var(--color);font-weight:var(--font-weight);font-size:var(--font-size);text-align:left;text-align:start}tfoot td,tfoot th{border-top:var(--border-width) solid var(--table-border-color);border-bottom:0}table[role=grid] tbody tr:nth-child(odd){background-color:var(--table-row-stripped-background-color)}code,kbd,pre,samp{font-size:.875em;font-family:var(--font-family)}pre{-ms-overflow-style:scrollbar;overflow:auto}code,kbd,pre{border-radius:var(--border-radius);background:var(--code-background-color);color:var(--code-color);font-weight:var(--font-weight);line-height:initial}code,kbd{display:inline-block;padding:.375rem .5rem}pre{display:block;margin-bottom:var(--spacing);overflow-x:auto}pre>code{display:block;padding:var(--spacing);background:0 0;font-size:14px;line-height:var(--line-height)}code b{color:var(--code-tag-color);font-weight:var(--font-weight)}code i{color:var(--code-property-color);font-style:normal}code u{color:var(--code-value-color);text-decoration:none}code em{color:var(--code-comment-color);font-style:normal}kbd{background-color:var(--code-kbd-background-color);color:var(--code-kbd-color);vertical-align:baseline}hr{height:0;border:0;border-top:1px solid var(--muted-border-color);color:inherit}[hidden],template{display:none!important}canvas{display:inline-block}details{display:block;margin-bottom:var(--spacing);padding-bottom:var(--spacing);border-bottom:var(--border-width) solid var(--accordion-border-color)}details summary{line-height:1rem;list-style-type:none;cursor:pointer;transition:color var(--transition)}details summary:not([role]){color:var(--accordion-close-summary-color)}details summary::-webkit-details-marker{display:none}details summary::marker{display:none}details summary::-moz-list-bullet{list-style-type:none}details summary::after{display:block;width:1rem;height:1rem;-webkit-margin-start:calc(var(--spacing,1rem) * 0.5);margin-inline-start:calc(var(--spacing,1rem) * .5);float:right;transform:rotate(-90deg);background-image:var(--icon-chevron);background-position:right center;background-size:1rem auto;background-repeat:no-repeat;content:"";transition:transform var(--transition)}details summary:focus{outline:0}details summary:focus:not([role=button]){color:var(--accordion-active-summary-color)}details summary[role=button]{width:100%;text-align:left}details summary[role=button]::after{height:calc(1rem * var(--line-height,1.5));background-image:var(--icon-chevron-button)}details summary[role=button]:not(.outline).contrast::after{background-image:var(--icon-chevron-button-inverse)}details[open]>summary{margin-bottom:calc(var(--spacing))}details[open]>summary:not([role]):not(:focus){color:var(--accordion-open-summary-color)}details[open]>summary::after{transform:rotate(0)}[dir=rtl] details summary{text-align:right}[dir=rtl] details summary::after{float:left;background-position:left center}article{margin:var(--block-spacing-vertical) 0;padding:var(--block-spacing-vertical) var(--block-spacing-horizontal);border-radius:var(--border-radius);background:var(--card-background-color);box-shadow:var(--card-box-shadow)}article>footer,article>header{margin-right:calc(var(--block-spacing-horizontal) * -1);margin-left:calc(var(--block-spacing-horizontal) * -1);padding:calc(var(--block-spacing-vertical) * .66) var(--block-spacing-horizontal);background-color:var(--card-sectionning-background-color)}article>header{margin-top:calc(var(--block-spacing-vertical) * -1);margin-bottom:var(--block-spacing-vertical);border-bottom:var(--border-width) solid var(--card-border-color);border-top-right-radius:var(--border-radius);border-top-left-radius:var(--border-radius)}article>footer{margin-top:var(--block-spacing-vertical);margin-bottom:calc(var(--block-spacing-vertical) * -1);border-top:var(--border-width) solid var(--card-border-color);border-bottom-right-radius:var(--border-radius);border-bottom-left-radius:var(--border-radius)}:root{--scrollbar-width:0px}dialog{display:flex;z-index:999;position:fixed;top:0;right:0;bottom:0;left:0;align-items:center;justify-content:center;width:inherit;min-width:100%;height:inherit;min-height:100%;padding:var(--spacing);border:0;-webkit-backdrop-filter:var(--modal-overlay-backdrop-filter);backdrop-filter:var(--modal-overlay-backdrop-filter);background-color:var(--modal-overlay-background-color);color:var(--color)}dialog article{max-height:calc(100vh - var(--spacing) * 2);overflow:auto}@media (min-width:576px){dialog article{max-width:510px}}@media (min-width:768px){dialog article{max-width:700px}}dialog article>footer,dialog article>header{padding:calc(var(--block-spacing-vertical) * .5) var(--block-spacing-horizontal)}dialog article>header .close{margin:0;margin-left:var(--spacing);float:right}dialog article>footer{text-align:right}dialog article>footer [role=button]{margin-bottom:0}dialog article>footer [role=button]:not(:first-of-type){margin-left:calc(var(--spacing) * .5)}dialog article p:last-of-type{margin:0}dialog article .close{display:block;width:1rem;height:1rem;margin-top:calc(var(--block-spacing-vertical) * -.5);margin-bottom:var(--typography-spacing-vertical);margin-left:auto;background-image:var(--icon-close);background-position:center;background-size:auto 1rem;background-repeat:no-repeat;opacity:.5;transition:opacity var(--transition)}dialog article .close:is([aria-current],:hover,:active,:focus){opacity:1}dialog:not([open]),dialog[open=false]{display:none}.modal-is-open{padding-right:var(--scrollbar-width,0);overflow:hidden;pointer-events:none;touch-action:none}.modal-is-open dialog{pointer-events:auto}:where(.modal-is-opening,.modal-is-closing) dialog,:where(.modal-is-opening,.modal-is-closing) dialog>article{animation-duration:.2s;animation-timing-function:ease-in-out;animation-fill-mode:both}:where(.modal-is-opening,.modal-is-closing) dialog{animation-duration:.8s;animation-name:modal-overlay}:where(.modal-is-opening,.modal-is-closing) dialog>article{animation-delay:.2s;animation-name:modal}.modal-is-closing dialog,.modal-is-closing dialog>article{animation-delay:0s;animation-direction:reverse}@keyframes modal-overlay{from{-webkit-backdrop-filter:none;backdrop-filter:none;background-color:transparent}}@keyframes modal{from{transform:translateY(-100%);opacity:0}}:where(nav li)::before{float:left;content:"​"}nav,nav ul{display:flex}nav{justify-content:space-between}nav ol,nav ul{align-items:center;margin-bottom:0;padding:0;list-style:none}nav ol:first-of-type,nav ul:first-of-type{margin-left:calc(var(--nav-element-spacing-horizontal) * -1)}nav ol:last-of-type,nav ul:last-of-type{margin-right:calc(var(--nav-element-spacing-horizontal) * -1)}nav li{display:inline-block;margin:0;padding:var(--nav-element-spacing-vertical) var(--nav-element-spacing-horizontal)}nav li>*{--spacing:0}nav :where(a,[role=link]){display:inline-block;margin:calc(var(--nav-link-spacing-vertical) * -1) calc(var(--nav-link-spacing-horizontal) * -1);padding:var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal);border-radius:var(--border-radius);text-decoration:none}nav :where(a,[role=link]):is([aria-current],:hover,:active,:focus){text-decoration:none}nav[aria-label=breadcrumb]{align-items:center;justify-content:start}nav[aria-label=breadcrumb] ul li:not(:first-child){-webkit-margin-start:var(--nav-link-spacing-horizontal);margin-inline-start:var(--nav-link-spacing-horizontal)}nav[aria-label=breadcrumb] ul li:not(:last-child) ::after{position:absolute;width:calc(var(--nav-link-spacing-horizontal) * 2);-webkit-margin-start:calc(var(--nav-link-spacing-horizontal)/ 2);margin-inline-start:calc(var(--nav-link-spacing-horizontal)/ 2);content:"/";color:var(--muted-color);text-align:center}nav[aria-label=breadcrumb] a[aria-current]{background-color:transparent;color:inherit;text-decoration:none;pointer-events:none}nav [role=button]{margin-right:inherit;margin-left:inherit;padding:var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal)}aside li,aside nav,aside ol,aside ul{display:block}aside li{padding:calc(var(--nav-element-spacing-vertical) * .5) var(--nav-element-spacing-horizontal)}aside li a{display:block}aside li [role=button]{margin:inherit}[dir=rtl] nav[aria-label=breadcrumb] ul li:not(:last-child) ::after{content:"\\"}progress{display:inline-block;vertical-align:baseline}progress{-webkit-appearance:none;-moz-appearance:none;display:inline-block;appearance:none;width:100%;height:.5rem;margin-bottom:calc(var(--spacing) * .5);overflow:hidden;border:0;border-radius:var(--border-radius);background-color:var(--progress-background-color);color:var(--progress-color)}progress::-webkit-progress-bar{border-radius:var(--border-radius);background:0 0}progress[value]::-webkit-progress-value{background-color:var(--progress-color)}progress::-moz-progress-bar{background-color:var(--progress-color)}@media (prefers-reduced-motion:no-preference){progress:indeterminate{background:var(--progress-background-color) linear-gradient(to right,var(--progress-color) 30%,var(--progress-background-color) 30%) top left/150% 150% no-repeat;animation:progress-indeterminate 1s linear infinite}progress:indeterminate[value]::-webkit-progress-value{background-color:transparent}progress:indeterminate::-moz-progress-bar{background-color:transparent}}@media (prefers-reduced-motion:no-preference){[dir=rtl] progress:indeterminate{animation-direction:reverse}}@keyframes progress-indeterminate{0%{background-position:200% 0}100%{background-position:-200% 0}}details[role=list],li[role=list]{position:relative}details[role=list] summary+ul,li[role=list]>ul{display:flex;z-index:99;position:absolute;top:auto;right:0;left:0;flex-direction:column;margin:0;padding:0;border:var(--border-width) solid var(--dropdown-border-color);border-radius:var(--border-radius);border-top-right-radius:0;border-top-left-radius:0;background-color:var(--dropdown-background-color);box-shadow:var(--card-box-shadow);color:var(--dropdown-color);white-space:nowrap}details[role=list] summary+ul li,li[role=list]>ul li{width:100%;margin-bottom:0;padding:calc(var(--form-element-spacing-vertical) * .5) var(--form-element-spacing-horizontal);list-style:none}details[role=list] summary+ul li:first-of-type,li[role=list]>ul li:first-of-type{margin-top:calc(var(--form-element-spacing-vertical) * .5)}details[role=list] summary+ul li:last-of-type,li[role=list]>ul li:last-of-type{margin-bottom:calc(var(--form-element-spacing-vertical) * .5)}details[role=list] summary+ul li a,li[role=list]>ul li a{display:block;margin:calc(var(--form-element-spacing-vertical) * -.5) calc(var(--form-element-spacing-horizontal) * -1);padding:calc(var(--form-element-spacing-vertical) * .5) var(--form-element-spacing-horizontal);overflow:hidden;color:var(--dropdown-color);text-decoration:none;text-overflow:ellipsis}details[role=list] summary+ul li a:hover,li[role=list]>ul li a:hover{background-color:var(--dropdown-hover-background-color)}details[role=list] summary::after,li[role=list]>a::after{display:block;width:1rem;height:calc(1rem * var(--line-height,1.5));-webkit-margin-start:0.5rem;margin-inline-start:.5rem;float:right;transform:rotate(0);background-position:right center;background-size:1rem auto;background-repeat:no-repeat;content:""}details[role=list]{padding:0;border-bottom:none}details[role=list] summary{margin-bottom:0}details[role=list] summary:not([role]){height:calc(1rem * var(--line-height) + var(--form-element-spacing-vertical) * 2 + var(--border-width) * 2);padding:var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal);border:var(--border-width) solid var(--form-element-border-color);border-radius:var(--border-radius);background-color:var(--form-element-background-color);color:var(--form-element-placeholder-color);line-height:inherit;cursor:pointer;transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)}details[role=list] summary:not([role]):active,details[role=list] summary:not([role]):focus{border-color:var(--form-element-active-border-color);background-color:var(--form-element-active-background-color)}details[role=list] summary:not([role]):focus{box-shadow:0 0 0 var(--outline-width) var(--form-element-focus-color)}details[role=list][open] summary{border-bottom-right-radius:0;border-bottom-left-radius:0}details[role=list][open] summary::before{display:block;z-index:1;position:fixed;top:0;right:0;bottom:0;left:0;background:0 0;content:"";cursor:default}nav details[role=list] summary,nav li[role=list] a{display:flex;direction:ltr}nav details[role=list] summary+ul,nav li[role=list]>ul{min-width:-moz-fit-content;min-width:fit-content;border-radius:var(--border-radius)}nav details[role=list] summary+ul li a,nav li[role=list]>ul li a{border-radius:0}nav details[role=list] summary,nav details[role=list] summary:not([role]){height:auto;padding:var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal)}nav details[role=list][open] summary{border-radius:var(--border-radius)}nav details[role=list] summary+ul{margin-top:var(--outline-width);-webkit-margin-start:0;margin-inline-start:0}nav details[role=list] summary[role=link]{margin-bottom:calc(var(--nav-link-spacing-vertical) * -1);line-height:var(--line-height)}nav details[role=list] summary[role=link]+ul{margin-top:calc(var(--nav-link-spacing-vertical) + var(--outline-width));-webkit-margin-start:calc(var(--nav-link-spacing-horizontal) * -1);margin-inline-start:calc(var(--nav-link-spacing-horizontal) * -1)}li[role=list] a:active~ul,li[role=list] a:focus~ul,li[role=list]:hover>ul{display:flex}li[role=list]>ul{display:none;margin-top:calc(var(--nav-link-spacing-vertical) + var(--outline-width));-webkit-margin-start:calc(var(--nav-element-spacing-horizontal) - var(--nav-link-spacing-horizontal));margin-inline-start:calc(var(--nav-element-spacing-horizontal) - var(--nav-link-spacing-horizontal))}li[role=list]>a::after{background-image:var(--icon-chevron)}label>details[role=list]{margin-top:calc(var(--spacing) * .25);margin-bottom:var(--spacing)}[aria-busy=true]{cursor:progress}[aria-busy=true]:not(input,select,textarea,html)::before{display:inline-block;width:1em;height:1em;border:.1875em solid currentColor;border-radius:1em;border-right-color:transparent;content:"";vertical-align:text-bottom;vertical-align:-.125em;animation:spinner .75s linear infinite;opacity:var(--loading-spinner-opacity)}[aria-busy=true]:not(input,select,textarea,html):not(:empty)::before{margin-right:calc(var(--spacing) * .5);margin-left:0;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:calc(var(--spacing) * .5);margin-inline-end:calc(var(--spacing) * .5)}[aria-busy=true]:not(input,select,textarea,html):empty{text-align:center}a[aria-busy=true],button[aria-busy=true],input[type=button][aria-busy=true],input[type=reset][aria-busy=true],input[type=submit][aria-busy=true]{pointer-events:none}@keyframes spinner{to{transform:rotate(360deg)}}[data-tooltip]{position:relative}[data-tooltip]:not(a,button,input){border-bottom:1px dotted;text-decoration:none;cursor:help}[data-tooltip]::after,[data-tooltip]::before,[data-tooltip][data-placement=top]::after,[data-tooltip][data-placement=top]::before{display:block;z-index:99;position:absolute;bottom:100%;left:50%;padding:.25rem .5rem;overflow:hidden;transform:translate(-50%,-.25rem);border-radius:var(--border-radius);background:var(--tooltip-background-color);content:attr(data-tooltip);color:var(--tooltip-color);font-style:normal;font-weight:var(--font-weight);font-size:.875rem;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;opacity:0;pointer-events:none}[data-tooltip]::after,[data-tooltip][data-placement=top]::after{padding:0;transform:translate(-50%,0);border-top:.3rem solid;border-right:.3rem solid transparent;border-left:.3rem solid transparent;border-radius:0;background-color:transparent;content:"";color:var(--tooltip-background-color)}[data-tooltip][data-placement=bottom]::after,[data-tooltip][data-placement=bottom]::before{top:100%;bottom:auto;transform:translate(-50%,.25rem)}[data-tooltip][data-placement=bottom]:after{transform:translate(-50%,-.3rem);border:.3rem solid transparent;border-bottom:.3rem solid}[data-tooltip][data-placement=left]::after,[data-tooltip][data-placement=left]::before{top:50%;right:100%;bottom:auto;left:auto;transform:translate(-.25rem,-50%)}[data-tooltip][data-placement=left]:after{transform:translate(.3rem,-50%);border:.3rem solid transparent;border-left:.3rem solid}[data-tooltip][data-placement=right]::after,[data-tooltip][data-placement=right]::before{top:50%;right:auto;bottom:auto;left:100%;transform:translate(.25rem,-50%)}[data-tooltip][data-placement=right]:after{transform:translate(-.3rem,-50%);border:.3rem solid transparent;border-right:.3rem solid}[data-tooltip]:focus::after,[data-tooltip]:focus::before,[data-tooltip]:hover::after,[data-tooltip]:hover::before{opacity:1}@media (hover:hover) and (pointer:fine){[data-tooltip]:hover::after,[data-tooltip]:hover::before,[data-tooltip][data-placement=bottom]:focus::after,[data-tooltip][data-placement=bottom]:focus::before,[data-tooltip][data-placement=bottom]:hover [data-tooltip]:focus::after,[data-tooltip][data-placement=bottom]:hover [data-tooltip]:focus::before{animation-duration:.2s;animation-name:tooltip-slide-top}[data-tooltip]:hover::after,[data-tooltip][data-placement=bottom]:focus::after,[data-tooltip][data-placement=bottom]:hover [data-tooltip]:focus::after{animation-name:tooltip-caret-slide-top}[data-tooltip][data-placement=bottom]:focus::after,[data-tooltip][data-placement=bottom]:focus::before,[data-tooltip][data-placement=bottom]:hover::after,[data-tooltip][data-placement=bottom]:hover::before{animation-duration:.2s;animation-name:tooltip-slide-bottom}[data-tooltip][data-placement=bottom]:focus::after,[data-tooltip][data-placement=bottom]:hover::after{animation-name:tooltip-caret-slide-bottom}[data-tooltip][data-placement=left]:focus::after,[data-tooltip][data-placement=left]:focus::before,[data-tooltip][data-placement=left]:hover::after,[data-tooltip][data-placement=left]:hover::before{animation-duration:.2s;animation-name:tooltip-slide-left}[data-tooltip][data-placement=left]:focus::after,[data-tooltip][data-placement=left]:hover::after{animation-name:tooltip-caret-slide-left}[data-tooltip][data-placement=right]:focus::after,[data-tooltip][data-placement=right]:focus::before,[data-tooltip][data-placement=right]:hover::after,[data-tooltip][data-placement=right]:hover::before{animation-duration:.2s;animation-name:tooltip-slide-right}[data-tooltip][data-placement=right]:focus::after,[data-tooltip][data-placement=right]:hover::after{animation-name:tooltip-caret-slide-right}}@keyframes tooltip-slide-top{from{transform:translate(-50%,.75rem);opacity:0}to{transform:translate(-50%,-.25rem);opacity:1}}@keyframes tooltip-caret-slide-top{from{opacity:0}50%{transform:translate(-50%,-.25rem);opacity:0}to{transform:translate(-50%,0);opacity:1}}@keyframes tooltip-slide-bottom{from{transform:translate(-50%,-.75rem);opacity:0}to{transform:translate(-50%,.25rem);opacity:1}}@keyframes tooltip-caret-slide-bottom{from{opacity:0}50%{transform:translate(-50%,-.5rem);opacity:0}to{transform:translate(-50%,-.3rem);opacity:1}}@keyframes tooltip-slide-left{from{transform:translate(.75rem,-50%);opacity:0}to{transform:translate(-.25rem,-50%);opacity:1}}@keyframes tooltip-caret-slide-left{from{opacity:0}50%{transform:translate(.05rem,-50%);opacity:0}to{transform:translate(.3rem,-50%);opacity:1}}@keyframes tooltip-slide-right{from{transform:translate(-.75rem,-50%);opacity:0}to{transform:translate(.25rem,-50%);opacity:1}}@keyframes tooltip-caret-slide-right{from{opacity:0}50%{transform:translate(-.05rem,-50%);opacity:0}to{transform:translate(-.3rem,-50%);opacity:1}}[aria-controls]{cursor:pointer}[aria-disabled=true],[disabled]{cursor:not-allowed}[aria-hidden=false][hidden]{display:initial}[aria-hidden=false][hidden]:not(:focus){clip:rect(0,0,0,0);position:absolute}[tabindex],a,area,button,input,label,select,summary,textarea{-ms-touch-action:manipulation}[dir=rtl]{direction:rtl}@media (prefers-reduced-motion:reduce){:not([aria-busy=true]),:not([aria-busy=true])::after,:not([aria-busy=true])::before{background-attachment:initial!important;animation-duration:1ms!important;animation-delay:-1ms!important;animation-iteration-count:1!important;scroll-behavior:auto!important;transition-delay:0s!important;transition-duration:0s!important}}
2506+ /*# sourceMappingURL=pico.min.css.map */
2507\ No newline at end of file
2508 diff --git a/src/database.rs b/src/database.rs
2509new file mode 100644
2510index 0000000..4e6f19f
2511--- /dev/null
2512+++ b/src/database.rs
2513 @@ -0,0 +1,77 @@
2514+ use std::collections::HashMap;
2515+ use std::sync::{Arc, Mutex};
2516+
2517+ use tracing::log::info;
2518+
2519+ use crate::objects;
2520+
2521+ pub type Connection = Arc<Database>;
2522+
2523+ pub type PingTable = HashMap<String, (objects::Ping, Option<objects::Pong>)>;
2524+
2525+ pub struct Database {
2526+ pub users: Mutex<HashMap<String, objects::DbUser>>,
2527+ pub pings: Mutex<HashMap<String, PingTable>>,
2528+ }
2529+
2530+ impl Database {
2531+ pub fn new(users: Vec<objects::DbUser>) -> Connection {
2532+ let users = users.iter().fold(HashMap::new(), |mut db, user| {
2533+ db.insert(user.id.path().to_string(), user.clone());
2534+ db
2535+ });
2536+ Arc::new(Database {
2537+ users: Mutex::new(users),
2538+ pings: Mutex::new(HashMap::new()),
2539+ })
2540+ }
2541+
2542+ pub fn read_user(&self, id: &str) -> Option<(objects::DbUser, Option<PingTable>)> {
2543+ info!("looking up user: {}", id);
2544+ self.users.lock().unwrap().get(id).map(|user| {
2545+ (
2546+ user.clone(),
2547+ self.pings
2548+ .lock()
2549+ .unwrap()
2550+ .get(&user.id.to_string())
2551+ .cloned(),
2552+ )
2553+ })
2554+ }
2555+
2556+ pub fn list_users(&self) -> Vec<(objects::DbUser, Option<PingTable>)> {
2557+ let pings = self.pings.lock().unwrap();
2558+ self.users
2559+ .lock()
2560+ .unwrap()
2561+ .clone()
2562+ .into_values()
2563+ .map(|user| {
2564+ let pm = pings.get(user.id.clone().as_str()).cloned();
2565+ (user.clone(), pm)
2566+ })
2567+ .collect()
2568+ }
2569+
2570+ pub fn upsert_user(&self, user: objects::DbUser) {
2571+ self.users
2572+ .lock()
2573+ .unwrap()
2574+ .insert(user.id.to_string(), user.clone());
2575+ }
2576+
2577+ pub fn write_ping(&self, user: objects::DbUser, ping: objects::Ping) {
2578+ let mut pings = self.pings.lock().expect("unlock");
2579+ match pings.get_mut(&user.id.to_string()) {
2580+ Some(user_pings) => {
2581+ user_pings.insert(ping.unique_id.clone(), (ping.clone(), None));
2582+ }
2583+ None => {
2584+ let mut table: PingTable = HashMap::new();
2585+ table.insert(ping.unique_id.clone(), (ping.clone(), None));
2586+ pings.insert(user.id.to_string(), table);
2587+ }
2588+ };
2589+ }
2590+ }
2591 diff --git a/src/error.rs b/src/error.rs
2592new file mode 100644
2593index 0000000..8e39c54
2594--- /dev/null
2595+++ b/src/error.rs
2596 @@ -0,0 +1,40 @@
2597+ use std::fmt::{Display, Formatter};
2598+
2599+ use axum::{
2600+ http::{HeaderName, HeaderValue, StatusCode},
2601+ response::{IntoResponse, Json, Response},
2602+ };
2603+
2604+ use serde::Serialize;
2605+
2606+ #[derive(Serialize)]
2607+ struct ErrorMessage {
2608+ pub error: String,
2609+ }
2610+
2611+ #[derive(Debug)]
2612+ pub struct Error(pub(crate) anyhow::Error);
2613+
2614+ impl Display for Error {
2615+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2616+ std::fmt::Display::fmt(&self.0, f)
2617+ }
2618+ }
2619+
2620+ impl<T> From<T> for Error
2621+ where
2622+ T: Into<anyhow::Error>,
2623+ {
2624+ fn from(t: T) -> Self {
2625+ Error(t.into())
2626+ }
2627+ }
2628+
2629+ impl IntoResponse for Error {
2630+ fn into_response(self) -> axum::response::Response {
2631+ Json(ErrorMessage {
2632+ error: self.0.to_string(),
2633+ })
2634+ .into_response()
2635+ }
2636+ }
2637 diff --git a/src/handle.rs b/src/handle.rs
2638new file mode 100644
2639index 0000000..40f2d92
2640--- /dev/null
2641+++ b/src/handle.rs
2642 @@ -0,0 +1,102 @@
2643+ use anyhow::Result;
2644+ use serde::{Deserialize, Serialize};
2645+ use tracing::log;
2646+ use url::Url;
2647+
2648+ #[derive(Clone)]
2649+ pub struct Builder {
2650+ pub secure: bool,
2651+ pub default_domain: String,
2652+ }
2653+
2654+ impl Builder {
2655+ fn protocol(&self) -> String {
2656+ if self.secure {
2657+ String::from("https")
2658+ } else {
2659+ String::from("http")
2660+ }
2661+ }
2662+
2663+ pub fn from_url(&self, parsed: Url) -> Handle {
2664+ let domain = parsed.domain().map(|domain| domain.to_string()).unwrap();
2665+ let domain = parsed
2666+ .port()
2667+ .map(|port| format!("{}:{}", domain, port))
2668+ .unwrap_or(domain);
2669+ let user = parsed.path_segments().unwrap().last().unwrap().to_string();
2670+ let handle = Handle((self.protocol(), domain, user));
2671+ log::info!("user: {:?}", handle);
2672+ handle
2673+ }
2674+
2675+ pub fn parse(&self, input: &str) -> Result<Handle> {
2676+ log::info!("parsing user: {}", input);
2677+ let split: Vec<&str> = input.split("@").collect();
2678+ let user = split.get(1).map(|user| user.to_string()).unwrap();
2679+ let domain = split
2680+ .get(2)
2681+ .map(|domain| domain.to_string())
2682+ .unwrap_or(self.default_domain.to_string());
2683+ let handle = if split.len() > 1 {
2684+ Handle((self.protocol(), user, domain))
2685+ } else {
2686+ Handle((self.protocol(), domain, user))
2687+ };
2688+ log::info!("user: {:?}", handle);
2689+ Ok(handle)
2690+ }
2691+
2692+ pub fn parse_url(&self, input: &str) -> Result<Handle> {
2693+ log::info!("parsing user from url: {}", input);
2694+ let parsed = Url::parse(input)?;
2695+ let domain = parsed.domain().map(|domain| domain.to_string()).unwrap();
2696+ let domain = parsed
2697+ .port()
2698+ .map(|port| format!("{}:{}", domain, port))
2699+ .unwrap_or(domain);
2700+ let user = parsed.path_segments().unwrap().last().unwrap().to_string();
2701+ let handle = Handle((self.protocol(), domain, user));
2702+ log::info!("user: {:?}", handle);
2703+ Ok(handle)
2704+ }
2705+ }
2706+
2707+ /// (protocol, domain, username)
2708+ #[derive(Clone, Serialize, Deserialize, Debug)]
2709+ pub struct Handle(pub (String, String, String));
2710+
2711+ impl Handle {
2712+ pub fn to_string(&self, domain: &str) -> String {
2713+ if self.0 .1 == domain {
2714+ format!("@{}", self.0 .2)
2715+ } else {
2716+ format!("@{}@{}", self.0 .1, self.0 .2)
2717+ }
2718+ }
2719+
2720+ pub fn is_local(&self, domain: &str) -> bool {
2721+ self.0 .1 == domain
2722+ }
2723+
2724+ pub fn name(&self) -> String {
2725+ self.0 .2.clone()
2726+ }
2727+
2728+ pub fn id(&self) -> String {
2729+ format!("{}://{}/users/{}", self.0 .0, self.0 .1, self.0 .2)
2730+ }
2731+
2732+ pub fn url(&self) -> Url {
2733+ Url::parse(&self.id()).unwrap()
2734+ }
2735+
2736+ pub fn inbox(&self) -> Url {
2737+ Url::parse(format!("{}://{}/users/{}/inbox", self.0 .0, self.0 .1, self.0 .2).as_str())
2738+ .unwrap()
2739+ }
2740+ pub fn outbox(&self) -> Url {
2741+ Url::parse(format!("{}://{}/users/{}/outbox", self.0 .0, self.0 .1, self.0 .2).as_str())
2742+ .unwrap()
2743+ }
2744+ }
2745 diff --git a/src/main.rs b/src/main.rs
2746new file mode 100644
2747index 0000000..aa35ccb
2748--- /dev/null
2749+++ b/src/main.rs
2750 @@ -0,0 +1,54 @@
2751+ use activitypub_federation::config::FederationConfig;
2752+ use tracing::log::{info, LevelFilter};
2753+
2754+ use clap::{arg, value_parser, Command};
2755+ use url::Url;
2756+
2757+ mod database;
2758+ mod error;
2759+ mod objects;
2760+ mod util;
2761+ mod web;
2762+
2763+ #[tokio::main]
2764+ async fn main() -> Result<(), error::Error> {
2765+ let matches = clap::Command::new("ping-pong")
2766+ .arg(arg!(-d --domain <DOMAIN> "domain / listen address").required(true))
2767+ .arg(arg!(-u --users <USERS> "users for the social network"))
2768+ .get_matches();
2769+ env_logger::builder().filter_level(LevelFilter::Info).init();
2770+ info!("logger configured");
2771+ let domain = matches.get_one::<String>("domain").unwrap();
2772+ let users: Vec<objects::DbUser> = matches
2773+ .get_one::<String>("users")
2774+ .unwrap_or(&String::from(
2775+ "@root,@beatriz,@charles,@fatima,@hanna,@ali,@gabriel@localhost:9998",
2776+ ))
2777+ .split(",")
2778+ .map(|name| {
2779+ let user_fqdn = util::to_url(name, domain.as_str(), false);
2780+ objects::DbUser::new(
2781+ user_fqdn.clone(),
2782+ util::inbox(user_fqdn.clone()),
2783+ util::outbox(user_fqdn.clone()),
2784+ util::is_local(user_fqdn, domain)
2785+ )
2786+ })
2787+ .collect();
2788+ let first_user = users.first().unwrap().clone();
2789+ let database = database::Database::new(users);
2790+ let config = FederationConfig::builder()
2791+ .domain(
2792+ matches
2793+ .get_one("domain")
2794+ .unwrap_or(&String::from("localhost:9999")),
2795+ )
2796+ .debug(true)
2797+ .app_data(database.clone())
2798+ .signed_fetch_actor(&first_user)
2799+ .build()
2800+ .await
2801+ .unwrap();
2802+ web::listen(&config).await?;
2803+ Ok(())
2804+ }
2805 diff --git a/src/objects.rs b/src/objects.rs
2806new file mode 100644
2807index 0000000..8aa35fd
2808--- /dev/null
2809+++ b/src/objects.rs
2810 @@ -0,0 +1,192 @@
2811+ use activitypub_federation::{
2812+ config::Data,
2813+ fetch::object_id::ObjectId,
2814+ http_signatures::generate_actor_keypair,
2815+ traits::{ActivityHandler, Actor, Object},
2816+ };
2817+ use anyhow::{Error, Result};
2818+
2819+ use chrono::NaiveDateTime;
2820+ use serde::{Deserialize, Serialize};
2821+ use tracing::log::info;
2822+ use url::Url;
2823+
2824+ use crate::database::Connection;
2825+
2826+ #[derive(Deserialize, Serialize, Debug)]
2827+ #[serde(untagged)]
2828+ #[enum_delegate::implement(ActivityHandler)]
2829+ pub enum AcceptedActivities {
2830+ Ping(Ping),
2831+ Pong(Pong),
2832+ }
2833+
2834+ #[derive(Debug, Clone, Serialize, Deserialize)]
2835+ #[serde(rename_all = "camelCase")]
2836+ pub struct PublicKey {
2837+ pub public_key_pem: String,
2838+ }
2839+
2840+ #[derive(Debug, Clone, Serialize, Deserialize)]
2841+ #[serde(rename_all = "camelCase")]
2842+ pub struct User {
2843+ pub id: Url,
2844+ pub inbox: Url,
2845+ pub outbox: Url,
2846+ pub public_key: PublicKey,
2847+ }
2848+
2849+ #[derive(Debug, Clone)]
2850+ pub struct DbUser {
2851+ pub id: Url,
2852+ public_key: String,
2853+ private_key: Option<String>,
2854+ inbox: Url,
2855+ outbox: Url,
2856+ internal: bool,
2857+ }
2858+
2859+ impl DbUser {
2860+ // new internal user
2861+ pub fn new(id: Url, inbox: Url, outbox: Url, internal: bool) -> Self {
2862+ let keypair = generate_actor_keypair().unwrap();
2863+ DbUser {
2864+ id,
2865+ public_key: keypair.public_key,
2866+ private_key: Some(keypair.private_key),
2867+ inbox,
2868+ outbox,
2869+ internal,
2870+ }
2871+ }
2872+ }
2873+
2874+ #[async_trait::async_trait]
2875+ impl Object for DbUser {
2876+ type DataType = Connection;
2877+ type Kind = User;
2878+ type Error = Error;
2879+
2880+ fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
2881+ None
2882+ }
2883+
2884+ async fn read_from_id(
2885+ object_id: Url,
2886+ data: &Data<Self::DataType>,
2887+ ) -> Result<Option<Self>, Self::Error> {
2888+ let username = object_id.path().replace("/@", "");
2889+ Ok(data.read_user(&username).map(|result| result.0))
2890+ }
2891+
2892+ async fn from_json(json: Self::Kind, data: &Data<Self::DataType>) -> Result<Self, Self::Error> {
2893+ let user = DbUser {
2894+ id: json.id.clone(),
2895+ public_key: json.public_key.public_key_pem,
2896+ private_key: None,
2897+ inbox: json.inbox,
2898+ outbox: json.outbox,
2899+ internal: true,
2900+ };
2901+ data.upsert_user(user.clone());
2902+ Ok(user)
2903+ }
2904+
2905+ async fn into_json(self, _data: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
2906+ Ok(User {
2907+ id: self.id,
2908+ inbox: self.inbox,
2909+ outbox: self.outbox,
2910+ public_key: PublicKey {
2911+ public_key_pem: self.public_key,
2912+ },
2913+ })
2914+ }
2915+
2916+ async fn verify(
2917+ json: &Self::Kind,
2918+ expected_domain: &Url,
2919+ _data: &Data<Self::DataType>,
2920+ ) -> Result<(), Self::Error> {
2921+ println!("verify being called?");
2922+ Ok(())
2923+ }
2924+ }
2925+
2926+ #[async_trait::async_trait]
2927+ impl Actor for DbUser {
2928+ fn id(&self) -> Url {
2929+ self.id.clone()
2930+ }
2931+
2932+ fn public_key_pem(&self) -> &str {
2933+ &self.public_key
2934+ }
2935+
2936+ fn private_key_pem(&self) -> Option<String> {
2937+ self.private_key.clone()
2938+ }
2939+
2940+ fn inbox(&self) -> Url {
2941+ self.inbox.clone()
2942+ }
2943+ }
2944+
2945+ #[derive(Deserialize, Serialize, Debug, Clone)]
2946+ #[serde(rename_all = "camelCase")]
2947+ pub struct Ping {
2948+ pub unique_id: String,
2949+ pub actor: ObjectId<DbUser>,
2950+ }
2951+
2952+ #[async_trait::async_trait]
2953+ impl ActivityHandler for Ping {
2954+ type DataType = Connection;
2955+ type Error = crate::error::Error;
2956+
2957+ fn id(&self) -> &Url {
2958+ &self.actor.inner()
2959+ }
2960+
2961+ fn actor(&self) -> &Url {
2962+ self.actor.inner()
2963+ }
2964+
2965+ async fn verify(&self, _data: &Data<Self::DataType>) -> Result<(), Self::Error> {
2966+ Ok(())
2967+ }
2968+
2969+ async fn receive(self, data: &Data<Self::DataType>) -> Result<(), Self::Error> {
2970+ println!("HANDLE: {:?} {:?}", self.unique_id, self.actor);
2971+ Ok(())
2972+ }
2973+ }
2974+
2975+ #[derive(Deserialize, Serialize, Debug, Clone)]
2976+ #[serde(rename_all = "camelCase")]
2977+ pub struct Pong {
2978+ actor: ObjectId<DbUser>,
2979+ pub reply_to: String,
2980+ }
2981+
2982+ #[async_trait::async_trait]
2983+ impl ActivityHandler for Pong {
2984+ type DataType = Connection;
2985+ type Error = crate::error::Error;
2986+
2987+ fn id(&self) -> &Url {
2988+ &self.actor.inner()
2989+ }
2990+
2991+ fn actor(&self) -> &Url {
2992+ &self.actor.inner()
2993+ }
2994+
2995+ async fn verify(&self, _data: &Data<Self::DataType>) -> Result<(), Self::Error> {
2996+ Ok(())
2997+ }
2998+
2999+ async fn receive(self, _data: &Data<Self::DataType>) -> Result<(), Self::Error> {
3000+ Ok(())
3001+ }
3002+ }
3003 diff --git a/src/util.rs b/src/util.rs
3004new file mode 100644
3005index 0000000..481439e
3006--- /dev/null
3007+++ b/src/util.rs
3008 @@ -0,0 +1,51 @@
3009+ use url::Url;
3010+
3011+ pub fn to_url(handle: &str, default_domain: &str, secure: bool) -> Url {
3012+ let protocol = if secure { "https" } else { "http" };
3013+ let split: Vec<&str> = handle.split("@").collect();
3014+ let user = split.get(1).map(|user| user.to_string()).unwrap();
3015+ let domain = split
3016+ .get(2)
3017+ .map(|domain| domain.to_string())
3018+ .unwrap_or(default_domain.to_string());
3019+ Url::parse(format!("{}://{}/users/{}", protocol, domain, user).as_str()).unwrap()
3020+ }
3021+
3022+ pub fn handle(url: Url, domain: &str) -> String {
3023+ let user = url.path_segments().unwrap().last().unwrap().to_string();
3024+ let this_domain = url.domain().unwrap();
3025+ let this_domain = format!(
3026+ "{}{}",
3027+ this_domain,
3028+ url.port()
3029+ .map(|port| format!(":{}", port))
3030+ .unwrap_or(String::new())
3031+ );
3032+ if this_domain == domain {
3033+ format!("@{}", user)
3034+ } else {
3035+ format!("@{}@{}", user, this_domain)
3036+ }
3037+ }
3038+
3039+ pub fn is_local(url: Url, domain: &str) -> bool {
3040+ format!(
3041+ "{}:{}",
3042+ url.domain().unwrap_or(""),
3043+ url.port()
3044+ .map(|port| port.to_string())
3045+ .unwrap_or(String::new())
3046+ ) == domain
3047+ }
3048+
3049+ pub fn inbox(url: Url) -> Url {
3050+ let mut url = url.clone();
3051+ url.path_segments_mut().unwrap().push("inbox");
3052+ url.clone()
3053+ }
3054+
3055+ pub fn outbox(url: Url) -> Url {
3056+ let mut url = url.clone();
3057+ url.path_segments_mut().unwrap().push("outbox");
3058+ url.clone()
3059+ }
3060 diff --git a/src/web.rs b/src/web.rs
3061new file mode 100644
3062index 0000000..715c84f
3063--- /dev/null
3064+++ b/src/web.rs
3065 @@ -0,0 +1,201 @@
3066+ use std::net::ToSocketAddrs;
3067+ use std::sync::Arc;
3068+
3069+ use activitypub_federation::{
3070+ activity_queue::send_activity,
3071+ axum::inbox::{receive_activity, ActivityData},
3072+ config::{Data, FederationConfig, FederationMiddleware},
3073+ fetch::object_id::ObjectId,
3074+ fetch::webfinger::{build_webfinger_response, extract_webfinger_name, Webfinger},
3075+ protocol::context::WithContext,
3076+ traits::{Actor, Object},
3077+ };
3078+ use axum::{
3079+ extract::{Path, Query},
3080+ headers::HeaderMap,
3081+ http::header::CONTENT_TYPE,
3082+ http::StatusCode,
3083+ response::{Html, IntoResponse, Json, Redirect, Response},
3084+ routing::{get, post},
3085+ Extension, Router,
3086+ };
3087+ use axum_macros::debug_handler;
3088+ use rand::{
3089+ distributions::{Alphanumeric, DistString},
3090+ thread_rng,
3091+ };
3092+ use serde::Deserialize;
3093+ use tera::{to_value, Context, Filter, Result as TeraResult, Tera, Value};
3094+ use tracing::log::info;
3095+ use url::Url;
3096+
3097+ use crate::database::Connection;
3098+ use crate::error::Error;
3099+ use crate::objects::{AcceptedActivities, DbUser, Ping, Pong, User};
3100+ use crate::util;
3101+
3102+ const PICOCSS: &'static str = include_str!("../pico.min.css");
3103+ const STYLESHEET: &'static str = include_str!("../main.css");
3104+ const LOGO: &'static str = include_str!("../logo.svg");
3105+
3106+ struct HandleFilter(String);
3107+
3108+ impl Filter for HandleFilter {
3109+ fn filter(
3110+ &self,
3111+ value: &Value,
3112+ _: &std::collections::HashMap<String, Value>,
3113+ ) -> TeraResult<Value> {
3114+ let url = Url::parse(value.as_str().unwrap()).unwrap();
3115+ Ok(to_value(util::handle(url, self.0.as_str()))?)
3116+ }
3117+ }
3118+
3119+ fn make_ctx() -> Context {
3120+ let mut ctx = Context::new();
3121+ ctx.insert("title", "ping-pong");
3122+ ctx.insert("picocss", &PICOCSS);
3123+ ctx.insert("stylesheet", &STYLESHEET);
3124+ ctx.insert("logo", &LOGO);
3125+ ctx
3126+ }
3127+
3128+ #[debug_handler]
3129+ async fn http_index(
3130+ data: Data<Connection>,
3131+ Extension(templates): Extension<Arc<Tera>>,
3132+ ) -> Result<Html<String>, Error> {
3133+ let mut ctx = make_ctx();
3134+ let mut users: Vec<(User, usize, usize)> = Vec::new();
3135+ for user in data.list_users() {
3136+ let json_user = user.0.into_json(&data).await?;
3137+ users.push((json_user, user.1.map_or(0, |pm| pm.len()), 0));
3138+ }
3139+ ctx.insert("users", &users);
3140+ let html = templates.render("index.html", &ctx)?;
3141+ Ok(Html(html))
3142+ }
3143+
3144+ #[debug_handler]
3145+ async fn http_get_user(
3146+ Path(handle): Path<String>,
3147+ data: Data<Connection>,
3148+ headers: HeaderMap,
3149+ Extension(templates): Extension<Arc<Tera>>,
3150+ ) -> Result<Response, Error> {
3151+ info!("looking up user: {}", handle);
3152+ let id = util::to_url(handle.as_str(), data.domain(), false);
3153+ info!("resolved user: {}", id);
3154+ let db_user = data.read_user(id.path());
3155+ let serve_html = || async {
3156+ let mut ctx = make_ctx();
3157+ match db_user {
3158+ Some(user) => {
3159+ let user = user.0.into_json(&data).await?;
3160+ ctx.insert("user", &user);
3161+ let html = templates.render("user.html", &ctx)?;
3162+ Ok((StatusCode::OK, Html(html)).into_response())
3163+ }
3164+ None => {
3165+ ctx.insert("error", format!("user {} does not exist", handle).as_str());
3166+ let html = templates.render("error.html", &ctx)?;
3167+ Ok((StatusCode::NOT_FOUND, Html(html)).into_response())
3168+ }
3169+ }
3170+ };
3171+ match headers.get(CONTENT_TYPE) {
3172+ Some(header_value) => {
3173+ println!("header: {}", header_value.to_str().unwrap());
3174+ panic!("oops");
3175+ }
3176+ None => serve_html().await,
3177+ }
3178+ }
3179+
3180+ #[debug_handler]
3181+ async fn http_post_user_inbox(
3182+ data: Data<Connection>,
3183+ activity_data: ActivityData,
3184+ ) -> impl IntoResponse {
3185+ info!("processing activity request: {:?}", activity_data);
3186+ receive_activity::<WithContext<AcceptedActivities>, DbUser, Connection>(activity_data, &data)
3187+ .await
3188+ }
3189+
3190+ #[derive(Deserialize)]
3191+ struct WebfingerQuery {
3192+ resource: String,
3193+ }
3194+
3195+ #[debug_handler]
3196+ async fn webfinger(
3197+ Query(query): Query<WebfingerQuery>,
3198+ data: Data<Connection>,
3199+ ) -> Result<Json<Webfinger>, Error> {
3200+ println!("calling?");
3201+ let name = extract_webfinger_name(&query.resource, &data)?;
3202+ let db_user = data.read_user(&name).unwrap();
3203+ Ok(Json(build_webfinger_response(query.resource, db_user.0.id())))
3204+ }
3205+
3206+ #[debug_handler]
3207+ async fn api_send_ping(
3208+ Path(handle): Path<String>,
3209+ data: Data<Connection>,
3210+ ) -> Result<Redirect, Error> {
3211+ let user_id = util::to_url(handle.as_str(), data.domain(), false);
3212+ let user_id = ObjectId::<DbUser>::parse(user_id.to_string().as_str())?;
3213+ let user = user_id.dereference(&data).await?;
3214+ let inbox_url = user.shared_inbox_or_inbox();
3215+ if util::is_local(inbox_url.clone(), data.domain()) {
3216+ // local ping
3217+ data.write_ping(
3218+ user,
3219+ Ping {
3220+ unique_id: Alphanumeric.sample_string(&mut rand::thread_rng(), 10),
3221+ actor: user_id, // todo
3222+ },
3223+ )
3224+ } else {
3225+ let inboxes = vec![inbox_url];
3226+ let ping = Ping {
3227+ actor: user_id,
3228+ unique_id: Alphanumeric.sample_string(&mut rand::thread_rng(), 10),
3229+ };
3230+ info!("sending remote ping: {:?}", ping);
3231+ send_activity(ping, &user, inboxes, &data).await?;
3232+ }
3233+ Ok(Redirect::to("/"))
3234+ }
3235+
3236+ pub async fn listen(cfg: &FederationConfig<Connection>) -> Result<(), Error> {
3237+ let hostname = cfg.domain();
3238+ let cfg = cfg.clone();
3239+ let mut tera = match Tera::new("templates/*") {
3240+ Ok(t) => t,
3241+ Err(e) => {
3242+ println!("Parsing error(s): {}", e);
3243+ ::std::process::exit(1);
3244+ }
3245+ };
3246+ tera.register_filter("handle", HandleFilter(cfg.domain().to_string()));
3247+ tera.autoescape_on(vec![".html"]);
3248+ let app = Router::new()
3249+ .route("/", get(http_index))
3250+ .route("/users/:user", get(http_get_user))
3251+ .route("/users/:user/inbox", post(http_post_user_inbox))
3252+ .route("/.well-known/webfinger", get(webfinger))
3253+ .route("/internal/ping/:user", post(api_send_ping))
3254+ .layer(FederationMiddleware::new(cfg.clone()))
3255+ .layer(Extension(Arc::new(tera)));
3256+
3257+ let addr = hostname
3258+ .to_socket_addrs()
3259+ .unwrap()
3260+ .next()
3261+ .expect("failed to lookup domain");
3262+ info!("listening @ {:?}", addr);
3263+ let server = axum::Server::bind(&addr).serve(app.into_make_service());
3264+ server.await.unwrap();
3265+ Ok(())
3266+ }
3267 diff --git a/templates/base.html b/templates/base.html
3268new file mode 100644
3269index 0000000..a3a4d88
3270--- /dev/null
3271+++ b/templates/base.html
3272 @@ -0,0 +1,30 @@
3273+ <!DOCTYPE html>
3274+ <html lang="en">
3275+ <head>
3276+ <meta charset="utf-8">
3277+ <meta name="viewport" content="width=device-width, initial-scale=1">
3278+ <title>
3279+ {% block title %}{{ title }}{% endblock %}
3280+ </title>
3281+ <style> {{ picocss | safe }} </style>
3282+ <style> {{ stylesheet | safe }} </style>
3283+ </head>
3284+ <body>
3285+ <script>0</script>
3286+ <main class="container">
3287+ <nav>
3288+ <ul>
3289+ <li>
3290+ <a href="/"><div class="logo">{{ logo | safe }}</div></a>
3291+ </li>
3292+ </ul>
3293+ <ul>
3294+ <li>
3295+ <b> User: root </b>
3296+ </li>
3297+ </ul>
3298+ </nav>
3299+ {% block content %}{% endblock %}
3300+ </main>
3301+ </body>
3302+ </html>
3303 diff --git a/templates/error.html b/templates/error.html
3304new file mode 100644
3305index 0000000..a0fff21
3306--- /dev/null
3307+++ b/templates/error.html
3308 @@ -0,0 +1,7 @@
3309+ {% extends "base.html" %}
3310+ {% block content %}
3311+ <section>
3312+ <h1> Error </h1>
3313+ <p> {{ error }} </p>
3314+ </section>
3315+ {% endblock %}
3316 diff --git a/templates/index.html b/templates/index.html
3317new file mode 100644
3318index 0000000..0d62dc4
3319--- /dev/null
3320+++ b/templates/index.html
3321 @@ -0,0 +1,36 @@
3322+ {% extends "base.html" %}
3323+ {% block content %}
3324+ <section>
3325+ <article>
3326+ <header>
3327+ <h1>Ping-Pong</h1>
3328+ <i> The World's Least Interesting Social Media Website </i>
3329+ </header>
3330+ <h2>Users</h2>
3331+ <table>
3332+ <thead>
3333+ <th>Name</th>
3334+ <th>Pings</th>
3335+ <th>Pongs</th>
3336+ <th>Activity</th>
3337+ </thead>
3338+ <tbody>
3339+ {% for user in users %}
3340+ <tr>
3341+ <td>
3342+ <a href="/users/{{ user.0.id | handle }}">{{ user.0.id | handle }}</a>
3343+ </td>
3344+ <td>{{user.1}}</td>
3345+ <td>{{user.2}}</td>
3346+ <td>
3347+ <form action="/internal/ping/{{ user.0.id | handle }}" method="POST">
3348+ <button>Ping</button>
3349+ </form>
3350+ </td>
3351+ </tr>
3352+ {% endfor %}
3353+ </tbody>
3354+ </table>
3355+ </article>
3356+ </section>
3357+ {% endblock %}
3358 diff --git a/templates/user.html b/templates/user.html
3359new file mode 100644
3360index 0000000..8d06f87
3361--- /dev/null
3362+++ b/templates/user.html
3363 @@ -0,0 +1,21 @@
3364+ {% extends "base.html" %}
3365+ {% block content %}
3366+ <section>
3367+ <article>
3368+ <header>
3369+ <h1>{{ user.id | handle }}</h1>
3370+ <form action="/internal/ping/{{user.id | handle}}" method="POST">
3371+ <button>Ping</button>
3372+ </form>
3373+ </header>
3374+ <table>
3375+ <thead>
3376+ <th>Sender</th>
3377+ <th>CreatedAt</th>
3378+ <th>RespondedAt</th>
3379+ <th>Pong</th>
3380+ </thead>
3381+ </table>
3382+ </article>
3383+ </section>
3384+ {% endblock %}