diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 5346ceb..5723180 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1,2 @@ liberapay: spike +custom: ['https://www.buymeacoffee.com/spikecodes'] diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 12ff5c5..03d38d1 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,7 +1,7 @@ --- name: 🐛 Bug report about: Create a report to help us improve -title: '' +title: '🐛 Bug Report: ' labels: bug assignees: '' @@ -12,7 +12,7 @@ assignees: '' A clear and concise description of what the bug is. --> -## To reproduce +## Steps to reproduce the bug -## Expected behavior +## What's the expected behavior? -## Additional context +## Additional context / screenshot diff --git a/.github/ISSUE_TEMPLATE/feature_parity.md b/.github/ISSUE_TEMPLATE/feature_parity.md index 95bc729..22b9bd8 100644 --- a/.github/ISSUE_TEMPLATE/feature_parity.md +++ b/.github/ISSUE_TEMPLATE/feature_parity.md @@ -1,7 +1,7 @@ --- name: ✨ Feature parity about: Suggest implementing a feature into Libreddit that is found in Reddit.com -title: '' +title: '✨ Feature parity: ' labels: feature parity assignees: '' @@ -12,7 +12,7 @@ assignees: '' A clear and concise description of what the feature is. --> -## Describe the implementation into Libreddit +## Describe how this could be implemented into Libreddit @@ -22,7 +22,7 @@ assignees: '' A clear and concise description of any alternative solutions or features you've considered. --> -## Additional context +## Additional context / screenshot diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 5d21fed..e9e6d31 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,7 +1,7 @@ --- name: 💡 Feature request about: Suggest a feature for Libreddit that is not found in Reddit -title: '' +title: '💡 Feature request: ' labels: enhancement assignees: '' @@ -12,7 +12,7 @@ assignees: '' A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] --> -## Describe the solution you'd like +## Describe the feature you would like to be implemented @@ -22,7 +22,7 @@ assignees: '' A clear and concise description of any alternative solutions or features you've considered. --> -## Additional context +## Additional context / screenshot diff --git a/.github/workflows/docker-arm.yml b/.github/workflows/docker-arm.yml index 941dce2..6e34e79 100644 --- a/.github/workflows/docker-arm.yml +++ b/.github/workflows/docker-arm.yml @@ -34,3 +34,5 @@ jobs: platforms: linux/arm64 push: true tags: spikecodes/libreddit:arm + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/docker-armv7.yml b/.github/workflows/docker-armv7.yml index 3229418..7c51db2 100644 --- a/.github/workflows/docker-armv7.yml +++ b/.github/workflows/docker-armv7.yml @@ -37,3 +37,5 @@ jobs: platforms: linux/arm/v7 push: true tags: spikecodes/libreddit:armv7 + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 7fe2374..ed1bf73 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -34,4 +34,5 @@ jobs: platforms: linux/amd64 push: true tags: spikecodes/libreddit:latest - + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/Cargo.lock b/Cargo.lock index 68df57b..2c5da4d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "askama" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d8f355701c672c2ba3d718acbd213f740beea577cc4eae66accdffe15be1882" +checksum = "fb98f10f371286b177db5eeb9a6e5396609555686a35e1d4f7b9a9c6d8af0139" dependencies = [ "askama_derive", "askama_escape", @@ -24,9 +24,9 @@ dependencies = [ [[package]] name = "askama_derive" -version = "0.11.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84704cab5b7ae0fd3a9f78ee5eb7b27f3749df445f04623db6633459ae283267" +checksum = "87bf87e6e8b47264efa9bde63d6225c6276a52e05e91bf37eaa8afd0032d6b71" dependencies = [ "askama_shared", "proc-macro2", @@ -35,32 +35,25 @@ dependencies = [ [[package]] name = "askama_escape" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1bb320f97e6edf9f756bf015900038e43c7700e059688e5724a928c8f3b8d5" +checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" [[package]] name = "askama_shared" -version = "0.12.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dae03eebba55a2697a376e58b573a29fe36893157173ac8df312ad85f3c0e012" +checksum = "bf722b94118a07fcbc6640190f247334027685d4e218b794dbfe17c32bf38ed0" dependencies = [ "askama_escape", + "mime", + "mime_guess", "nom", "proc-macro2", "quote", "syn", ] -[[package]] -name = "async-mutex" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" -dependencies = [ - "event-listener", -] - [[package]] name = "async-recursion" version = "1.0.0" @@ -72,21 +65,11 @@ dependencies = [ "syn", ] -[[package]] -name = "async-rwlock" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261803dcc39ba9e72760ba6e16d0199b1eef9fc44e81bffabbebb9f5aea3906c" -dependencies = [ - "async-mutex", - "event-listener", -] - [[package]] name = "async-trait" -version = "0.1.52" +version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" +checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600" dependencies = [ "proc-macro2", "quote", @@ -94,10 +77,16 @@ dependencies = [ ] [[package]] -name = "autocfg" -version = "1.0.1" +name = "async_once" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "2ce4f10ea3abcd6617873bae9f91d1c5332b4a778bd9ce34d0cd517474c1de82" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" @@ -112,10 +101,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "bumpalo" -version = "3.8.0" +name = "block-buffer" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "bytes" @@ -125,25 +123,27 @@ checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" [[package]] name = "cached" -version = "0.26.2" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2bc2fd249a24a9cdd4276f3a3e0461713271ab63b0e9e656e200e8e21c8c927" +checksum = "aadf76ddea74bab35ebeb8f1eb115b9bc04eaee42d8acc0d5f477dee6b176c9a" dependencies = [ - "async-mutex", - "async-rwlock", "async-trait", + "async_once", "cached_proc_macro", "cached_proc_macro_types", "futures", - "hashbrown", + "hashbrown 0.12.1", + "lazy_static", "once_cell", + "thiserror", + "tokio", ] [[package]] name = "cached_proc_macro" -version = "0.7.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3531903b39df48a378a7ed515baee7c1fff32488489c7d0725eb1749b22a91" +checksum = "bce0f37f9b77c6b93cdf3f060c89adca303d2ab052cacb3c3d1ab543e8cecd2f" dependencies = [ "cached_proc_macro_types", "darling", @@ -159,9 +159,9 @@ checksum = "3a4f925191b4367301851c6d99b09890311d74b0d43f274c0b34c86d308a3663" [[package]] name = "cc" -version = "1.0.72" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" [[package]] name = "cfg-if" @@ -171,16 +171,25 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "3.0.5" +version = "3.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f34b09b9ee8c7c7b400fe2f8df39cafc9538b03d6ba7f4ae13e4cb90bfbb7d" +checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b" dependencies = [ "bitflags", + "clap_lex", "indexmap", - "os_str_bytes", "textwrap", ] +[[package]] +name = "clap_lex" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "cookie" version = "0.16.0" @@ -193,9 +202,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ "core-foundation-sys", "libc", @@ -208,10 +217,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] -name = "darling" -version = "0.13.1" +name = "cpufeatures" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4" +checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +dependencies = [ + "libc", +] + +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" dependencies = [ "darling_core", "darling_macro", @@ -219,9 +237,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.13.1" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" dependencies = [ "fnv", "ident_case", @@ -233,9 +251,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.13.1" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", "quote", @@ -243,16 +261,19 @@ dependencies = [ ] [[package]] -name = "event-listener" -version = "2.5.1" +name = "digest" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] [[package]] name = "fastrand" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "779d043b6a0b90cc4c0ed7ee380a6504394cee7efd7db050e3774eee387324b2" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" dependencies = [ "instant", ] @@ -275,9 +296,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" dependencies = [ "futures-channel", "futures-core", @@ -290,9 +311,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" dependencies = [ "futures-core", "futures-sink", @@ -300,15 +321,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" [[package]] name = "futures-executor" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" dependencies = [ "futures-core", "futures-task", @@ -317,9 +338,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" [[package]] name = "futures-lite" @@ -338,9 +359,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ "proc-macro2", "quote", @@ -349,21 +370,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" [[package]] name = "futures-task" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" [[package]] name = "futures-util" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ "futures-channel", "futures-core", @@ -378,10 +399,20 @@ dependencies = [ ] [[package]] -name = "h2" -version = "0.3.9" +name = "generic-array" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f072413d126e57991455e0a922b31e4c8ba7c2ffbebf6b78b4f8521397d65cd" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "h2" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" dependencies = [ "bytes", "fnv", @@ -402,6 +433,12 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +[[package]] +name = "hashbrown" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -413,20 +450,20 @@ dependencies = [ [[package]] name = "http" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +checksum = "ff8670570af52249509a86f5e3e18a08c60b177071826898fde8997cf5f6bfbb" dependencies = [ "bytes", "fnv", - "itoa 1.0.1", + "itoa", ] [[package]] name = "http-body" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", "http", @@ -435,9 +472,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.5.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" +checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" [[package]] name = "httpdate" @@ -447,9 +484,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.14.16" +version = "0.14.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" +checksum = "42dc3c131584288d375f2d07f822b0cb012d8c6fb899a5b9fdb3cb7eb9b6004f" dependencies = [ "bytes", "futures-channel", @@ -460,7 +497,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 0.4.8", + "itoa", "pin-project-lite", "socket2", "tokio", @@ -503,12 +540,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.7.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.11.2", ] [[package]] @@ -522,21 +559,15 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.8" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" [[package]] name = "js-sys" -version = "0.3.55" +version = "0.3.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" dependencies = [ "wasm-bindgen", ] @@ -549,13 +580,13 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.112" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" [[package]] name = "libreddit" -version = "0.21.7" +version = "0.22.9" dependencies = [ "askama", "async-recursion", @@ -565,8 +596,10 @@ dependencies = [ "futures-lite", "hyper", "hyper-rustls", + "percent-encoding", "regex", "route-recognizer", + "rust-embed", "serde", "serde_json", "time", @@ -576,18 +609,19 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" dependencies = [ + "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] @@ -600,9 +634,25 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] [[package]] name = "minimal-lexical" @@ -612,44 +662,24 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "mio" -version = "0.7.14" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" dependencies = [ "libc", "log", - "miow", - "ntapi", - "winapi", -] - -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", + "wasi", + "windows-sys", ] [[package]] name = "nom" -version = "7.1.0" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" dependencies = [ "memchr", "minimal-lexical", - "version_check", -] - -[[package]] -name = "ntapi" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" -dependencies = [ - "winapi", ] [[package]] @@ -663,25 +693,37 @@ dependencies = [ ] [[package]] -name = "once_cell" -version = "1.9.0" +name = "num_threads" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + +[[package]] +name = "once_cell" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl-probe" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "os_str_bytes" -version = "6.0.0" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" -dependencies = [ - "memchr", -] +checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" [[package]] name = "parking" @@ -691,27 +733,25 @@ checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" [[package]] name = "parking_lot" -version = "0.11.2" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" dependencies = [ - "instant", "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" -version = "0.8.5" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" dependencies = [ "cfg-if", - "instant", "libc", "redox_syscall", "smallvec", - "winapi", + "windows-sys", ] [[package]] @@ -722,9 +762,9 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pin-project-lite" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -734,36 +774,36 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.14" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" dependencies = [ "proc-macro2", ] [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.5.4" +version = "1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" dependencies = [ "aho-corasick", "memchr", @@ -772,9 +812,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" [[package]] name = "ring" @@ -798,10 +838,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746" [[package]] -name = "rustls" -version = "0.20.2" +name = "rust-embed" +version = "6.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d37e5e2290f3e040b594b1a9e04377c2c671f1a1cfd9bfdef82106ac1c113f84" +checksum = "9a17e5ac65b318f397182ae94e532da0ba56b88dd1200b774715d36c4943b1c3" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "6.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94e763e24ba2bf0c72bc6be883f967f794a019fafd1b86ba1daff9c91a7edd30" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "7.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756feca3afcbb1487a1d01f4ecd94cf8ec98ea074c55a69e7136d29fb6166029" +dependencies = [ + "sha2", + "walkdir", +] + +[[package]] +name = "rustls" +version = "0.20.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" dependencies = [ "log", "ring", @@ -811,9 +885,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca9ebdfa27d3fc180e42879037b5338ab1c040c06affd00d8338598e7800943" +checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" dependencies = [ "openssl-probe", "rustls-pemfile", @@ -823,27 +897,36 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "0.2.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9" dependencies = [ "base64", ] [[package]] name = "ryu" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] [[package]] name = "schannel" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" dependencies = [ "lazy_static", - "winapi", + "windows-sys", ] [[package]] @@ -864,9 +947,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.4.2" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" dependencies = [ "bitflags", "core-foundation", @@ -877,9 +960,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.4.2" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" dependencies = [ "core-foundation-sys", "libc", @@ -887,18 +970,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.133" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.133" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ "proc-macro2", "quote", @@ -907,15 +990,28 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.74" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2bb9cd061c5865d345bb02ca49fcef1391741b672b54a0bf7b679badec3142" +checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" dependencies = [ - "itoa 1.0.1", + "itoa", "ryu", "serde", ] +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer", + "cfg-if", + "cpufeatures", + "digest", + "opaque-debug", +] + [[package]] name = "signal-hook-registry" version = "1.4.0" @@ -927,21 +1023,21 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" +checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" [[package]] name = "smallvec" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "socket2" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" dependencies = [ "libc", "winapi", @@ -961,43 +1057,64 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.84" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecb2e6da8ee5eb9a61068762a32fa9619cc591ceb055b3687f4cd4051ec2e06b" +checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] name = "textwrap" -version = "0.14.2" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + +[[package]] +name = "thiserror" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "time" -version = "0.3.5" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41effe7cfa8af36f439fac33861b66b049edc6f9a32331e2312660529c1c24ad" +checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd" dependencies = [ - "itoa 0.4.8", + "itoa", "libc", + "num_threads", "time-macros", ] [[package]] name = "time-macros" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25eb0ca3468fc0acc11828786797f6ef9aa1555e4a211a60d64cc8e4d1be47d6" +checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" [[package]] name = "tinyvec" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] @@ -1010,9 +1127,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.15.0" +version = "1.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" +checksum = "4903bf0427cf68dddd5aa6a93220756f8be0c34fcfa9f5e6191e103e15a31395" dependencies = [ "bytes", "libc", @@ -1023,6 +1140,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", + "socket2", "tokio-macros", "winapi", ] @@ -1040,9 +1158,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.23.2" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" dependencies = [ "rustls", "tokio", @@ -1051,16 +1169,16 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.6.9" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" +checksum = "f988a1a1adc2fb21f9c12aa96441da33a1728193ae0b95d2be22dbd17fcb4e5c" dependencies = [ "bytes", "futures-core", "futures-sink", - "log", "pin-project-lite", "tokio", + "tracing", ] [[package]] @@ -1071,20 +1189,32 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.29" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" dependencies = [ "cfg-if", "pin-project-lite", + "tracing-attributes", "tracing-core", ] [[package]] -name = "tracing-core" +name = "tracing-attributes" version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" dependencies = [ "lazy_static", ] @@ -1096,10 +1226,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] -name = "unicode-bidi" -version = "0.3.7" +name = "typenum" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-ident" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" [[package]] name = "unicode-normalization" @@ -1110,12 +1261,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - [[package]] name = "untrusted" version = "0.7.1" @@ -1146,6 +1291,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + [[package]] name = "want" version = "0.3.0" @@ -1157,10 +1313,16 @@ dependencies = [ ] [[package]] -name = "wasm-bindgen" -version = "0.2.78" +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1168,9 +1330,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.78" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" dependencies = [ "bumpalo", "lazy_static", @@ -1183,9 +1345,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.78" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" +checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1193,9 +1355,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.78" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" dependencies = [ "proc-macro2", "quote", @@ -1206,15 +1368,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.78" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" +checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" [[package]] name = "web-sys" -version = "0.3.55" +version = "0.3.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" +checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" dependencies = [ "js-sys", "wasm-bindgen", @@ -1246,8 +1408,60 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" diff --git a/Cargo.toml b/Cargo.toml index 76fe295..484962c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,23 +3,25 @@ name = "libreddit" description = " Alternative private front-end to Reddit" license = "AGPL-3.0" repository = "https://github.com/spikecodes/libreddit" -version = "0.21.7" +version = "0.22.9" authors = ["spikecodes <19519553+spikecodes@users.noreply.github.com>"] edition = "2021" [dependencies] -askama = { version = "0.11.0", default-features = false } +askama = { version = "0.11.1", default-features = false } async-recursion = "1.0.0" -cached = "0.26.2" -clap = { version = "3.0.5", default-features = false, features = ["std"] } -regex = "1.5.4" -serde = { version = "1.0.133", features = ["derive"] } +cached = "0.34.0" +clap = { version = "3.1.18", default-features = false, features = ["std"] } +regex = "1.5.6" +serde = { version = "1.0.137", features = ["derive"] } cookie = "0.16.0" futures-lite = "1.12.0" -hyper = { version = "0.14.16", features = ["full"] } +hyper = { version = "0.14.19", features = ["full"] } hyper-rustls = "0.23.0" +percent-encoding = "2.1.0" route-recognizer = "0.3.1" -serde_json = "1.0.74" -tokio = { version = "1.15.0", features = ["full"] } -time = "0.3.5" +serde_json = "1.0.81" +tokio = { version = "1.18.2", features = ["full"] } +time = "0.3.9" url = "2.2.2" +rust-embed = "6.4.0" diff --git a/FUNDING.yml b/FUNDING.yml deleted file mode 100644 index 49fc1ba..0000000 --- a/FUNDING.yml +++ /dev/null @@ -1,12 +0,0 @@ -# These are supported funding model platforms - -github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] -patreon: # Replace with a single Patreon username -open_collective: # Replace with a single Open Collective username -ko_fi: # Replace with a single Ko-fi username -tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel -community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry -liberapay: spike -issuehunt: # Replace with a single IssueHunt username -otechie: # Replace with a single Otechie username -custom: ['https://www.buymeacoffee.com/spikecodes'] diff --git a/README.md b/README.md index fa2c5ff..5a941f3 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ **10 second pitch:** Libreddit is a portmanteau of "libre" (meaning freedom) and "Reddit". It is a private front-end like [Invidious](https://github.com/iv-org/invidious) but for Reddit. Browse the coldest takes of [r/unpopularopinion](https://libreddit.spike.codes/r/unpopularopinion) without being [tracked](#reddit). -- 🚀 Fast: written in Rust for blazing fast speeds and memory safety +- 🚀 Fast: written in Rust for blazing-fast speeds and memory safety - ☁️ Light: no JavaScript, no ads, no tracking, no bloat - 🕵 Private: all requests are proxied through the server, including media - 🔒 Secure: strong [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) prevents browser requests to Reddit @@ -17,11 +17,13 @@ I appreciate any donations! Your support allows me to continue developing Libreddit. -Buy Me A Coffee +Buy Me A Coffee +Donate using Liberapay -**Bitcoin:** [bc1qwyxjnafpu3gypcpgs025cw9wa7ryudtecmwa6y](bitcoin:bc1qwyxjnafpu3gypcpgs025cw9wa7ryudtecmwa6y) -**Monero:** [45FJrEuFPtG2o7QZz2Nps77TbHD4sPqxViwbdyV9A6ktfHiWs47UngG5zXPcLoDXAc8taeuBgeNjfeprwgeXYXhN3C9tVSR](monero:45FJrEuFPtG2o7QZz2Nps77TbHD4sPqxViwbdyV9A6ktfHiWs47UngG5zXPcLoDXAc8taeuBgeNjfeprwgeXYXhN3C9tVSR) +**Bitcoin:** `bc1qwyxjnafpu3gypcpgs025cw9wa7ryudtecmwa6y` + +**Monero:** `45FJrEuFPtG2o7QZz2Nps77TbHD4sPqxViwbdyV9A6ktfHiWs47UngG5zXPcLoDXAc8taeuBgeNjfeprwgeXYXhN3C9tVSR` --- @@ -29,49 +31,70 @@ I appreciate any donations! Your support allows me to continue developing Libred Feel free to [open an issue](https://github.com/spikecodes/libreddit/issues/new) to have your [selfhosted instance](#deployment) listed here! +🔗 **Want to automatically redirect Reddit links to Libreddit? Use [LibRedirect](https://github.com/libredirect/libredirect) or [Privacy Redirect](https://github.com/SimonBrazell/privacy-redirect)!** + | Website | Country | Cloudflare | |-|-|-| | [libredd.it](https://libredd.it) (official) | 🇺🇸 US | | | [libreddit.spike.codes](https://libreddit.spike.codes) (official) | 🇺🇸 US | | | [libreddit.dothq.co](https://libreddit.dothq.co) | 🇩🇪 DE | ✅ | | [libreddit.kavin.rocks](https://libreddit.kavin.rocks) | 🇮🇳 IN | | -| [libreddit.40two.app](https://libreddit.40two.app) | 🇳🇱 NL | | | [reddit.invak.id](https://reddit.invak.id) | 🇧🇬 BG | | | [reddit.phii.me](https://reddit.phii.me) | 🇺🇸 US | | | [lr.riverside.rocks](https://lr.riverside.rocks) | 🇺🇸 US | | -| [libreddit.silkky.cloud](https://libreddit.silkky.cloud) | 🇫🇮 FI | ✅ | +| [libreddit.strongthany.cc](https://libreddit.strongthany.cc) | 🇺🇸 US | | | [libreddit.database.red](https://libreddit.database.red) | 🇺🇸 US | ✅ | -| [libreddit.exonip.de](https://libreddit.exonip.de) | 🇩🇪 DE | | +| [libreddit.privacy.com.de](https://libreddit.privacy.com.de) | 🇩🇪 DE | | | [libreddit.domain.glass](https://libreddit.domain.glass) | 🇺🇸 US | ✅ | | [libreddit.sugoma.tk](https://libreddit.sugoma.tk) | 🇺🇸 US | | | [libreddit.jamiethalacker.dev](https://libreddit.jamiethalacker.dev) | 🇺🇸 US | ✅ | | [reddit.artemislena.eu](https://reddit.artemislena.eu) | 🇩🇪 DE | | | [r.nf](https://r.nf) | 🇩🇪 DE | ✅ | -| [libreddit.awesomehub.io](https://libreddit.awesomehub.io) | 🇫🇮 FI | | | [libreddit.some-things.org](https://libreddit.some-things.org) | 🇨🇭 CH | | | [reddit.stuehieyr.com](https://reddit.stuehieyr.com) | 🇩🇪 DE | | | [lr.mint.lgbt](https://lr.mint.lgbt) | 🇨🇦 CA | | -| [libreddit.alefvanoon.xyz](https://libreddit.alefvanoon.xyz) | 🇺🇸 US | ✅ | | [libreddit.igna.rocks](https://libreddit.igna.rocks) | 🇺🇸 US | | | [libreddit.autarkic.org](https://libreddit.autarkic.org) | 🇺🇸 US | | | [libreddit.flux.industries](https://libreddit.flux.industries) | 🇩🇪 DE | ✅ | -| [libreddit.drivet.xyz](https://libreddit.drivet.xyz) | 🇫🇮 FI | ✅ | +| [libreddit.drivet.xyz](https://libreddit.drivet.xyz) | 🇵🇱 PL | | | [lr.oversold.host](https://lr.oversold.host) | 🇱🇺 LU | | | [libreddit.de](https://libreddit.de) | 🇩🇪 DE | | | [libreddit.pussthecat.org](https://libreddit.pussthecat.org) | 🇩🇪 DE | | | [libreddit.mutahar.rocks](https://libreddit.mutahar.rocks) | 🇫🇷 FR | | | [libreddit.northboot.xyz](https://libreddit.northboot.xyz) | 🇩🇪 DE | | -| [leddit.xyz](https://www.leddit.xyz) | 🇺🇸 US | | +| [leddit.xyz](https://leddit.xyz) | 🇺🇸 US | | +| [de.leddit.xyz](https://de.leddit.xyz) | 🇩🇪 DE | | | [lr.cowfee.moe](https://lr.cowfee.moe) | 🇺🇸 US | | | [libreddit.hu](https://libreddit.hu) | 🇫🇮 FI | ✅ | | [libreddit.totaldarkness.net](https://libreddit.totaldarkness.net) | 🇨🇦 CA | | -| [libreddit.esmailelbob.xyz](https://libreddit.esmailelbob.xyz) | 🇪🇬 EG | | +| [libreddit.esmailelbob.xyz](https://libreddit.esmailelbob.xyz) | 🇨🇦 CA | | +| [lr.vern.cc](https://lr.vern.cc) | 🇨🇦 CA | | | [libreddit.nl](https://libreddit.nl) | 🇳🇱 NL | | | [lr.stilic.ml](https://lr.stilic.ml) | 🇫🇷 FR | ✅ | | [reddi.tk](https://reddi.tk) | 🇺🇸 US | ✅ | | [libreddit.bus-hit.me](https://libreddit.bus-hit.me) | 🇨🇦 CA | | -| [lr.rfl890.cf](https://lr.rfl890.cf) | 🇺🇸 US | | | [libreddit.datatunnel.xyz](https://libreddit.datatunnel.xyz) | 🇫🇮 FI | | +| [libreddit.crewz.me](https://libreddit.crewz.me) | 🇳🇱 NL | ✅ | +| [r.walkx.org](https://r.walkx.org) | 🇳🇱 NL | ✅ | +| [libreddit.kylrth.com](https://libreddit.kylrth.com) | 🇨🇦 CA | | +| [libreddit.yonalee.eu](https://libreddit.yonalee.eu) | 🇱🇺 LU | ✅ | +| [libreddit.winscloud.net](https://libreddit.winscloud.net) | 🇹🇭 TH | ✅ | +| [libreddit.tiekoetter.com](https://libreddit.tiekoetter.com) | 🇩🇪 DE | | +| [reddit.rtrace.io](https://reddit.rtrace.io) | 🇩🇪 DE | | +| [libreddit.lunar.icu](https://libreddit.lunar.icu) | 🇩🇪 DE | ✅ | +| [libreddit.privacydev.net](https://libreddit.privacydev.net) | 🇺🇸 US | | +| [libreddit.notyourcomputer.net](https://libreddit.notyourcomputer.net) | 🇺🇸 US | | +| [r.ahwx.org](https://r.ahwx.org) | 🇳🇱 NL | ✅ | +| [bob.fr.to](https://bob.fr.to) | 🇺🇸 US | | +| [reddit.beparanoid.de](https://reddit.beparanoid.de) | 🇨🇭 CH | | +| [libreddit.dcs0.hu](https://libreddit.dcs0.hu) | 🇭🇺 HU | | +| [reddit.dr460nf1r3.org](https://reddit.dr460nf1r3.org) | 🇩🇪 DE | ✅ | +| [rd.jae.su](https://rd.jae.su) | 🇫🇮 FI | | +| [libreddit.mha.fi](https://libreddit.mha.fi) | 🇫🇮 FI | | +| [libreddit.foss.wtf](https://libreddit.foss.wtf) | 🇩🇪 DE | | +| [libreddit.encrypted-data.xyz](https://libreddit.encrypted-data.xyz)| 🇫🇷 FR | ✅ | +| [libreddit.eu.org](https://libreddit.eu.org)| 🇮🇪 IE | ✅ | +| [l.opnxng.com](https://l.opnxng.com)| 🇸🇬 SG | | | [spjmllawtheisznfs7uryhxumin26ssv2draj7oope3ok3wuhy43eoyd.onion](http://spjmllawtheisznfs7uryhxumin26ssv2draj7oope3ok3wuhy43eoyd.onion) | 🇮🇳 IN | | | [fwhhsbrbltmrct5hshrnqlqygqvcgmnek3cnka55zj4y7nuus5muwyyd.onion](http://fwhhsbrbltmrct5hshrnqlqygqvcgmnek3cnka55zj4y7nuus5muwyyd.onion) | 🇩🇪 DE | | | [kphht2jcflojtqte4b4kyx7p2ahagv4debjj32nre67dxz7y57seqwyd.onion](http://kphht2jcflojtqte4b4kyx7p2ahagv4debjj32nre67dxz7y57seqwyd.onion) | 🇳🇱 NL | | @@ -82,9 +105,14 @@ Feel free to [open an issue](https://github.com/spikecodes/libreddit/issues/new) | [ledditqo2mxfvlgobxnlhrkq4dh34jss6evfkdkb2thlvy6dn4f4gpyd.onion](http://ledditqo2mxfvlgobxnlhrkq4dh34jss6evfkdkb2thlvy6dn4f4gpyd.onion) | 🇺🇸 US | | | [libredoxhxwnmsb6dvzzd35hmgzmawsq5i764es7witwhddvpc2razid.onion](http://libredoxhxwnmsb6dvzzd35hmgzmawsq5i764es7witwhddvpc2razid.onion) | 🇺🇸 US | | | [libreddit.2syis2nnyytz6jnusnjurva4swlaizlnleiks5mjp46phuwjbdjqwgqd.onion](http://libreddit.2syis2nnyytz6jnusnjurva4swlaizlnleiks5mjp46phuwjbdjqwgqd.onion) | 🇪🇬 EG | | - - -A checkmark in the "Cloudflare" category here refers to the use of the reverse proxy, [Cloudflare](https://cloudflare). The checkmark will not be listed for a site which uses Cloudflare DNS but rather the proxying service which grants Cloudflare the ability to monitor traffic to the website. +| [ol5begilptoou34emq2sshf3may3hlblvipdjtybbovpb7c7zodxmtqd.onion](http://ol5begilptoou34emq2sshf3may3hlblvipdjtybbovpb7c7zodxmtqd.onion) | 🇩🇪 DE | | +| [lbrdtjaj7567ptdd4rv74lv27qhxfkraabnyphgcvptl64ijx2tijwid.onion](http://lbrdtjaj7567ptdd4rv74lv27qhxfkraabnyphgcvptl64ijx2tijwid.onion) | 🇨🇦 CA | | +| [libreddit.lqs5fjmajyp7rvp4qvyubwofzi6d4imua7vs237rkc4m5qogitqwrgyd.onion](http://libreddit.lqs5fjmajyp7rvp4qvyubwofzi6d4imua7vs237rkc4m5qogitqwrgyd.onion) | 🇨🇦 CA | | +| [reddit.prnoid54e44a4bduq5due64jkk7wcnkxcp5kv3juncm7veptjcqudgyd.onion](http://reddit.prnoid54e44a4bduq5due64jkk7wcnkxcp5kv3juncm7veptjcqudgyd.onion) | 🇨🇭 CH | | +| [inz6tbezfwzexva6dize4cqraj2tjdhygxabmcgysccesvw2pybzhbyd.onion](http://inz6tbezfwzexva6dize4cqraj2tjdhygxabmcgysccesvw2pybzhbyd.onion) | 🇫🇮 FI | | +| [libreddit.micohauwkjbyw5meacrb4ipicwvwg4xtzl7y7viv53kig2mdcsvwkyyd.onion](http://libreddit.micohauwkjbyw5meacrb4ipicwvwg4xtzl7y7viv53kig2mdcsvwkyyd.onion/)| 🇫🇮 FI | | +| [lr.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion](http://lr.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion/) | 🇨🇦 CA | | +A checkmark in the "Cloudflare" category here refers to the use of the reverse proxy, [Cloudflare](https://cloudflare.com). The checkmark will not be listed for a site that uses Cloudflare DNS but rather the proxying service which grants Cloudflare the ability to monitor traffic to the website. --- @@ -147,7 +175,7 @@ Results from Google Lighthouse ([Libreddit Report](https://lighthouse-dot-webdot - The requested URL - Search terms -**Location:** The same privacy policy goes on to describe location data may be collected through the use of: +**Location:** The same privacy policy goes on to describe that location data may be collected through the use of: - GPS (consensual) - Bluetooth (consensual) - Content associated with a location (consensual) @@ -171,7 +199,7 @@ For transparency, I hope to describe all the ways Libreddit handles user privacy **Cookies:** Libreddit uses optional cookies to store any configured settings in [the settings menu](https://libreddit.spike.codes/settings). These are not cross-site cookies and the cookies hold no personal data. -**Hosting:** The official instances are hosted on [Replit](https://replit.com/) which monitors usage to prevent abuse. I can understand if this invalidates certain users' threat models and therefore, selfhosting, using unofficial instances and browsing through Tor are welcomed. +**Hosting:** The official instances are hosted on [Replit](https://replit.com/) which monitors usage to prevent abuse. I can understand if this invalidates certain users' threat models and therefore, self-hosting, using unofficial instances, and browsing through Tor are welcomed. --- @@ -243,8 +271,8 @@ Assign a default value for each setting by passing environment variables to Libr | `FRONT_PAGE` | `["default", "popular", "all"]` | `default` | | `LAYOUT` | `["card", "clean", "compact"]` | `card` | | `WIDE` | `["on", "off"]` | `off` | -| `COMMENT_SORT` | `["hot", "new", "top", "rising", "controversial"]` | `hot` | -| `POST_SORT` | `["confidence", "top", "new", "controversial", "old"]` | `confidence` | +| `POST_SORT` | `["hot", "new", "top", "rising", "controversial"]` | `hot` | +| `COMMENT_SORT` | `["confidence", "top", "new", "controversial", "old"]` | `confidence` | | `SHOW_NSFW` | `["on", "off"]` | `off` | | `USE_HLS` | `["on", "off"]` | `off` | | `HIDE_HLS_NOTIFICATION` | `["on", "off"]` | `off` | @@ -262,7 +290,7 @@ LIBREDDIT_DEFAULT_WIDE=on LIBREDDIT_DEFAULT_THEME=dark libreddit -r ## Proxying using NGINX -**NOTE** If you're [proxying Libreddit through a NGINX Reverse Proxy](https://github.com/spikecodes/libreddit/issues/122#issuecomment-782226853), add +**NOTE** If you're [proxying Libreddit through an NGINX Reverse Proxy](https://github.com/spikecodes/libreddit/issues/122#issuecomment-782226853), add ```nginx proxy_http_version 1.1; ``` diff --git a/contrib/libreddit.conf b/contrib/libreddit.conf index 18b8193..dd91e3b 100644 --- a/contrib/libreddit.conf +++ b/contrib/libreddit.conf @@ -1,2 +1,2 @@ -ADDRESS=localhost +ADDRESS=0.0.0.0 PORT=12345 diff --git a/contrib/libreddit.service b/contrib/libreddit.service index b6e6fef..8ed5da7 100644 --- a/contrib/libreddit.service +++ b/contrib/libreddit.service @@ -11,5 +11,27 @@ Environment=PORT=8080 EnvironmentFile=-/etc/libreddit.conf ExecStart=/usr/bin/libreddit -a ${ADDRESS} -p ${PORT} +# Hardening +DeviceAllow= +LockPersonality=yes +MemoryDenyWriteExecute=yes +PrivateDevices=yes +ProcSubset=pid +ProtectClock=yes +ProtectControlGroups=yes +ProtectHome=yes +ProtectHostname=yes +ProtectKernelLogs=yes +ProtectKernelModules=yes +ProtectKernelTunables=yes +ProtectProc=invisible +RestrictAddressFamilies=AF_INET AF_INET6 +RestrictNamespaces=yes +RestrictRealtime=yes +RestrictSUIDSGID=yes +SystemCallArchitectures=native +SystemCallFilter=@system-service ~@privileged ~@resources +UMask=0077 + [Install] WantedBy=default.target diff --git a/src/client.rs b/src/client.rs index 864a6c6..da271dd 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,6 +1,7 @@ use cached::proc_macro::cached; use futures_lite::{future::Boxed, FutureExt}; use hyper::{body::Buf, client, Body, Request, Response, Uri}; +use percent_encoding::{percent_encode, CONTROLS}; use serde_json::Value; use std::result::Result; @@ -90,7 +91,7 @@ fn request(url: String, quarantine: bool) -> Boxed, String .headers() .get("Location") .map(|val| { - let new_url = val.to_str().unwrap_or_default(); + let new_url = percent_encode(val.as_bytes(), CONTROLS).to_string(); format!("{}{}raw_json=1", new_url, if new_url.contains('?') { "&" } else { "?" }) }) .unwrap_or_default() diff --git a/src/main.rs b/src/main.rs index 206d5cf..b6f7889 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,7 @@ mod user; mod utils; // Import Crates -use clap::{App as cli, Arg}; +use clap::{Arg, Command}; use futures_lite::FutureExt; use hyper::{header::HeaderValue, Body, Request, Response}; @@ -19,7 +19,7 @@ use hyper::{header::HeaderValue, Body, Request, Response}; mod client; use client::proxy; use server::RequestExt; -use utils::{error, redirect}; +use utils::{error, redirect, ThemeAssets}; mod server; @@ -85,9 +85,26 @@ async fn resource(body: &str, content_type: &str, cache: bool) -> Result Result, String> { + let mut res = include_str!("../static/style.css").to_string(); + for file in ThemeAssets::iter() { + res.push('\n'); + let theme = ThemeAssets::get(file.as_ref()).unwrap(); + res.push_str(std::str::from_utf8(theme.data.as_ref()).unwrap()); + } + Ok( + Response::builder() + .status(200) + .header("content-type", "text/css") + .header("Cache-Control", "public, max-age=1209600, s-maxage=86400") + .body(res.to_string().into()) + .unwrap_or_default(), + ) +} + #[tokio::main] async fn main() { - let matches = cli::new("Libreddit") + let matches = Command::new("Libreddit") .version(env!("CARGO_PKG_VERSION")) .about("Private front-end for Reddit written in Rust ") .arg( @@ -152,7 +169,7 @@ async fn main() { } // Read static files - app.at("/style.css").get(|_| resource(include_str!("../static/style.css"), "text/css", false).boxed()); + app.at("/style.css").get(|_| style().boxed()); app .at("/manifest.json") .get(|_| resource(include_str!("../static/manifest.json"), "application/json", false).boxed()); @@ -193,6 +210,7 @@ async fn main() { app.at("/user/[deleted]").get(|req| error(req, "User has deleted their account".to_string()).boxed()); app.at("/user/:name").get(|r| user::profile(r).boxed()); + app.at("/user/:name/:listing").get(|r| user::profile(r).boxed()); app.at("/user/:name/comments/:id").get(|r| post::item(r).boxed()); app.at("/user/:name/comments/:id/:title").get(|r| post::item(r).boxed()); app.at("/user/:name/comments/:id/:title/:comment_id").get(|r| post::item(r).boxed()); diff --git a/src/post.rs b/src/post.rs index 857b0b4..02ca380 100644 --- a/src/post.rs +++ b/src/post.rs @@ -1,6 +1,5 @@ // CRATES use crate::client::json; -use crate::esc; use crate::server::RequestExt; use crate::subreddit::{can_access_quarantine, quarantine}; use crate::utils::{ @@ -13,7 +12,7 @@ use std::collections::HashSet; // STRUCTS #[derive(Template)] -#[template(path = "post.html", escape = "none")] +#[template(path = "post.html")] struct PostTemplate { comments: Vec, post: Post, @@ -100,15 +99,18 @@ async fn parse_post(json: &serde_json::Value) -> Post { let permalink = val(post, "permalink"); let body = if val(post, "removed_by_category") == "moderator" { - format!("

[removed] — view removed post

", permalink) + format!( + "

[removed] — view removed post

", + permalink + ) } else { - rewrite_urls(&val(post, "selftext_html")).replace("\\", "") + rewrite_urls(&val(post, "selftext_html")) }; // Build a post using data parsed from Reddit post API Post { id: val(post, "id"), - title: esc!(post, "title"), + title: val(post, "title"), community: val(post, "subreddit"), body, author: Author { @@ -119,7 +121,7 @@ async fn parse_post(json: &serde_json::Value) -> Post { post["data"]["author_flair_richtext"].as_array(), post["data"]["author_flair_text"].as_str(), ), - text: esc!(post, "link_flair_text"), + text: val(post, "link_flair_text"), background_color: val(post, "author_flair_background_color"), foreground_color: val(post, "author_flair_text_color"), }, @@ -143,7 +145,7 @@ async fn parse_post(json: &serde_json::Value) -> Post { post["data"]["link_flair_richtext"].as_array(), post["data"]["link_flair_text"].as_str(), ), - text: esc!(post, "link_flair_text"), + text: val(post, "link_flair_text"), background_color: val(post, "link_flair_background_color"), foreground_color: if val(post, "link_flair_text_color") == "dark" { "black".to_string() @@ -199,9 +201,12 @@ fn parse_comments(json: &serde_json::Value, post_link: &str, post_author: &str, let highlighted = id == highlighted_comment; let body = if val(&comment, "author") == "[deleted]" && val(&comment, "body") == "[removed]" { - format!("

[removed] — view removed comment

", post_link, id) + format!( + "

[removed] — view removed comment

", + post_link, id + ) } else { - rewrite_urls(&val(&comment, "body_html")).to_string() + rewrite_urls(&val(&comment, "body_html")) }; let author = Author { @@ -212,7 +217,7 @@ fn parse_comments(json: &serde_json::Value, post_link: &str, post_author: &str, data["author_flair_richtext"].as_array(), data["author_flair_text"].as_str(), ), - text: esc!(&comment, "link_flair_text"), + text: val(&comment, "link_flair_text"), background_color: val(&comment, "author_flair_background_color"), foreground_color: val(&comment, "author_flair_text_color"), }, diff --git a/src/search.rs b/src/search.rs index 3547679..4dd3b5f 100644 --- a/src/search.rs +++ b/src/search.rs @@ -29,7 +29,7 @@ struct Subreddit { } #[derive(Template)] -#[template(path = "search.html", escape = "none")] +#[template(path = "search.html")] struct SearchTemplate { posts: Vec, subreddits: Vec, diff --git a/src/server.rs b/src/server.rs index ce20860..979dbd7 100644 --- a/src/server.rs +++ b/src/server.rs @@ -158,8 +158,8 @@ impl Server { Ok::<_, String>(service_fn(move |req: Request| { let headers = default_headers.clone(); - // Remove double slashes - let mut path = req.uri().path().replace("//", "/"); + // Remove double slashes and decode encoded slashes + let mut path = req.uri().path().replace("//", "/").replace("%2F","/"); // Remove trailing slashes if path != "/" && path.ends_with('/') { diff --git a/src/subreddit.rs b/src/subreddit.rs index d673601..b03e7e9 100644 --- a/src/subreddit.rs +++ b/src/subreddit.rs @@ -1,5 +1,4 @@ // CRATES -use crate::esc; use crate::utils::{ catch_random, error, filter_posts, format_num, format_url, get_filters, param, redirect, rewrite_urls, setting, template, val, Post, Preferences, Subreddit, }; @@ -11,7 +10,7 @@ use time::{Duration, OffsetDateTime}; // STRUCTS #[derive(Template)] -#[template(path = "subreddit.html", escape = "none")] +#[template(path = "subreddit.html")] struct SubredditTemplate { sub: Subreddit, posts: Vec, @@ -19,6 +18,7 @@ struct SubredditTemplate { ends: (String, String), prefs: Preferences, url: String, + redirect_url: String, /// Whether the subreddit itself is filtered. is_filtered: bool, /// Whether all fetched posts are filtered (to differentiate between no posts fetched in the first place, @@ -27,7 +27,7 @@ struct SubredditTemplate { } #[derive(Template)] -#[template(path = "wiki.html", escape = "none")] +#[template(path = "wiki.html")] struct WikiTemplate { sub: String, wiki: String, @@ -37,7 +37,7 @@ struct WikiTemplate { } #[derive(Template)] -#[template(path = "wall.html", escape = "none")] +#[template(path = "wall.html")] struct WallTemplate { title: String, sub: String, @@ -86,18 +86,17 @@ pub async fn community(req: Request) -> Result, String> { } else { Subreddit::default() } - } else if sub_name.contains('+') { - // Multireddit + } else { + // Multireddit, all, popular Subreddit { name: sub_name.clone(), ..Subreddit::default() } - } else { - Subreddit::default() }; let path = format!("/r/{}/{}.json?{}&raw_json=1", sub_name.clone(), sort, req.uri().query().unwrap_or_default()); let url = String::from(req.uri().path_and_query().map_or("", |val| val.as_str())); + let redirect_url = url[1..].replace('?', "%3F").replace('&', "%26").replace('+', "%2B"); let filters = get_filters(&req); // If all requested subs are filtered, we don't need to fetch posts. @@ -109,6 +108,7 @@ pub async fn community(req: Request) -> Result, String> { ends: (param(&path, "after").unwrap_or_default(), "".to_string()), prefs: Preferences::new(req), url, + redirect_url, is_filtered: true, all_posts_filtered: false, }) @@ -124,6 +124,7 @@ pub async fn community(req: Request) -> Result, String> { ends: (param(&path, "after").unwrap_or_default(), after), prefs: Preferences::new(req), url, + redirect_url, is_filtered: false, all_posts_filtered, }) @@ -253,7 +254,7 @@ pub async fn subscriptions_filters(req: Request) -> Result, // Redirect back to subreddit // check for redirect parameter if unsubscribing/unfiltering from outside sidebar let path = if let Some(redirect_path) = param(&format!("?{}", query), "redirect") { - format!("/{}/", redirect_path) + format!("/{}", redirect_path) } else { format!("/r/{}", sub) }; @@ -334,10 +335,10 @@ pub async fn sidebar(req: Request) -> Result, String> { match json(path, quarantined).await { // If success, receive JSON in response Ok(response) => template(WikiTemplate { - wiki: rewrite_urls(&val(&response, "description_html").replace("\\", "")), + wiki: rewrite_urls(&val(&response, "description_html")), // wiki: format!( // "{}

Moderators


    {}
", - // rewrite_urls(&val(&response, "description_html").replace("\\", "")), + // rewrite_urls(&val(&response, "description_html"), // moderators(&sub, quarantined).await.unwrap_or(vec!["Could not fetch moderators".to_string()]).join(""), // ), sub, @@ -406,10 +407,10 @@ async fn subreddit(sub: &str, quarantined: bool) -> Result { let icon = if community_icon.is_empty() { val(&res, "icon_img") } else { community_icon.to_string() }; Ok(Subreddit { - name: esc!(&res, "display_name"), - title: esc!(&res, "title"), - description: esc!(&res, "public_description"), - info: rewrite_urls(&val(&res, "description_html").replace("\\", "")), + name: val(&res, "display_name"), + title: val(&res, "title"), + description: val(&res, "public_description"), + info: rewrite_urls(&val(&res, "description_html")), // moderators: moderators_list(sub, quarantined).await.unwrap_or_default(), icon: format_url(&icon), members: format_num(members), diff --git a/src/user.rs b/src/user.rs index d60e65d..69c4ae9 100644 --- a/src/user.rs +++ b/src/user.rs @@ -1,22 +1,24 @@ // CRATES use crate::client::json; -use crate::esc; use crate::server::RequestExt; use crate::utils::{error, filter_posts, format_url, get_filters, param, template, Post, Preferences, User}; use askama::Template; use hyper::{Body, Request, Response}; -use time::{OffsetDateTime, macros::format_description}; +use time::{macros::format_description, OffsetDateTime}; // STRUCTS #[derive(Template)] -#[template(path = "user.html", escape = "none")] +#[template(path = "user.html")] struct UserTemplate { user: User, posts: Vec, sort: (String, String), ends: (String, String), + /// "overview", "comments", or "submitted" + listing: String, prefs: Preferences, url: String, + redirect_url: String, /// Whether the user themself is filtered. is_filtered: bool, /// Whether all fetched posts are filtered (to differentiate between no posts fetched in the first place, @@ -26,13 +28,17 @@ struct UserTemplate { // FUNCTIONS pub async fn profile(req: Request) -> Result, String> { + let listing = req.param("listing").unwrap_or_else(|| "overview".to_string()); + // Build the Reddit JSON API path let path = format!( - "/user/{}.json?{}&raw_json=1", + "/user/{}/{}.json?{}&raw_json=1", req.param("name").unwrap_or_else(|| "reddit".to_string()), - req.uri().query().unwrap_or_default() + listing, + req.uri().query().unwrap_or_default(), ); let url = String::from(req.uri().path_and_query().map_or("", |val| val.as_str())); + let redirect_url = url[1..].replace('?', "%3F").replace('&', "%26"); // Retrieve other variables from Libreddit request let sort = param(&path, "sort").unwrap_or_default(); @@ -46,8 +52,10 @@ pub async fn profile(req: Request) -> Result, String> { posts: Vec::new(), sort: (sort, param(&path, "t").unwrap_or_default()), ends: (param(&path, "after").unwrap_or_default(), "".to_string()), + listing, prefs: Preferences::new(req), url, + redirect_url, is_filtered: true, all_posts_filtered: false, }) @@ -62,8 +70,10 @@ pub async fn profile(req: Request) -> Result, String> { posts, sort: (sort, param(&path, "t").unwrap_or_default()), ends: (param(&path, "after").unwrap_or_default(), after), + listing, prefs: Preferences::new(req), url, + redirect_url, is_filtered: false, all_posts_filtered, }) @@ -91,11 +101,11 @@ async fn user(name: &str) -> Result { // Parse the JSON output into a User struct User { name: res["data"]["name"].as_str().unwrap_or(name).to_owned(), - title: esc!(about("title")), + title: about("title"), icon: format_url(&about("icon_img")), karma: res["data"]["total_karma"].as_i64().unwrap_or(0), created: created.format(format_description!("[month repr:short] [day] '[year repr:last_two]")).unwrap_or_default(), - banner: esc!(about("banner_img")), + banner: about("banner_img"), description: about("public_description"), } }) diff --git a/src/utils.rs b/src/utils.rs index b2e4af1..f63982e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,15 +1,16 @@ // // CRATES // -use crate::{client::json, esc, server::RequestExt}; +use crate::{client::json, server::RequestExt}; use askama::Template; use cookie::Cookie; use hyper::{Body, Request, Response}; use regex::Regex; +use rust_embed::RustEmbed; use serde_json::Value; use std::collections::{HashMap, HashSet}; use std::str::FromStr; -use time::{Duration, OffsetDateTime, macros::format_description}; +use time::{macros::format_description, Duration, OffsetDateTime}; use url::Url; // Post flair with content, background color and foreground color @@ -41,7 +42,7 @@ impl FlairPart { Self { flair_part_type: value("e").to_string(), value: match value("e") { - "text" => esc!(value("t")), + "text" => value("t").to_string(), "emoji" => format_url(value("u")), _ => String::new(), }, @@ -54,7 +55,7 @@ impl FlairPart { "text" => match text_flair { Some(text) => vec![Self { flair_part_type: "text".to_string(), - value: esc!(text), + value: text.to_string(), }], None => Vec::new(), }, @@ -217,24 +218,19 @@ pub struct Post { impl Post { // Fetch posts of a user or subreddit and return a vector of posts and the "after" value pub async fn fetch(path: &str, quarantine: bool) -> Result<(Vec, String), String> { - let res; - let post_list; - // Send a request to the url - match json(path.to_string(), quarantine).await { + let res = match json(path.to_string(), quarantine).await { // If success, receive JSON in response - Ok(response) => { - res = response; - } + Ok(response) => response, // If the Reddit API returns an error, exit this function Err(msg) => return Err(msg), - } + }; // Fetch the list of posts from the JSON response - match res["data"]["children"].as_array() { - Some(list) => post_list = list, + let post_list = match res["data"]["children"].as_array() { + Some(list) => list, None => return Err("No posts found".to_string()), - } + }; let mut posts: Vec = Vec::new(); @@ -245,7 +241,7 @@ impl Post { let (rel_time, created) = time(data["created_utc"].as_f64().unwrap_or_default()); let score = data["score"].as_i64().unwrap_or_default(); let ratio: f64 = data["upvote_ratio"].as_f64().unwrap_or(1.0) * 100.0; - let title = esc!(post, "title"); + let title = val(post, "title"); // Determine the type of media along with the media URL let (post_type, media, gallery) = Media::parse(data).await; @@ -270,7 +266,7 @@ impl Post { data["author_flair_richtext"].as_array(), data["author_flair_text"].as_str(), ), - text: esc!(post, "link_flair_text"), + text: val(post, "link_flair_text"), background_color: val(post, "author_flair_background_color"), foreground_color: val(post, "author_flair_text_color"), }, @@ -298,7 +294,7 @@ impl Post { data["link_flair_richtext"].as_array(), data["link_flair_text"].as_str(), ), - text: esc!(post, "link_flair_text"), + text: val(post, "link_flair_text"), background_color: val(post, "link_flair_background_color"), foreground_color: if val(post, "link_flair_text_color") == "dark" { "black".to_string() @@ -324,7 +320,7 @@ impl Post { } #[derive(Template)] -#[template(path = "comment.html", escape = "none")] +#[template(path = "comment.html")] // Comment with content, post, score and data/time that it was posted pub struct Comment { pub id: String, @@ -400,7 +396,7 @@ impl Awards { } #[derive(Template)] -#[template(path = "error.html", escape = "none")] +#[template(path = "error.html")] pub struct ErrorTemplate { pub msg: String, pub prefs: Preferences, @@ -445,6 +441,7 @@ pub struct Params { #[derive(Default)] pub struct Preferences { + pub available_themes: Vec, pub theme: String, pub front_page: String, pub layout: String, @@ -459,10 +456,23 @@ pub struct Preferences { pub filters: Vec, } +#[derive(RustEmbed)] +#[folder = "static/themes/"] +#[include = "*.css"] +pub struct ThemeAssets; + impl Preferences { // Build preferences from cookies pub fn new(req: Request) -> Self { + // Read available theme names from embedded css files. + // Always make the default "system" theme available. + let mut themes = vec!["system".to_string()]; + for file in ThemeAssets::iter() { + let chunks: Vec<&str> = file.as_ref().split(".css").collect(); + themes.push(chunks[0].to_owned()) + } Self { + available_themes: themes, theme: setting(&req, "theme"), front_page: setting(&req, "front_page"), layout: setting(&req, "layout"), @@ -607,8 +617,11 @@ pub fn format_url(url: &str) -> String { // Rewrite Reddit links to Libreddit in body of text pub fn rewrite_urls(input_text: &str) -> String { - let text1 = - Regex::new(r#"href="(https|http|)://(www\.|old\.|np\.|amp\.|)(reddit\.com|redd\.it)/"#).map_or(String::new(), |re| re.replace_all(input_text, r#"href="/"#).to_string()); + let text1 = Regex::new(r#"href="(https|http|)://(www\.|old\.|np\.|amp\.|)(reddit\.com|redd\.it)/"#) + .map_or(String::new(), |re| re.replace_all(input_text, r#"href="/"#).to_string()) + // Remove (html-encoded) "\" from URLs. + .replace("%5C", "") + .replace('\\', ""); // Rewrite external media previews to Libreddit Regex::new(r"https://external-preview\.redd\.it(.*)[^?]").map_or(String::new(), |re| { @@ -652,7 +665,12 @@ pub fn time(created: f64) -> (String, String) { format!("{}m ago", time_delta.whole_minutes()) }; - (rel_time, time.format(format_description!("[month repr:short] [day] [year], [hour]:[minute]:[second] UTC")).unwrap_or_default()) + ( + rel_time, + time + .format(format_description!("[month repr:short] [day] [year], [hour]:[minute]:[second] UTC")) + .unwrap_or_default(), + ) } // val() function used to parse JSON from Reddit APIs @@ -660,17 +678,6 @@ pub fn val(j: &Value, k: &str) -> String { j["data"][k].as_str().unwrap_or_default().to_string() } -// Escape < and > to accurately render HTML -#[macro_export] -macro_rules! esc { - ($f:expr) => { - $f.replace('&', "&").replace('<', "<").replace('>', ">") - }; - ($j:expr, $k:expr) => { - $j["data"][$k].as_str().unwrap_or_default().to_string().replace('<', "<").replace('>', ">") - }; -} - // // NETWORKING // @@ -710,6 +717,7 @@ pub async fn error(req: Request, msg: String) -> Result, St #[cfg(test)] mod tests { use super::format_num; + use super::rewrite_urls; #[test] fn format_num_works() { @@ -719,4 +727,14 @@ mod tests { assert_eq!(format_num(1001), ("1.0k".to_string(), "1001".to_string())); assert_eq!(format_num(1_999_999), ("2.0m".to_string(), "1999999".to_string())); } + + #[test] + fn rewrite_urls_removes_backslashes() { + let comment_body_html = + r#"https://www.reddit.com/r/linux\\_gaming/comments/x/just\\_a\\_test/"#; + assert_eq!( + rewrite_urls(comment_body_html), + r#"https://www.reddit.com/r/linux_gaming/comments/x/just_a_test/"# + ) + } } diff --git a/static/style.css b/static/style.css index 92ef7c2..3e0d64d 100644 --- a/static/style.css +++ b/static/style.css @@ -45,124 +45,7 @@ } } -/* Light theme setting */ -.light { - --accent: #009a9a; - --green: #00a229; - --text: black; - --foreground: #f5f5f5; - --background: #ddd; - --outside: #ececec; - --post: #eee; - --panel-border: 1px solid #ccc; - --highlighted: white; - --visited: #555; - --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -} - -/* Black theme setting */ -.black { - --accent: #009a9a; - --green: #00a229; - --text: white; - --foreground: #0f0f0f; - --background: black; - --outside: black; - --post: black; - --panel-border: 2px solid #0f0f0f; - --highlighted: #0f0f0f; - --visited: #aaa; - --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -} - -/* Dracula theme setting */ -.dracula { - --accent: #bd93f9; - --green: #50fa7b; - --text: #f8f8f2; - --foreground: #3d4051; - --background: #282a36; - --outside: #393c4d; - --post: #333544; - --panel-border: 2px solid #44475a; - --highlighted: #4e5267; - --visited: #969692; - --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -} - -/* Nord theme setting */ -.nord { - --accent: #8fbcbb; - --green: #a3be8c; - --text: #eceff4; - --foreground: #3b4252; - --background: #2e3440; - --outside: #434c5e; - --post: #434c5e; - --panel-border: 2px solid #4c566a; - --highlighted: #3b4252; - --visited: #a3a5aa; - --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -} - -/* Laserwave theme setting */ -.laserwave { - --accent: #eb64b9; - --green: #74dfc4; - --text: #e0dfe1; - --foreground: #302a36; - --background: #27212e; - --outside: #3e3647; - --post: #3e3647; - --panel-border: 2px solid #2f2738; - --highlighted: #302a36; - --visited: #91889b; - --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -} - -/* Violet theme setting */ -.violet { - --accent: #7c71dd; - --green: #5cff85; - --text: white; - --foreground: #1F2347; - --background: #12152b; - --outside: #181c3a; - --post: #181c3a; - --panel-border: 1px solid #1F2347; - --highlighted: #1F2347; - --visited: #aaa; - --shadow: 0 2px 5px rgba(0, 0, 0, 0.5); -} - -/* Gold theme setting */ -.gold { - --accent: #f2aa4c; - --green: #5cff85; - --text: white; - --foreground: #234; - --background: #101820; - --outside: #1b2936; - --post: #1b2936; - --panel-border: 0px solid black; - --highlighted: #234; - --visited: #aaa; - --shadow: 0 2px 5px rgba(0, 0, 0, 0.5); -} - -/* Rosebox theme setting */ -.rosebox { - --accent: #a57562; - --green: #a3be8c; - --text: white; - --foreground: #222; - --background: #262626; - --outside: #222; - --post: #222; - --panel-border: 1px solid #222; - --highlighted: #262626; - --shadow: 0 1px 3px rgba(0, 0, 0, 0.5); -} +/* Other themes are located in the "themes" folder */ /* General */ @@ -177,6 +60,7 @@ html, body, div, h1, h2, h3, h4, h5, h6, ul, ol, dl, li, dt, dd, p, blockquote, pre, form, fieldset, table, th, td, select, input { + accent-color: var(--accent); margin: 0; color: var(--text); font-family: "Inter", sans-serif; @@ -487,7 +371,7 @@ aside { /* Sorting and Search */ -select, #search, #sort_options, #inside, #searchbox > *, #sort_submit { +select, #search, #sort_options, #listing_options, #inside, #searchbox > *, #sort_submit { height: 38px; } @@ -563,6 +447,11 @@ button.submit:hover > svg { stroke: var(--accent); } border-radius: 5px 0px 0px 5px; } +#listing_options + #sort_select { + margin-left: 10px; + border-radius: 5px 0px 0px 5px; +} + #search_sort { background: var(--highlighted); border-radius: 5px; @@ -591,7 +480,7 @@ button.submit:hover > svg { stroke: var(--accent); } margin-bottom: 20px; } -#sort_options, footer > a { +#sort_options, #listing_options, footer > a { border-radius: 5px; align-items: center; box-shadow: var(--shadow); @@ -600,7 +489,7 @@ button.submit:hover > svg { stroke: var(--accent); } overflow: hidden; } -#sort_options > a, footer > a { +#sort_options > a, #listing_options > a, footer > a { color: var(--text); padding: 10px 20px; text-align: center; @@ -608,12 +497,12 @@ button.submit:hover > svg { stroke: var(--accent); } transition: 0.2s background; } -#sort_options > a.selected { +#sort_options > a.selected, #listing_options > a.selected { background: var(--accent); color: var(--foreground); } -#sort_options > a:not(.selected):hover { +#sort_options > a:not(.selected):hover, #listing_options > a:not(.selected):hover { background: var(--foreground); } @@ -749,6 +638,7 @@ a.search_subreddit:hover { font-size: 16px; font-weight: 500; line-height: 1.5; + overflow-wrap: anywhere; margin: 5px 15px 5px 12px; grid-area: post_title; } @@ -878,6 +768,7 @@ a.search_subreddit:hover { color: var(--accent); margin: 5px 12px; grid-area: post_media; + overflow-wrap: anywhere; } .post_body { @@ -886,6 +777,7 @@ a.search_subreddit:hover { padding: 5px 15px 5px 12px; grid-area: post_body; width: calc(100% - 30px); + overflow-wrap: anywhere; } /* Used only for text post preview */ @@ -1311,6 +1203,8 @@ input[type="submit"] { .md table { margin: 5px; overflow-x: auto; + display: block; + max-width: fit-content; } .md code { diff --git a/static/themes/black.css b/static/themes/black.css new file mode 100644 index 0000000..5906b5b --- /dev/null +++ b/static/themes/black.css @@ -0,0 +1,14 @@ +/* Black theme setting */ +.black { + --accent: #009a9a; + --green: #00a229; + --text: white; + --foreground: #0f0f0f; + --background: black; + --outside: black; + --post: black; + --panel-border: 2px solid #0f0f0f; + --highlighted: #0f0f0f; + --visited: #aaa; + --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} \ No newline at end of file diff --git a/static/themes/dark.css b/static/themes/dark.css new file mode 100644 index 0000000..ef7b32c --- /dev/null +++ b/static/themes/dark.css @@ -0,0 +1,14 @@ +/* Dark theme setting */ +.dark{ + --accent: aqua; + --green: #5cff85; + --text: white; + --foreground: #222; + --background: #0f0f0f; + --outside: #1f1f1f; + --post: #161616; + --panel-border: 1px solid #333; + --highlighted: #333; + --visited: #aaa; + --shadow: 0 1px 3px rgba(0, 0, 0, 0.5); +} \ No newline at end of file diff --git a/static/themes/dracula.css b/static/themes/dracula.css new file mode 100644 index 0000000..0e36e2b --- /dev/null +++ b/static/themes/dracula.css @@ -0,0 +1,14 @@ +/* Dracula theme setting */ +.dracula { + --accent: #bd93f9; + --green: #50fa7b; + --text: #f8f8f2; + --foreground: #3d4051; + --background: #282a36; + --outside: #393c4d; + --post: #333544; + --panel-border: 2px solid #44475a; + --highlighted: #4e5267; + --visited: #969692; + --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} \ No newline at end of file diff --git a/static/themes/gold.css b/static/themes/gold.css new file mode 100644 index 0000000..4ff7d6e --- /dev/null +++ b/static/themes/gold.css @@ -0,0 +1,14 @@ +/* Gold theme setting */ +.gold { + --accent: #f2aa4c; + --green: #5cff85; + --text: white; + --foreground: #234; + --background: #101820; + --outside: #1b2936; + --post: #1b2936; + --panel-border: 0px solid black; + --highlighted: #234; + --visited: #aaa; + --shadow: 0 2px 5px rgba(0, 0, 0, 0.5); +} \ No newline at end of file diff --git a/static/themes/laserwave.css b/static/themes/laserwave.css new file mode 100644 index 0000000..dde21f3 --- /dev/null +++ b/static/themes/laserwave.css @@ -0,0 +1,14 @@ +/* Laserwave theme setting */ +.laserwave { + --accent: #eb64b9; + --green: #74dfc4; + --text: #e0dfe1; + --foreground: #302a36; + --background: #27212e; + --outside: #3e3647; + --post: #3e3647; + --panel-border: 2px solid #2f2738; + --highlighted: #302a36; + --visited: #91889b; + --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} \ No newline at end of file diff --git a/static/themes/light.css b/static/themes/light.css new file mode 100644 index 0000000..1fe0387 --- /dev/null +++ b/static/themes/light.css @@ -0,0 +1,14 @@ +/* Light theme setting */ +.light { + --accent: #009a9a; + --green: #00a229; + --text: black; + --foreground: #f5f5f5; + --background: #ddd; + --outside: #ececec; + --post: #eee; + --panel-border: 1px solid #ccc; + --highlighted: white; + --visited: #555; + --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} \ No newline at end of file diff --git a/static/themes/nord.css b/static/themes/nord.css new file mode 100644 index 0000000..d75fd11 --- /dev/null +++ b/static/themes/nord.css @@ -0,0 +1,14 @@ +/* Nord theme setting */ +.nord { + --accent: #8fbcbb; + --green: #a3be8c; + --text: #eceff4; + --foreground: #3b4252; + --background: #2e3440; + --outside: #434c5e; + --post: #434c5e; + --panel-border: 2px solid #4c566a; + --highlighted: #3b4252; + --visited: #a3a5aa; + --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} diff --git a/static/themes/rosebox.css b/static/themes/rosebox.css new file mode 100644 index 0000000..903931d --- /dev/null +++ b/static/themes/rosebox.css @@ -0,0 +1,13 @@ +/* Rosebox theme setting */ +.rosebox { + --accent: #a57562; + --green: #a3be8c; + --text: white; + --foreground: #222; + --background: #262626; + --outside: #222; + --post: #222; + --panel-border: 1px solid #222; + --highlighted: #262626; + --shadow: 0 1px 3px rgba(0, 0, 0, 0.5); +} \ No newline at end of file diff --git a/static/themes/violet.css b/static/themes/violet.css new file mode 100644 index 0000000..0d836ee --- /dev/null +++ b/static/themes/violet.css @@ -0,0 +1,14 @@ +/* Violet theme setting */ +.violet { + --accent: #7c71dd; + --green: #5cff85; + --text: white; + --foreground: #1F2347; + --background: #12152b; + --outside: #181c3a; + --post: #181c3a; + --panel-border: 1px solid #1F2347; + --highlighted: #1F2347; + --visited: #aaa; + --shadow: 0 2px 5px rgba(0, 0, 0, 0.5); +} \ No newline at end of file diff --git a/templates/comment.html b/templates/comment.html index 3014192..61c44f5 100644 --- a/templates/comment.html +++ b/templates/comment.html @@ -32,9 +32,9 @@ {% if is_filtered %}
(Filtered content)
{% else %} -
{{ body }}
+
{{ body|safe }}
{% endif %} -
{% for c in replies -%}{{ c.render().unwrap() }}{%- endfor %} +
{% for c in replies -%}{{ c.render().unwrap()|safe }}{%- endfor %}
diff --git a/templates/post.html b/templates/post.html index add5881..227d7fc 100644 --- a/templates/post.html +++ b/templates/post.html @@ -55,7 +55,7 @@ {% endif %}

-

+

{{ post.title }} {% if post.flair.flair_parts.len() > 0 %} {% call utils::render_flair(post.flair.flair_parts) %} {% endif %} {% if post.flags.nsfw %} NSFW{% endif %} -

+

@@ -110,7 +110,7 @@ {% endif %} -
{{ post.body }}
+
{{ post.body|safe }}
{{ post.score.0 }} Upvotes
{%- endfor %} diff --git a/templates/search.html b/templates/search.html index 0218c35..9386f35 100644 --- a/templates/search.html +++ b/templates/search.html @@ -39,7 +39,7 @@ {% endif %} {% for subreddit in subreddits %} -
{% if subreddit.icon != "" %}r/{{ subreddit.name }} icon{% endif %}
+
{% if subreddit.icon != "" %}r/{{ subreddit.name }} icon{% endif %}

r/{{ subreddit.name }} @@ -92,13 +92,13 @@ {% if params.before != "" %} PREV + &before={{ params.before }}" accesskey="P">PREV {% endif %} {% if params.after != "" %} NEXT + &after={{ params.after }}" accesskey="N">NEXT {% endif %} {% endif %} diff --git a/templates/settings.html b/templates/settings.html index 8a70912..60ee109 100644 --- a/templates/settings.html +++ b/templates/settings.html @@ -15,7 +15,7 @@

Interface @@ -110,7 +110,7 @@

Note: settings and subscriptions are saved in browser cookies. Clearing your cookies will reset them.


-

You can restore your current settings and subscriptions after clearing your cookies using this link.

+

You can restore your current settings and subscriptions after clearing your cookies using this link.

diff --git a/templates/subreddit.html b/templates/subreddit.html index be22acc..e5e8fa1 100644 --- a/templates/subreddit.html +++ b/templates/subreddit.html @@ -41,7 +41,7 @@ {% if sub.name.contains("+") %} -
+
{% endif %} @@ -65,21 +65,21 @@
{% if !ends.0.is_empty() %} - PREV + PREV {% endif %} {% if !ends.1.is_empty() %} - NEXT + NEXT {% endif %}
{% endif %} - {% if is_filtered || (!sub.name.is_empty() && !sub.name.contains("+")) %} + {% if is_filtered || (!sub.name.is_empty() && sub.name != "all" && sub.name != "popular" && !sub.name.contains("+")) %}