mirror of
https://git.joinplu.me/Plume/Plume.git
synced 2024-11-19 18:21:00 +00:00
commit
dbdcbe7104
29 changed files with 319 additions and 215 deletions
137
Cargo.lock
generated
137
Cargo.lock
generated
|
@ -71,14 +71,6 @@ dependencies = [
|
|||
"url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "antidote"
|
||||
version = "1.0.0"
|
||||
|
@ -97,16 +89,6 @@ dependencies = [
|
|||
"nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.6"
|
||||
|
@ -231,20 +213,6 @@ dependencies = [
|
|||
"time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.31.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "1.6.0"
|
||||
|
@ -253,22 +221,6 @@ dependencies = [
|
|||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "comrak"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"entities 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"typed-arena 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
version = "0.11.0-dev"
|
||||
|
@ -400,11 +352,6 @@ dependencies = [
|
|||
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "entities"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "error-chain"
|
||||
version = "0.11.0"
|
||||
|
@ -1008,7 +955,6 @@ dependencies = [
|
|||
"bcrypt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"comrak 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"diesel 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dotenv 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1019,6 +965,7 @@ dependencies = [
|
|||
"hyper 0.11.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"reqwest 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rocket 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)",
|
||||
"rocket_codegen 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)",
|
||||
|
@ -1070,6 +1017,14 @@ dependencies = [
|
|||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.3.15"
|
||||
|
@ -1134,14 +1089,6 @@ name = "redox_syscall"
|
|||
version = "0.1.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "redox_termios"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "0.2.10"
|
||||
|
@ -1474,11 +1421,6 @@ name = "string_cache_shared"
|
|||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.11.11"
|
||||
|
@ -1587,24 +1529,6 @@ dependencies = [
|
|||
"url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termion"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "0.3.5"
|
||||
|
@ -1786,24 +1710,11 @@ name = "traitobject"
|
|||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "twoway"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typeable"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "typed-arena"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.10.0"
|
||||
|
@ -1848,11 +1759,6 @@ name = "unicode-segmentation"
|
|||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.0.4"
|
||||
|
@ -1863,11 +1769,6 @@ name = "unicode-xid"
|
|||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode_categories"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unidecode"
|
||||
version = "0.3.0"
|
||||
|
@ -1919,11 +1820,6 @@ name = "vcpkg"
|
|||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.1.3"
|
||||
|
@ -1996,11 +1892,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6cbd0b9af8587c72beadc9f72d35b9fbb070982c9e6203e46e93f10df25f8f45"
|
||||
"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
|
||||
"checksum ammonia 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd4c682378117e4186a492b2252b9537990e1617f44aed9788b9a1149de45477"
|
||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
"checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5"
|
||||
"checksum array_tool 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8f8cb5d814eb646a863c4f24978cff2880c4be96ad8cde2c0f0678732902e271"
|
||||
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
|
||||
"checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1"
|
||||
"checksum backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe525f66f42d207968308ee86bc2dd60aa5fab535b22e616323a173d097d8e"
|
||||
"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"
|
||||
"checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9"
|
||||
|
@ -2017,9 +1911,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8b9d2900f78631a5876dc5d6c9033ede027253efcd33dd36b1309fc6cab97ee0"
|
||||
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||
"checksum chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cce36c92cb605414e9b824f866f5babe0a0368e39ea07393b9b63cf3844c0e6"
|
||||
"checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
|
||||
"checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc"
|
||||
"checksum comrak 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "053b26c8ce23b4c505a9479beace98f95899e0bf5c5255cf0219e9b0f48cf6ea"
|
||||
"checksum cookie 0.11.0-dev (git+https://github.com/alexcrichton/cookie-rs?rev=0365a18)" = "<none>"
|
||||
"checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67"
|
||||
"checksum core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d"
|
||||
|
@ -2034,7 +1926,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum dotenv 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a70de3c590ce18df70743cace1cf12565637a0b26fd8b04ef10c7d33fdc66cdc"
|
||||
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
|
||||
"checksum encoding_rs 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98fd0f24d1fb71a4a6b9330c8ca04cbd4e7cc5d846b54ca74ff376bc7c9f798d"
|
||||
"checksum entities 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca"
|
||||
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
|
||||
"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82"
|
||||
"checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b"
|
||||
|
@ -2110,6 +2001,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0"
|
||||
"checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118"
|
||||
"checksum proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "effdb53b25cdad54f8f48843d67398f7ef2e14f12c1b4cb4effc549a6462a4d6"
|
||||
"checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32"
|
||||
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
|
||||
"checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408"
|
||||
"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8"
|
||||
|
@ -2118,7 +2010,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1"
|
||||
"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
|
||||
"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd"
|
||||
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
||||
"checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb"
|
||||
"checksum regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bd90079345f4a4c3409214734ae220fd773c6f2e8a543d07370c6c1c369cfbfb"
|
||||
"checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a"
|
||||
|
@ -2155,7 +2046,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423"
|
||||
"checksum string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35293b05cf1494e8ddd042a7df6756bf18d07f42d234f32e71dce8a7aabb0191"
|
||||
"checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
|
||||
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
|
||||
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
|
||||
"checksum syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97c05b8ebc34ddd6b967994d5c6e9852fa92f8b82b3858c39451f97346dcce5"
|
||||
"checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59"
|
||||
|
@ -2167,8 +2057,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
|
||||
"checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508"
|
||||
"checksum tera 0.11.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e815b67d44c26feb06630011fb58b5b243f4e9585aac1ed0592c5795de64cd75"
|
||||
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
||||
"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
|
||||
"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
|
||||
"checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098"
|
||||
"checksum tokio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be15ef40f675c9fe66e354d74c73f3ed012ca1aa14d65846a33ee48f1ae8d922"
|
||||
|
@ -2185,9 +2073,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum tokio-udp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "137bda266504893ac4774e0ec4c2108f7ccdbcb7ac8dced6305fe9e4e0b5041a"
|
||||
"checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9"
|
||||
"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
|
||||
"checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1"
|
||||
"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887"
|
||||
"checksum typed-arena 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5934776c3ac1bea4a9d56620d6bf2d483b20d394e49581db40f187e1118ff667"
|
||||
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
|
||||
"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
|
||||
"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
|
||||
|
@ -2195,10 +2081,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
|
||||
"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f"
|
||||
"checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946"
|
||||
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
|
||||
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
|
||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
"checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
|
||||
"checksum unidecode 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "402bb19d8e03f1d1a7450e2bd613980869438e0666331be3e073089124aa1adc"
|
||||
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
|
||||
"checksum untrusted 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70afa43c8c5d23a53a3c39ec9b56232c5badc19f6bb5ad529c1d6448a7241365"
|
||||
|
@ -2207,7 +2091,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
|
||||
"checksum uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc7e3b898aa6f6c08e5295b6c89258d1331e9ac578cc992fb818759951bdc22"
|
||||
"checksum vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7ed0f6789c8a85ca41bbc1c9d175422116a9869bd1cf31bb08e1493ecce60380"
|
||||
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
||||
"checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d"
|
||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
"checksum webfinger 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "27a4e6d1de7050af8beb026c02bcef5340ec1f3af6d4a02248b7990908baa3ff"
|
||||
|
|
|
@ -9,7 +9,6 @@ array_tool = "1.0"
|
|||
base64 = "0.9"
|
||||
bcrypt = "0.2"
|
||||
colored = "1.6"
|
||||
comrak = "0.2"
|
||||
dotenv = "*"
|
||||
failure = "0.1"
|
||||
failure_derive = "0.1"
|
||||
|
@ -19,6 +18,7 @@ hex = "0.3"
|
|||
hyper = "*"
|
||||
lazy_static = "*"
|
||||
openssl = "0.10.6"
|
||||
pulldown-cmark = { version = "0.1.2", default-features = false }
|
||||
reqwest = "0.8"
|
||||
rpassword = "2.0"
|
||||
serde = "*"
|
||||
|
|
2
migrations/2018-06-20-175532_create_mentions/down.sql
Normal file
2
migrations/2018-06-20-175532_create_mentions/down.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
-- This file should undo anything in `up.sql`
|
||||
DROP TABLE mentions;
|
7
migrations/2018-06-20-175532_create_mentions/up.sql
Normal file
7
migrations/2018-06-20-175532_create_mentions/up.sql
Normal file
|
@ -0,0 +1,7 @@
|
|||
-- Your SQL goes here
|
||||
CREATE TABLE mentions (
|
||||
id SERIAL PRIMARY KEY,
|
||||
mentioned_id INTEGER REFERENCES users(id) ON DELETE CASCADE NOT NULL,
|
||||
post_id INTEGER REFERENCES posts(id) ON DELETE CASCADE,
|
||||
comment_id INTEGER REFERENCES comments(id) ON DELETE CASCADE
|
||||
)
|
|
@ -0,0 +1,2 @@
|
|||
-- This file should undo anything in `up.sql`
|
||||
ALTER TABLE mentions DROP COLUMN ap_url;
|
2
migrations/2018-06-20-194538_add_mentions_ap_url/up.sql
Normal file
2
migrations/2018-06-20-194538_add_mentions_ap_url/up.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
-- Your SQL goes here
|
||||
ALTER TABLE mentions ADD COLUMN ap_url VARCHAR NOT NULL DEFAULT '';
|
3
po/en.po
3
po/en.po
|
@ -280,3 +280,6 @@ msgstr ""
|
|||
|
||||
msgid "You are not author in this blog."
|
||||
msgstr ""
|
||||
|
||||
msgid "{{ data }} mentioned you."
|
||||
msgstr ""
|
||||
|
|
3
po/fr.po
3
po/fr.po
|
@ -279,3 +279,6 @@ msgstr "Vous n'avez pas les droits."
|
|||
|
||||
msgid "You are not author in this blog."
|
||||
msgstr "Vous n'êtes pas auteur dans ce blog."
|
||||
|
||||
msgid "{{ data }} mentioned you."
|
||||
msgstr ""
|
||||
|
|
4
po/pl.po
4
po/pl.po
|
@ -285,5 +285,9 @@ msgstr ""
|
|||
msgid "You are not author in this blog."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "{{ data }} mentioned you."
|
||||
msgstr "{{ data }} skomentował Twój artykuł"
|
||||
|
||||
#~ msgid "Logowanie"
|
||||
#~ msgstr "Zaloguj się"
|
||||
|
|
|
@ -275,3 +275,6 @@ msgstr ""
|
|||
|
||||
msgid "You are not author in this blog."
|
||||
msgstr ""
|
||||
|
||||
msgid "{{ data }} mentioned you."
|
||||
msgstr ""
|
||||
|
|
|
@ -40,8 +40,8 @@ pub trait FromActivity<T: Object>: Sized {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait Notify<T: Object> {
|
||||
fn notify(conn: &PgConnection, act: T, actor: Id);
|
||||
pub trait Notify {
|
||||
fn notify(&self, conn: &PgConnection);
|
||||
}
|
||||
|
||||
pub trait Deletable {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use diesel::{
|
||||
pg::PgConnection,
|
||||
r2d2::{ConnectionManager, Pool, PooledConnection}
|
||||
r2d2::{ConnectionManager, PooledConnection}
|
||||
};
|
||||
use rocket::{Request, State, Outcome, http::Status, request::{self, FromRequest}};
|
||||
use std::ops::Deref;
|
||||
|
||||
use setup::PgPool;
|
||||
|
||||
// From rocket documentation
|
||||
|
||||
// Connection request guard type: a wrapper around an r2d2 pooled connection.
|
||||
|
@ -17,7 +19,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for DbConn {
|
|||
type Error = ();
|
||||
|
||||
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
|
||||
let pool = request.guard::<State<Pool<ConnectionManager<PgConnection>>>>()?;
|
||||
let pool = request.guard::<State<PgPool>>()?;
|
||||
match pool.get() {
|
||||
Ok(conn) => Outcome::Success(DbConn(conn)),
|
||||
Err(_) => Outcome::Failure((Status::ServiceUnavailable, ()))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#![feature(plugin, custom_derive, decl_macro, iterator_find_map)]
|
||||
#![feature(plugin, custom_derive, decl_macro, iterator_find_map, iterator_flatten)]
|
||||
#![plugin(rocket_codegen)]
|
||||
|
||||
extern crate activitypub;
|
||||
|
@ -8,7 +8,6 @@ extern crate base64;
|
|||
extern crate bcrypt;
|
||||
extern crate chrono;
|
||||
extern crate colored;
|
||||
extern crate comrak;
|
||||
extern crate failure;
|
||||
#[macro_use]
|
||||
extern crate failure_derive;
|
||||
|
@ -23,6 +22,7 @@ extern crate dotenv;
|
|||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate openssl;
|
||||
extern crate pulldown_cmark;
|
||||
extern crate reqwest;
|
||||
extern crate rocket;
|
||||
extern crate rocket_contrib;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use activitypub::{
|
||||
activity::Create,
|
||||
link,
|
||||
object::{Note, properties::ObjectProperties}
|
||||
};
|
||||
use chrono;
|
||||
|
@ -13,6 +14,7 @@ use activity_pub::{
|
|||
};
|
||||
use models::{
|
||||
instance::Instance,
|
||||
mentions::Mention,
|
||||
notifications::*,
|
||||
posts::Post,
|
||||
users::User
|
||||
|
@ -114,6 +116,16 @@ impl FromActivity<Note> for Comment {
|
|||
fn from_activity(conn: &PgConnection, note: Note, actor: Id) -> Comment {
|
||||
let previous_url = note.object_props.in_reply_to.clone().unwrap().as_str().unwrap().to_string();
|
||||
let previous_comment = Comment::find_by_ap_url(conn, previous_url.clone());
|
||||
|
||||
// save mentions
|
||||
if let Some(serde_json::Value::Array(tags)) = note.object_props.tag.clone() {
|
||||
for tag in tags.into_iter() {
|
||||
serde_json::from_value::<link::Mention>(tag)
|
||||
.map(|m| Mention::from_activity(conn, m, Id::new(note.clone().object_props.clone().url_string().unwrap_or(String::from("")))))
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
|
||||
let comm = Comment::insert(conn, NewComment {
|
||||
content: SafeString::new(¬e.object_props.content_string().unwrap()),
|
||||
spoiler_text: note.object_props.summary_string().unwrap_or(String::from("")),
|
||||
|
@ -125,27 +137,21 @@ impl FromActivity<Note> for Comment {
|
|||
author_id: User::from_url(conn, actor.clone().into()).unwrap().id,
|
||||
sensitive: false // "sensitive" is not a standard property, we need to think about how to support it with the activitypub crate
|
||||
});
|
||||
Comment::notify(conn, note, actor);
|
||||
comm.notify(conn);
|
||||
comm
|
||||
}
|
||||
}
|
||||
|
||||
impl Notify<Note> for Comment {
|
||||
fn notify(conn: &PgConnection, note: Note, _actor: Id) {
|
||||
match Comment::find_by_ap_url(conn, note.object_props.id_string().unwrap()) {
|
||||
Some(comment) => {
|
||||
for author in comment.clone().get_post(conn).get_authors(conn) {
|
||||
let comment = comment.clone();
|
||||
Notification::insert(conn, NewNotification {
|
||||
title: "{{ data }} commented your article".to_string(),
|
||||
data: Some(comment.get_author(conn).display_name.clone()),
|
||||
content: Some(comment.get_post(conn).title),
|
||||
link: comment.ap_url,
|
||||
user_id: author.id
|
||||
});
|
||||
}
|
||||
},
|
||||
None => println!("Couldn't find comment by AP id, to create a new notification")
|
||||
};
|
||||
impl Notify for Comment {
|
||||
fn notify(&self, conn: &PgConnection) {
|
||||
for author in self.get_post(conn).get_authors(conn) {
|
||||
Notification::insert(conn, NewNotification {
|
||||
title: "{{ data }} commented your article".to_string(),
|
||||
data: Some(self.get_author(conn).display_name.clone()),
|
||||
content: Some(self.get_post(conn).title),
|
||||
link: self.ap_url.clone(),
|
||||
user_id: author.id
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,15 +62,15 @@ impl FromActivity<FollowAct> for Follow {
|
|||
}
|
||||
}
|
||||
|
||||
impl Notify<FollowAct> for Follow {
|
||||
fn notify(conn: &PgConnection, follow: FollowAct, actor: Id) {
|
||||
let follower = User::from_url(conn, actor.into()).unwrap();
|
||||
impl Notify for Follow {
|
||||
fn notify(&self, conn: &PgConnection) {
|
||||
let follower = User::get(conn, self.follower_id).unwrap();
|
||||
Notification::insert(conn, NewNotification {
|
||||
title: "{{ data }} started following you".to_string(),
|
||||
data: Some(follower.display_name.clone()),
|
||||
content: None,
|
||||
link: Some(follower.ap_url),
|
||||
user_id: User::from_url(conn, follow.follow_props.object_link::<Id>().unwrap().into()).unwrap().id
|
||||
user_id: self.following_id
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ impl Like {
|
|||
}
|
||||
|
||||
impl FromActivity<activity::Like> for Like {
|
||||
fn from_activity(conn: &PgConnection, like: activity::Like, actor: Id) -> Like {
|
||||
fn from_activity(conn: &PgConnection, like: activity::Like, _actor: Id) -> Like {
|
||||
let liker = User::from_url(conn, like.like_props.actor.as_str().unwrap().to_string());
|
||||
let post = Post::find_by_ap_url(conn, like.like_props.object.as_str().unwrap().to_string());
|
||||
let res = Like::insert(conn, NewLike {
|
||||
|
@ -85,15 +85,15 @@ impl FromActivity<activity::Like> for Like {
|
|||
user_id: liker.unwrap().id,
|
||||
ap_url: like.object_props.id_string().unwrap_or(String::from(""))
|
||||
});
|
||||
Like::notify(conn, like, actor);
|
||||
res.notify(conn);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl Notify<activity::Like> for Like {
|
||||
fn notify(conn: &PgConnection, like: activity::Like, actor: Id) {
|
||||
let liker = User::from_url(conn, actor.into()).unwrap();
|
||||
let post = Post::find_by_ap_url(conn, like.like_props.object_link::<Id>().unwrap().into()).unwrap();
|
||||
impl Notify for Like {
|
||||
fn notify(&self, conn: &PgConnection) {
|
||||
let liker = User::get(conn, self.user_id).unwrap();
|
||||
let post = Post::get(conn, self.post_id).unwrap();
|
||||
for author in post.get_authors(conn) {
|
||||
let post = post.clone();
|
||||
Notification::insert(conn, NewNotification {
|
||||
|
|
113
src/models/mentions.rs
Normal file
113
src/models/mentions.rs
Normal file
|
@ -0,0 +1,113 @@
|
|||
use activitypub::link;
|
||||
use diesel::{self, PgConnection, QueryDsl, RunQueryDsl, ExpressionMethods};
|
||||
|
||||
use activity_pub::{Id, inbox::Notify};
|
||||
use models::{
|
||||
comments::Comment,
|
||||
notifications::*,
|
||||
posts::Post,
|
||||
users::User
|
||||
};
|
||||
use schema::mentions;
|
||||
|
||||
#[derive(Queryable, Identifiable)]
|
||||
pub struct Mention {
|
||||
pub id: i32,
|
||||
pub mentioned_id: i32,
|
||||
pub post_id: Option<i32>,
|
||||
pub comment_id: Option<i32>,
|
||||
pub ap_url: String
|
||||
}
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[table_name = "mentions"]
|
||||
pub struct NewMention {
|
||||
pub mentioned_id: i32,
|
||||
pub post_id: Option<i32>,
|
||||
pub comment_id: Option<i32>,
|
||||
pub ap_url: String
|
||||
}
|
||||
|
||||
impl Mention {
|
||||
insert!(mentions, NewMention);
|
||||
get!(mentions);
|
||||
find_by!(mentions, find_by_ap_url, ap_url as String);
|
||||
list_by!(mentions, list_for_user, mentioned_id as i32);
|
||||
list_by!(mentions, list_for_post, post_id as i32);
|
||||
|
||||
pub fn get_mentioned(&self, conn: &PgConnection) -> Option<User> {
|
||||
User::get(conn, self.mentioned_id)
|
||||
}
|
||||
|
||||
pub fn get_post(&self, conn: &PgConnection) -> Option<Post> {
|
||||
self.post_id.and_then(|id| Post::get(conn, id))
|
||||
}
|
||||
|
||||
pub fn get_comment(&self, conn: &PgConnection) -> Option<Comment> {
|
||||
self.post_id.and_then(|id| Comment::get(conn, id))
|
||||
}
|
||||
|
||||
pub fn build_activity(conn: &PgConnection, ment: String) -> link::Mention {
|
||||
let user = User::find_by_fqn(conn, ment.clone());
|
||||
println!("building act : {} -> {:?}", ment, user);
|
||||
let mut mention = link::Mention::default();
|
||||
mention.link_props.set_href_string(user.clone().map(|u| u.ap_url).unwrap_or(String::new())).expect("Error setting mention's href");
|
||||
mention.link_props.set_name_string(format!("@{}", ment)).expect("Error setting mention's name");
|
||||
mention
|
||||
}
|
||||
|
||||
pub fn to_activity(&self, conn: &PgConnection) -> link::Mention {
|
||||
let user = self.get_mentioned(conn);
|
||||
let mut mention = link::Mention::default();
|
||||
mention.link_props.set_href_string(user.clone().map(|u| u.ap_url).unwrap_or(String::new())).expect("Error setting mention's href");
|
||||
mention.link_props.set_name_string(user.map(|u| format!("@{}", u.get_fqn(conn))).unwrap_or(String::new())).expect("Error setting mention's name");
|
||||
mention
|
||||
}
|
||||
|
||||
pub fn from_activity(conn: &PgConnection, ment: link::Mention, inside: Id) -> Option<Self> {
|
||||
let ap_url = ment.link_props.href_string().unwrap();
|
||||
let mentioned = User::find_by_ap_url(conn, ap_url).unwrap();
|
||||
|
||||
if let Some(post) = Post::find_by_ap_url(conn, inside.clone().into()) {
|
||||
let res = Mention::insert(conn, NewMention {
|
||||
mentioned_id: mentioned.id,
|
||||
post_id: Some(post.id),
|
||||
comment_id: None,
|
||||
ap_url: ment.link_props.href_string().unwrap_or(String::new())
|
||||
});
|
||||
res.notify(conn);
|
||||
Some(res)
|
||||
} else {
|
||||
if let Some(comment) = Comment::find_by_ap_url(conn, inside.into()) {
|
||||
let res = Mention::insert(conn, NewMention {
|
||||
mentioned_id: mentioned.id,
|
||||
post_id: None,
|
||||
comment_id: Some(comment.id),
|
||||
ap_url: ment.link_props.href_string().unwrap_or(String::new())
|
||||
});
|
||||
res.notify(conn);
|
||||
Some(res)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Notify for Mention {
|
||||
fn notify(&self, conn: &PgConnection) {
|
||||
let author = self.get_comment(conn)
|
||||
.map(|c| c.get_author(conn).display_name.clone())
|
||||
.unwrap_or(self.get_post(conn).unwrap().get_authors(conn)[0].display_name.clone());
|
||||
|
||||
self.get_mentioned(conn).map(|m| {
|
||||
Notification::insert(conn, NewNotification {
|
||||
title: "{{ data }} mentioned you.".to_string(),
|
||||
data: Some(author),
|
||||
content: None,
|
||||
link: Some(self.get_post(conn).map(|p| p.ap_url).unwrap_or_else(|| self.get_comment(conn).unwrap().ap_url.unwrap_or(String::new()))),
|
||||
user_id: m.id
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -12,6 +12,18 @@ macro_rules! find_by {
|
|||
};
|
||||
}
|
||||
|
||||
macro_rules! list_by {
|
||||
($table:ident, $fn:ident, $($col:ident as $type:ident),+) => {
|
||||
/// Try to find a $table with a given $col
|
||||
pub fn $fn(conn: &PgConnection, $($col: $type),+) -> Vec<Self> {
|
||||
$table::table
|
||||
$(.filter($table::$col.eq($col)))+
|
||||
.load::<Self>(conn)
|
||||
.expect("Error loading $table by $col")
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! get {
|
||||
($table:ident) => {
|
||||
pub fn get(conn: &PgConnection, id: i32) -> Option<Self> {
|
||||
|
@ -41,6 +53,7 @@ pub mod comments;
|
|||
pub mod follows;
|
||||
pub mod instance;
|
||||
pub mod likes;
|
||||
pub mod mentions;
|
||||
pub mod notifications;
|
||||
pub mod post_authors;
|
||||
pub mod posts;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use activitypub::{
|
||||
activity::Create,
|
||||
link,
|
||||
object::{Article, properties::ObjectProperties}
|
||||
};
|
||||
use chrono::NaiveDateTime;
|
||||
|
@ -9,13 +10,13 @@ use serde_json;
|
|||
use BASE_URL;
|
||||
use activity_pub::{
|
||||
PUBLIC_VISIBILTY, ap_url, Id, IntoId,
|
||||
actor::Actor,
|
||||
inbox::FromActivity
|
||||
};
|
||||
use models::{
|
||||
blogs::Blog,
|
||||
instance::Instance,
|
||||
likes::Like,
|
||||
mentions::Mention,
|
||||
post_authors::PostAuthor,
|
||||
reshares::Reshare,
|
||||
users::User
|
||||
|
@ -144,6 +145,8 @@ impl Post {
|
|||
let mut to = self.get_receivers_urls(conn);
|
||||
to.push(PUBLIC_VISIBILTY.to_string());
|
||||
|
||||
let mentions = Mention::list_for_post(conn, self.id).into_iter().map(|m| m.to_activity(conn)).collect::<Vec<link::Mention>>();
|
||||
|
||||
let mut article = Article::default();
|
||||
article.object_props = ObjectProperties {
|
||||
name: Some(serde_json::to_value(self.title.clone()).unwrap()),
|
||||
|
@ -151,11 +154,11 @@ impl Post {
|
|||
attributed_to: Some(serde_json::to_value(self.get_authors(conn).into_iter().map(|x| x.ap_url).collect::<Vec<String>>()).unwrap()),
|
||||
content: Some(serde_json::to_value(self.content.clone()).unwrap()),
|
||||
published: Some(serde_json::to_value(self.creation_date).unwrap()),
|
||||
tag: Some(serde_json::to_value(Vec::<serde_json::Value>::new()).unwrap()),
|
||||
tag: Some(serde_json::to_value(mentions).unwrap()),
|
||||
url: Some(serde_json::to_value(self.compute_id(conn)).unwrap()),
|
||||
to: Some(serde_json::to_value(to).unwrap()),
|
||||
cc: Some(serde_json::to_value(Vec::<serde_json::Value>::new()).unwrap()),
|
||||
..ObjectProperties::default()
|
||||
..ObjectProperties::default()
|
||||
};
|
||||
article
|
||||
}
|
||||
|
@ -184,6 +187,15 @@ impl Post {
|
|||
|
||||
impl FromActivity<Article> for Post {
|
||||
fn from_activity(conn: &PgConnection, article: Article, _actor: Id) -> Post {
|
||||
// save mentions
|
||||
if let Some(serde_json::Value::Array(tags)) = article.object_props.tag.clone() {
|
||||
for tag in tags.into_iter() {
|
||||
serde_json::from_value::<link::Mention>(tag)
|
||||
.map(|m| Mention::from_activity(conn, m, Id::new(article.clone().object_props.clone().url_string().unwrap_or(String::from("")))))
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
|
||||
Post::insert(conn, NewPost {
|
||||
blog_id: 0, // TODO
|
||||
slug: String::from(""), // TODO
|
||||
|
|
|
@ -73,7 +73,7 @@ impl Reshare {
|
|||
}
|
||||
|
||||
impl FromActivity<Announce> for Reshare {
|
||||
fn from_activity(conn: &PgConnection, announce: Announce, actor: Id) -> Reshare {
|
||||
fn from_activity(conn: &PgConnection, announce: Announce, _actor: Id) -> Reshare {
|
||||
let user = User::from_url(conn, announce.announce_props.actor.as_str().unwrap().to_string());
|
||||
let post = Post::find_by_ap_url(conn, announce.announce_props.object.as_str().unwrap().to_string());
|
||||
let reshare = Reshare::insert(conn, NewReshare {
|
||||
|
@ -81,15 +81,15 @@ impl FromActivity<Announce> for Reshare {
|
|||
user_id: user.unwrap().id,
|
||||
ap_url: announce.object_props.id_string().unwrap_or(String::from(""))
|
||||
});
|
||||
Reshare::notify(conn, announce, actor);
|
||||
reshare.notify(conn);
|
||||
reshare
|
||||
}
|
||||
}
|
||||
|
||||
impl Notify<Announce> for Reshare {
|
||||
fn notify(conn: &PgConnection, announce: Announce, actor: Id) {
|
||||
let actor = User::from_url(conn, actor.into()).unwrap();
|
||||
let post = Post::find_by_ap_url(conn, announce.announce_props.object_link::<Id>().unwrap().into()).unwrap();
|
||||
impl Notify for Reshare {
|
||||
fn notify(&self, conn: &PgConnection) {
|
||||
let actor = User::get(conn, self.user_id).unwrap();
|
||||
let post = self.get_post(conn).unwrap();
|
||||
for author in post.get_authors(conn) {
|
||||
let post = post.clone();
|
||||
Notification::insert(conn, NewNotification {
|
||||
|
|
|
@ -47,7 +47,7 @@ use safe_string::SafeString;
|
|||
|
||||
pub const AUTH_COOKIE: &'static str = "user_id";
|
||||
|
||||
#[derive(Queryable, Identifiable, Serialize, Deserialize, Clone)]
|
||||
#[derive(Queryable, Identifiable, Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct User {
|
||||
pub id: i32,
|
||||
pub username: String,
|
||||
|
@ -89,7 +89,7 @@ impl User {
|
|||
get!(users);
|
||||
find_by!(users, find_by_email, email as String);
|
||||
find_by!(users, find_by_name, username as String, instance_id as i32);
|
||||
|
||||
find_by!(users, find_by_ap_url, ap_url as String);
|
||||
|
||||
pub fn grant_admin_rights(&self, conn: &PgConnection) {
|
||||
diesel::update(self)
|
||||
|
@ -419,23 +419,15 @@ impl APActor for User {
|
|||
}
|
||||
|
||||
fn from_url(conn: &PgConnection, url: String) -> Option<User> {
|
||||
let in_db = users::table.filter(users::ap_url.eq(url.clone()))
|
||||
.limit(1)
|
||||
.load::<User>(conn)
|
||||
.expect("Error loading user by AP url")
|
||||
.into_iter().nth(0);
|
||||
match in_db {
|
||||
Some(u) => Some(u),
|
||||
None => {
|
||||
// The requested user was not in the DB
|
||||
// We try to fetch it if it is remote
|
||||
if Url::parse(url.as_ref()).unwrap().host_str().unwrap() != BASE_URL.as_str() {
|
||||
Some(User::fetch_from_url(conn, url).unwrap())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
User::find_by_ap_url(conn, url.clone()).or_else(|| {
|
||||
// The requested user was not in the DB
|
||||
// We try to fetch it if it is remote
|
||||
if Url::parse(url.as_ref()).unwrap().host_str().unwrap() != BASE_URL.as_str() {
|
||||
Some(User::fetch_from_url(conn, url).unwrap())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use rocket::{
|
|||
};
|
||||
use rocket_contrib::Template;
|
||||
|
||||
use activity_pub::{broadcast, IntoId, inbox::Notify};
|
||||
use activity_pub::{broadcast, inbox::Notify};
|
||||
use db_conn::DbConn;
|
||||
use models::{
|
||||
blogs::Blog,
|
||||
|
@ -53,12 +53,12 @@ fn create(blog_name: String, slug: String, query: CommentQuery, data: Form<NewCo
|
|||
in_response_to_id: query.responding_to,
|
||||
post_id: post.id,
|
||||
author_id: user.id,
|
||||
ap_url: None,
|
||||
ap_url: None, // TODO: set it
|
||||
sensitive: false,
|
||||
spoiler_text: "".to_string()
|
||||
});
|
||||
comment.notify(&*conn);
|
||||
|
||||
Comment::notify(&*conn, comment.into_activity(&*conn), user.clone().into_id());
|
||||
broadcast(&*conn, &user, comment.create_activity(&*conn), user.get_followers(&*conn));
|
||||
|
||||
Redirect::to(format!("/~/{}/{}/#comment-{}", blog_name, slug, comment.id))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use rocket::response::{Redirect, Flash};
|
||||
|
||||
use activity_pub::{broadcast, IntoId, inbox::Notify};
|
||||
use activity_pub::{broadcast, inbox::Notify};
|
||||
use db_conn::DbConn;
|
||||
use models::{
|
||||
blogs::Blog,
|
||||
|
@ -23,8 +23,8 @@ fn create(blog: String, slug: String, user: User, conn: DbConn) -> Redirect {
|
|||
ap_url: "".to_string()
|
||||
});
|
||||
like.update_ap_url(&*conn);
|
||||
like.notify(&*conn);
|
||||
|
||||
likes::Like::notify(&*conn, like.into_activity(&*conn), user.clone().into_id());
|
||||
broadcast(&*conn, &user, like.into_activity(&*conn), user.get_followers(&*conn));
|
||||
} else {
|
||||
let like = likes::Like::find_by_user_on_post(&*conn, user.id, post.id).unwrap();
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
use comrak::{markdown_to_html, ComrakOptions};
|
||||
use heck::KebabCase;
|
||||
use rocket::request::Form;
|
||||
use rocket::response::{Redirect, Flash};
|
||||
use rocket_contrib::Template;
|
||||
use serde_json;
|
||||
|
||||
use activity_pub::{broadcast, context, activity_pub, ActivityPub};
|
||||
use activity_pub::{broadcast, context, activity_pub, ActivityPub, Id};
|
||||
use db_conn::DbConn;
|
||||
use models::{
|
||||
blogs::*,
|
||||
comments::Comment,
|
||||
mentions::Mention,
|
||||
post_authors::*,
|
||||
posts::*,
|
||||
users::User
|
||||
};
|
||||
use utils;
|
||||
use safe_string::SafeString;
|
||||
use utils;
|
||||
|
||||
#[get("/~/<blog>/<slug>", rank = 4)]
|
||||
fn details(blog: String, slug: String, conn: DbConn, user: Option<User>) -> Template {
|
||||
|
@ -88,19 +88,7 @@ fn create(blog_name: String, data: Form<NewPostForm>, user: User, conn: DbConn)
|
|||
if slug == "new" || Post::find_by_slug(&*conn, slug.clone(), blog.id).is_some() {
|
||||
Redirect::to(uri!(new: blog = blog_name))
|
||||
} else {
|
||||
let content = markdown_to_html(form.content.to_string().as_ref(), &ComrakOptions{
|
||||
smart: true,
|
||||
safe: true,
|
||||
ext_strikethrough: true,
|
||||
ext_tagfilter: true,
|
||||
ext_table: true,
|
||||
ext_autolink: true,
|
||||
ext_tasklist: true,
|
||||
ext_superscript: true,
|
||||
ext_header_ids: Some("title".to_string()),
|
||||
ext_footnotes: true,
|
||||
..ComrakOptions::default()
|
||||
});
|
||||
let (content, mentions) = utils::md_to_html(form.content.to_string().as_ref());
|
||||
|
||||
let post = Post::insert(&*conn, NewPost {
|
||||
blog_id: blog.id,
|
||||
|
@ -117,6 +105,10 @@ fn create(blog_name: String, data: Form<NewPostForm>, user: User, conn: DbConn)
|
|||
author_id: user.id
|
||||
});
|
||||
|
||||
for m in mentions.into_iter() {
|
||||
Mention::from_activity(&*conn, Mention::build_activity(&*conn, m), Id::new(post.compute_id(&*conn)));
|
||||
}
|
||||
|
||||
let act = post.create_activity(&*conn);
|
||||
broadcast(&*conn, &user, act, user.get_followers(&*conn));
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use rocket::response::{Redirect, Flash};
|
||||
|
||||
use activity_pub::{broadcast, IntoId, inbox::Notify};
|
||||
use activity_pub::{broadcast, inbox::Notify};
|
||||
use db_conn::DbConn;
|
||||
use models::{
|
||||
blogs::Blog,
|
||||
|
@ -23,8 +23,8 @@ fn create(blog: String, slug: String, user: User, conn: DbConn) -> Redirect {
|
|||
ap_url: "".to_string()
|
||||
});
|
||||
reshare.update_ap_url(&*conn);
|
||||
reshare.notify(&*conn);
|
||||
|
||||
Reshare::notify(&*conn, reshare.into_activity(&*conn), user.clone().into_id());
|
||||
broadcast(&*conn, &user, reshare.into_activity(&*conn), user.get_followers(&*conn));
|
||||
} else {
|
||||
let reshare = Reshare::find_by_user_on_post(&*conn, user.id, post.id).unwrap();
|
||||
|
|
|
@ -71,16 +71,17 @@ fn dashboard_auth() -> Flash<Redirect> {
|
|||
#[get("/@/<name>/follow")]
|
||||
fn follow(name: String, conn: DbConn, user: User) -> Redirect {
|
||||
let target = User::find_by_fqn(&*conn, name.clone()).unwrap();
|
||||
follows::Follow::insert(&*conn, follows::NewFollow {
|
||||
let f = follows::Follow::insert(&*conn, follows::NewFollow {
|
||||
follower_id: user.id,
|
||||
following_id: target.id
|
||||
});
|
||||
f.notify(&*conn);
|
||||
|
||||
let mut act = Follow::default();
|
||||
act.follow_props.set_actor_link::<Id>(user.clone().into_id()).unwrap();
|
||||
act.follow_props.set_object_object(user.into_activity(&*conn)).unwrap();
|
||||
act.object_props.set_id_string(format!("{}/follow/{}", user.ap_url, target.ap_url)).unwrap();
|
||||
|
||||
follows::Follow::notify(&*conn, act.clone(), user.clone().into_id());
|
||||
broadcast(&*conn, &user, act, vec![target]);
|
||||
Redirect::to(uri!(details: name = name))
|
||||
}
|
||||
|
|
|
@ -66,6 +66,16 @@ table! {
|
|||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
mentions (id) {
|
||||
id -> Int4,
|
||||
mentioned_id -> Int4,
|
||||
post_id -> Nullable<Int4>,
|
||||
comment_id -> Nullable<Int4>,
|
||||
ap_url -> Varchar,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
notifications (id) {
|
||||
id -> Int4,
|
||||
|
@ -137,6 +147,9 @@ joinable!(comments -> posts (post_id));
|
|||
joinable!(comments -> users (author_id));
|
||||
joinable!(likes -> posts (post_id));
|
||||
joinable!(likes -> users (user_id));
|
||||
joinable!(mentions -> comments (comment_id));
|
||||
joinable!(mentions -> posts (post_id));
|
||||
joinable!(mentions -> users (mentioned_id));
|
||||
joinable!(notifications -> users (user_id));
|
||||
joinable!(post_authors -> posts (post_id));
|
||||
joinable!(post_authors -> users (author_id));
|
||||
|
@ -152,6 +165,7 @@ allow_tables_to_appear_in_same_query!(
|
|||
follows,
|
||||
instances,
|
||||
likes,
|
||||
mentions,
|
||||
notifications,
|
||||
post_authors,
|
||||
posts,
|
||||
|
|
|
@ -12,7 +12,7 @@ use db_conn::DbConn;
|
|||
use models::instance::*;
|
||||
use models::users::*;
|
||||
|
||||
type PgPool = Pool<ConnectionManager<PgConnection>>;
|
||||
pub type PgPool = Pool<ConnectionManager<PgConnection>>;
|
||||
|
||||
/// Initializes a database pool.
|
||||
fn init_pool() -> Option<PgPool> {
|
||||
|
|
50
src/utils.rs
50
src/utils.rs
|
@ -1,5 +1,6 @@
|
|||
use gettextrs::gettext;
|
||||
use heck::CamelCase;
|
||||
use pulldown_cmark::{Event, Parser, Options, Tag, html};
|
||||
use rocket::{
|
||||
http::uri::Uri,
|
||||
response::{Redirect, Flash}
|
||||
|
@ -18,3 +19,52 @@ pub fn make_actor_id(name: String) -> String {
|
|||
pub fn requires_login(message: &str, url: Uri) -> Flash<Redirect> {
|
||||
Flash::new(Redirect::to(Uri::new(format!("/login?m={}", gettext(message.to_string())))), "callback", url.as_str())
|
||||
}
|
||||
|
||||
/// Returns (HTML, mentions)
|
||||
pub fn md_to_html(md: &str) -> (String, Vec<String>) {
|
||||
let parser = Parser::new_ext(md, Options::all());
|
||||
|
||||
let (parser, mentions): (Vec<Vec<Event>>, Vec<Vec<String>>) = parser.map(|evt| match evt {
|
||||
Event::Text(txt) => {
|
||||
let (evts, _, _, _, new_mentions) = txt.chars().fold((vec![], false, String::new(), 0, vec![]), |(mut events, in_mention, text_acc, n, mut mentions), c| {
|
||||
if in_mention {
|
||||
if (c.is_alphanumeric() || c == '@' || c == '.' || c == '-' || c == '_') && (n < (txt.chars().count() - 1)) {
|
||||
(events, in_mention, text_acc + c.to_string().as_ref(), n + 1, mentions)
|
||||
} else {
|
||||
let mention = text_acc + c.to_string().as_ref();
|
||||
let short_mention = mention.clone();
|
||||
let short_mention = short_mention.splitn(1, '@').nth(0).unwrap_or("");
|
||||
let link = Tag::Link(format!("/@/{}/", mention).into(), short_mention.to_string().into());
|
||||
|
||||
mentions.push(mention);
|
||||
events.push(Event::Start(link.clone()));
|
||||
events.push(Event::Text(format!("@{}", short_mention).into()));
|
||||
events.push(Event::End(link));
|
||||
|
||||
(events, false, c.to_string(), n + 1, mentions)
|
||||
}
|
||||
} else {
|
||||
if c == '@' {
|
||||
events.push(Event::Text(text_acc.into()));
|
||||
(events, true, String::new(), n + 1, mentions)
|
||||
} else {
|
||||
if n >= (txt.chars().count() - 1) { // Add the text after at the end, even if it is not followed by a mention.
|
||||
events.push(Event::Text((text_acc.clone() + c.to_string().as_ref()).into()))
|
||||
}
|
||||
(events, in_mention, text_acc + c.to_string().as_ref(), n + 1, mentions)
|
||||
}
|
||||
}
|
||||
});
|
||||
(evts, new_mentions)
|
||||
},
|
||||
_ => (vec![evt], vec![])
|
||||
}).unzip();
|
||||
let parser = parser.into_iter().flatten();
|
||||
let mentions = mentions.into_iter().flatten().map(|m| String::from(m.trim()));
|
||||
|
||||
// TODO: fetch mentionned profiles in background, if needed
|
||||
|
||||
let mut buf = String::new();
|
||||
html::push_html(&mut buf, parser);
|
||||
(buf, mentions.collect())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue