Federated mentions. Fixes #681 (#717)

* Federated mentions. Fixes #681

* Changing some todos, adding comments.
This commit is contained in:
Dessalines 2020-05-15 12:36:11 -04:00 committed by GitHub
parent 3a4973ad68
commit 940dc73f28
19 changed files with 660 additions and 452 deletions

352
server/Cargo.lock generated vendored
View file

@ -2,24 +2,24 @@
# It is not intended for manual editing.
[[package]]
name = "activitystreams"
version = "0.6.0"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd5b29a0f2c64cc56f2b79ec29cab68a9dab3b714d811a55668d072f18a8638e"
checksum = "edf0082191df1d6d39577b28b5daa7b8318b812038d0f7a83f05331f17580934"
dependencies = [
"activitystreams-derive",
"chrono",
"mime",
"serde 1.0.106",
"serde_json 1.0.51",
"serde 1.0.110",
"serde_json 1.0.53",
"thiserror",
"url",
]
[[package]]
name = "activitystreams-derive"
version = "0.6.0"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "985d3ca1ee226e83f4118e0235bc11d9fce39c4eec8d53739a21b01dd0b3f30f"
checksum = "c39ba5929399e9f921055bac76dd8f47419fa5b6b6da1ac4c1e82b94ed0ac7b4"
dependencies = [
"proc-macro2",
"quote",
@ -144,8 +144,8 @@ dependencies = [
"pin-project",
"rand 0.7.3",
"regex 1.3.7",
"serde 1.0.106",
"serde_json 1.0.51",
"serde 1.0.110",
"serde_json 1.0.53",
"serde_urlencoded",
"sha1",
"slab",
@ -172,20 +172,21 @@ dependencies = [
"http",
"log",
"regex 1.3.7",
"serde 1.0.106",
"serde 1.0.110",
]
[[package]]
name = "actix-rt"
version = "1.1.0"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20066d9200ef8d441ac156c76dd36c3f1e9a15976c34e69ae97f7f570b331882"
checksum = "143fcc2912e0d1de2bcf4e2f720d2a60c28652ab4179685a1ee159e0fb3db227"
dependencies = [
"actix-macros",
"actix-threadpool",
"copyless",
"futures-channel",
"futures-util",
"smallvec",
"tokio",
]
@ -311,8 +312,8 @@ dependencies = [
"net2",
"pin-project",
"regex 1.3.7",
"serde 1.0.106",
"serde_json 1.0.51",
"serde 1.0.110",
"serde_json 1.0.53",
"serde_urlencoded",
"time",
"url",
@ -355,6 +356,15 @@ dependencies = [
"syn",
]
[[package]]
name = "addr2line"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "456d75cbb82da1ad150c8a9d97285ffcd21c9931dcb11e995903e7d75141b38b"
dependencies = [
"gimli",
]
[[package]]
name = "adler32"
version = "1.0.4"
@ -411,9 +421,9 @@ checksum = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a"
[[package]]
name = "async-trait"
version = "0.1.30"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da71fef07bc806586090247e971229289f64c210a278ee5ae419314eb386b31d"
checksum = "26c4f3195085c36ea8d24d32b2f828d23296a9370a28aa39d111f6f16bef9f3b"
dependencies = [
"proc-macro2",
"quote",
@ -461,33 +471,24 @@ dependencies = [
"mime",
"percent-encoding",
"rand 0.7.3",
"serde 1.0.106",
"serde_json 1.0.51",
"serde 1.0.110",
"serde_json 1.0.53",
"serde_urlencoded",
]
[[package]]
name = "backtrace"
version = "0.3.46"
version = "0.3.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e"
checksum = "0df2f85c8a2abbe3b7d7e748052fdd9b76a0458fdeb16ad4223f5eca78c7c130"
dependencies = [
"backtrace-sys",
"addr2line",
"cfg-if",
"libc",
"object",
"rustc-demangle",
]
[[package]]
name = "backtrace-sys"
version = "0.1.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78848718ee1255a2485d1309ad9cdecfc2e7d0362dd11c6829364c6b35ae1bc7"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "base64"
version = "0.9.3"
@ -515,21 +516,20 @@ checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
[[package]]
name = "base64"
version = "0.12.0"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d5ca2cd0adc3f48f9e9ea5a6bbdf9ccc0bfade884847e484d452414c7ccffb3"
checksum = "53d1ccbaf7d9ec9537465a97bf19edc1a4e158ecb49fc16178202238c569cc42"
[[package]]
name = "bcrypt"
version = "0.6.3"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f055c8591efe08e03f534ee632672ea3643c3932e485f422107ec6cc1157b0ea"
checksum = "41b70db86f3c560199b0dada79a22b9a924622384abb2a756a9707ffcce077f2"
dependencies = [
"base64 0.12.0",
"base64 0.12.1",
"blowfish",
"byteorder",
"lazy_static 1.4.0",
"rand 0.7.3",
"getrandom",
]
[[package]]
@ -607,9 +607,9 @@ checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8"
[[package]]
name = "bumpalo"
version = "3.2.1"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187"
checksum = "5356f1d23ee24a1f785a56d1d1a5f0fd5b0f6a0c0fb2412ce11da71649ab78f6"
[[package]]
name = "byte-tools"
@ -640,9 +640,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.0.52"
version = "1.0.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d87b23d6a92cd03af510a5ade527033f6aa6fa92161e2d5863a907d4c5e31d"
checksum = "404b1fe4f65288577753b17e3b36a04596ee784493ec249bf81c7f2d2acd751c"
[[package]]
name = "cfg-if"
@ -658,15 +658,15 @@ checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
dependencies = [
"num-integer",
"num-traits 0.2.11",
"serde 1.0.106",
"serde 1.0.110",
"time",
]
[[package]]
name = "clap"
version = "2.33.0"
version = "2.33.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
checksum = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129"
dependencies = [
"ansi_term",
"atty",
@ -712,9 +712,9 @@ dependencies = [
"lazy_static 1.4.0",
"nom 5.1.1",
"rust-ini",
"serde 1.0.106",
"serde 1.0.110",
"serde-hjson 0.9.1",
"serde_json 1.0.51",
"serde_json 1.0.53",
"toml",
"yaml-rust",
]
@ -773,9 +773,9 @@ dependencies = [
[[package]]
name = "curl"
version = "0.4.28"
version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eda1c0c03cacf3365d84818a40293f0e3f3953db8759c9c565a3b434edf0b52e"
checksum = "762e34611d2d5233a506a79072be944fddd057db2f18e04c0d6fa79e3fd466fd"
dependencies = [
"curl-sys",
"libc",
@ -788,9 +788,9 @@ dependencies = [
[[package]]
name = "curl-sys"
version = "0.4.30+curl-7.69.1"
version = "0.4.31+curl-7.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "923b38e423a8f47a4058e96f2a1fa2865a6231097ee860debd678d244277d50c"
checksum = "dcd62757cc4f5ab9404bc6ca9f0ae447e729a1403948ce5106bd588ceac6a3b0"
dependencies = [
"cc",
"libc",
@ -864,9 +864,9 @@ dependencies = [
[[package]]
name = "derive_more"
version = "0.99.5"
version = "0.99.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2323f3f47db9a0e77ce7a300605d8d2098597fc451ed1a97bb1f6411bb550a7"
checksum = "46b046a346c374c6c3c84d2070bfe33904504686bdf949c2d8eb22edad3f270c"
dependencies = [
"proc-macro2",
"quote",
@ -885,7 +885,7 @@ dependencies = [
"diesel_derives",
"pq-sys",
"r2d2",
"serde_json 1.0.51",
"serde_json 1.0.53",
]
[[package]]
@ -1035,9 +1035,9 @@ checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
[[package]]
name = "encoding_rs"
version = "0.8.22"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28"
checksum = "e8ac63f94732332f44fe654443c46f6375d1939684c17b0afb6cb56b0456e171"
dependencies = [
"cfg-if",
]
@ -1075,9 +1075,9 @@ dependencies = [
[[package]]
name = "failure"
version = "0.1.7"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8529c2421efa3066a5cbd8063d2244603824daccb6936b079010bb2aa89464b"
checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
dependencies = [
"backtrace",
"failure_derive",
@ -1085,9 +1085,9 @@ dependencies = [
[[package]]
name = "failure_derive"
version = "0.1.7"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231"
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
dependencies = [
"proc-macro2",
"quote",
@ -1124,9 +1124,9 @@ dependencies = [
[[package]]
name = "fnv"
version = "1.0.6"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foreign-types"
@ -1167,9 +1167,9 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
[[package]]
name = "futures"
version = "0.3.4"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c329ae8753502fb44ae4fc2b622fa2a94652c41e795143765ba0927f92ab780"
checksum = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613"
dependencies = [
"futures-channel",
"futures-core",
@ -1182,9 +1182,9 @@ dependencies = [
[[package]]
name = "futures-channel"
version = "0.3.4"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8"
checksum = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5"
dependencies = [
"futures-core",
"futures-sink",
@ -1192,15 +1192,15 @@ dependencies = [
[[package]]
name = "futures-core"
version = "0.3.4"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a"
checksum = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399"
[[package]]
name = "futures-executor"
version = "0.3.4"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f674f3e1bcb15b37284a90cedf55afdba482ab061c407a9c0ebbd0f3109741ba"
checksum = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314"
dependencies = [
"futures-core",
"futures-task",
@ -1209,15 +1209,15 @@ dependencies = [
[[package]]
name = "futures-io"
version = "0.3.4"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6"
checksum = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789"
[[package]]
name = "futures-macro"
version = "0.3.4"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7"
checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39"
dependencies = [
"proc-macro-hack",
"proc-macro2",
@ -1227,21 +1227,24 @@ dependencies = [
[[package]]
name = "futures-sink"
version = "0.3.4"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3466821b4bc114d95b087b850a724c6f83115e929bc88f1fa98a3304a944c8a6"
checksum = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc"
[[package]]
name = "futures-task"
version = "0.3.4"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27"
checksum = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626"
dependencies = [
"once_cell",
]
[[package]]
name = "futures-util"
version = "0.3.4"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5"
checksum = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6"
dependencies = [
"futures-channel",
"futures-core",
@ -1250,6 +1253,7 @@ dependencies = [
"futures-sink",
"futures-task",
"memchr 2.3.3",
"pin-project",
"pin-utils",
"proc-macro-hack",
"proc-macro-nested",
@ -1286,10 +1290,16 @@ dependencies = [
]
[[package]]
name = "h2"
version = "0.2.4"
name = "gimli"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "377038bf3c89d18d6ca1431e7a5027194fbd724ca10592b9487ede5e8e144f42"
checksum = "bcc8e0c9bce37868955864dbecd2b1ab2bdf967e6f28066d65aaac620444b65c"
[[package]]
name = "h2"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79b7246d7e4b979c03fa093da39cfb3617a96bbeee6310af63991668d7e843ff"
dependencies = [
"bytes",
"fnv",
@ -1374,9 +1384,9 @@ dependencies = [
[[package]]
name = "http-signature-normalization"
version = "0.4.2"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fde6b0321d465ea2cdc18b5d5ec73eee2ff20177ecee126cd8dd997f6c49e088"
checksum = "648233553603e7bb55bc1ea08a514661e212c09c10f6434507894273d8b5e773"
dependencies = [
"chrono",
"thiserror",
@ -1434,9 +1444,9 @@ dependencies = [
[[package]]
name = "ipconfig"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa79fa216fbe60834a9c0737d7fcd30425b32d1c58854663e24d4c4b328ed83f"
checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7"
dependencies = [
"socket2",
"widestring",
@ -1446,9 +1456,9 @@ dependencies = [
[[package]]
name = "isahc"
version = "0.9.1"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50bdb3bdcbf6d534daaad1a686eda0d0dc1946818fa71e3edd3124d001adfdc2"
checksum = "ee16417863ac2b4869ac774af7ef0322b08c53d952665edc5749ccaa37d68588"
dependencies = [
"bytes",
"crossbeam-channel",
@ -1490,9 +1500,9 @@ checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
[[package]]
name = "js-sys"
version = "0.3.37"
version = "0.3.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a27d435371a2fa5b6d2b028a74bbdb1234f308da363226a2854ca3ff8ba7055"
checksum = "fa5a448de267e7358beaf4a5d849518fe9a0c13fce7afd44b06e68550e5562a7"
dependencies = [
"wasm-bindgen",
]
@ -1506,8 +1516,8 @@ dependencies = [
"base64 0.11.0",
"pem",
"ring",
"serde 1.0.106",
"serde_json 1.0.51",
"serde 1.0.110",
"serde_json 1.0.53",
"simple_asn1",
]
@ -1549,7 +1559,7 @@ dependencies = [
"actix-rt",
"actix-web",
"actix-web-actors",
"base64 0.12.0",
"base64 0.12.1",
"bcrypt",
"chrono",
"comrak",
@ -1576,8 +1586,8 @@ dependencies = [
"rand 0.7.3",
"regex 1.3.7",
"rss",
"serde 1.0.106",
"serde_json 1.0.51",
"serde 1.0.110",
"serde_json 1.0.53",
"sha2",
"strum",
"strum_macros",
@ -1599,9 +1609,9 @@ dependencies = [
"log",
"native-tls",
"nom 4.2.3",
"serde 1.0.106",
"serde 1.0.110",
"serde_derive",
"serde_json 1.0.51",
"serde_json 1.0.53",
]
[[package]]
@ -1633,9 +1643,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.69"
version = "0.2.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005"
checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f"
[[package]]
name = "libnghttp2-sys"
@ -1671,9 +1681,9 @@ dependencies = [
[[package]]
name = "linked-hash-map"
version = "0.5.2"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
[[package]]
name = "lock_api"
@ -1699,7 +1709,7 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
dependencies = [
"linked-hash-map 0.5.2",
"linked-hash-map 0.5.3",
]
[[package]]
@ -1789,9 +1799,9 @@ dependencies = [
[[package]]
name = "mio"
version = "0.6.21"
version = "0.6.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f"
checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430"
dependencies = [
"cfg-if",
"fuchsia-zircon",
@ -1808,9 +1818,9 @@ dependencies = [
[[package]]
name = "mio-uds"
version = "0.6.7"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125"
checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0"
dependencies = [
"iovec",
"libc",
@ -1849,9 +1859,9 @@ dependencies = [
[[package]]
name = "net2"
version = "0.2.33"
version = "0.2.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7"
dependencies = [
"cfg-if",
"libc",
@ -1934,6 +1944,18 @@ dependencies = [
"libc",
]
[[package]]
name = "object"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2"
[[package]]
name = "once_cell"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d"
[[package]]
name = "opaque-debug"
version = "0.2.3"
@ -1962,9 +1984,9 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
[[package]]
name = "openssl-sys"
version = "0.9.55"
version = "0.9.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7717097d810a0f2e2323f9e5d11e71608355e24828410b55b9d4f18aa5f9a5d8"
checksum = "f02309a7f127000ed50594f0b50ecc69e7c654e16d41b4e8156d1b3df8e0b52e"
dependencies = [
"autocfg 1.0.0",
"cc",
@ -2059,18 +2081,18 @@ dependencies = [
[[package]]
name = "pin-project"
version = "0.4.9"
version = "0.4.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f6a7f5eee6292c559c793430c55c00aea9d3b3d1905e855806ca4d7253426a2"
checksum = "81d480cb4e89522ccda96d0eed9af94180b7a5f93fb28f66e1fd7d68431663d1"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "0.4.9"
version = "0.4.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8988430ce790d8682672117bc06dda364c0be32d3abd738234f19f3240bad99a"
checksum = "a82996f11efccb19b685b14b5df818de31c1edcee3daa256ab5775dd98e72feb"
dependencies = [
"proc-macro2",
"quote",
@ -2079,9 +2101,9 @@ dependencies = [
[[package]]
name = "pin-project-lite"
version = "0.1.4"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae"
checksum = "f7505eeebd78492e0f6108f7171c4948dbb120ee8119d9d77d0afa5469bef67f"
[[package]]
name = "pin-utils"
@ -2124,9 +2146,9 @@ checksum = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694"
[[package]]
name = "proc-macro2"
version = "1.0.10"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3"
checksum = "8872cf6f48eee44265156c111456a700ab3483686b3f96df4cf5481c89157319"
dependencies = [
"unicode-xid",
]
@ -2149,9 +2171,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.3"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
checksum = "42934bc9c8ab0d3b273a16d8551c8f0fcff46be73276ca083ec2414c15c4ba5e"
dependencies = [
"proc-macro2",
]
@ -2400,13 +2422,13 @@ dependencies = [
[[package]]
name = "ring"
version = "0.16.12"
version = "0.16.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ba5a8ec64ee89a76c98c549af81ff14813df09c3e6dc4766c3856da48597a0c"
checksum = "703516ae74571f24b465b4a1431e81e2ad51336cb0ded733a55a1aa3eccac196"
dependencies = [
"cc",
"lazy_static 1.4.0",
"libc",
"once_cell",
"spin",
"untrusted",
"web-sys",
@ -2464,9 +2486,9 @@ checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
[[package]]
name = "schannel"
version = "0.1.18"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "039c25b130bd8c1321ee2d7de7fde2659fa9c2744e4bb29711cfc852ea53cd19"
checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
dependencies = [
"lazy_static 1.4.0",
"winapi 0.3.8",
@ -2489,9 +2511,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "security-framework"
version = "0.4.3"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f331b9025654145cd425b9ded0caf8f5ae0df80d418b326e2dc1c3dc5eb0620"
checksum = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535"
dependencies = [
"bitflags",
"core-foundation",
@ -2533,9 +2555,9 @@ checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8"
[[package]]
name = "serde"
version = "1.0.106"
version = "1.0.110"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399"
checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c"
dependencies = [
"serde_derive",
]
@ -2568,9 +2590,9 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.106"
version = "1.0.110"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c"
checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984"
dependencies = [
"proc-macro2",
"quote",
@ -2591,14 +2613,14 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.51"
version = "1.0.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da07b57ee2623368351e9a0488bb0b261322a15a6e0ae53e243cbdc0f4208da9"
checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2"
dependencies = [
"indexmap",
"itoa 0.4.5",
"ryu",
"serde 1.0.106",
"serde 1.0.110",
]
[[package]]
@ -2618,7 +2640,7 @@ checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97"
dependencies = [
"dtoa 0.4.5",
"itoa 0.4.5",
"serde 1.0.106",
"serde 1.0.110",
"url",
]
@ -2759,9 +2781,9 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.18"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213"
checksum = "4696caa4048ac7ce2bcd2e484b3cef88c1004e41b8e945a277e2c25dc0b72060"
dependencies = [
"proc-macro2",
"quote",
@ -2814,18 +2836,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.16"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d12a1dae4add0f0d568eebc7bf142f145ba1aa2544cafb195c76f0f409091b60"
checksum = "467e5ff447618a916519a4e0d62772ab14f434897f3d63f05d8700ef1e9b22c1"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.16"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f34e0c1caaa462fd840ec6b768946ea1e7842620d94fe29d5b847138f521269"
checksum = "e63c1091225b9834089b429bc4a2e01223470e3183e891582909e9d1c4cb55d9"
dependencies = [
"proc-macro2",
"quote",
@ -2862,9 +2884,9 @@ dependencies = [
[[package]]
name = "threadpool"
version = "1.8.0"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8dae184447c15d5a6916d973c642aec485105a13cd238192a6927ae3e077d66"
checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
dependencies = [
"num_cpus",
]
@ -2881,9 +2903,9 @@ dependencies = [
[[package]]
name = "tokio"
version = "0.2.19"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d9c43f1bb96970e153bcbae39a65e249ccb942bd9d36dbdf086024920417c9c"
checksum = "d099fa27b9702bed751524694adbe393e18b36b204da91eb1cbbbbb4a5ee2d58"
dependencies = [
"bytes",
"fnv",
@ -2934,7 +2956,7 @@ version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a"
dependencies = [
"serde 1.0.106",
"serde 1.0.110",
]
[[package]]
@ -3063,9 +3085,9 @@ checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
[[package]]
name = "untrusted"
version = "0.7.0"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "url"
@ -3076,7 +3098,7 @@ dependencies = [
"idna",
"matches",
"percent-encoding",
"serde 1.0.106",
"serde 1.0.110",
]
[[package]]
@ -3101,7 +3123,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11"
dependencies = [
"rand 0.7.3",
"serde 1.0.106",
"serde 1.0.110",
]
[[package]]
@ -3143,9 +3165,9 @@ checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168"
[[package]]
name = "vec_map"
version = "0.8.1"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
@ -3167,9 +3189,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
[[package]]
name = "wasm-bindgen"
version = "0.2.60"
version = "0.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f"
checksum = "e3c7d40d09cdbf0f4895ae58cf57d92e1e57a9dd8ed2e8390514b54a47cc5551"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@ -3177,9 +3199,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.60"
version = "0.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d967d37bf6c16cca2973ca3af071d0a2523392e4a594548155d89a678f4237cd"
checksum = "c3972e137ebf830900db522d6c8fd74d1900dcfc733462e9a12e942b00b4ac94"
dependencies = [
"bumpalo",
"lazy_static 1.4.0",
@ -3192,9 +3214,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.60"
version = "0.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4"
checksum = "2cd85aa2c579e8892442954685f0d801f9129de24fa2136b2c6a539c76b65776"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -3202,9 +3224,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.60"
version = "0.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931"
checksum = "8eb197bd3a47553334907ffd2f16507b4f4f01bbec3ac921a7719e0decdfe72a"
dependencies = [
"proc-macro2",
"quote",
@ -3215,15 +3237,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.60"
version = "0.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639"
checksum = "a91c2916119c17a8e316507afaaa2dd94b47646048014bbdf6bef098c1bb58ad"
[[package]]
name = "web-sys"
version = "0.3.37"
version = "0.3.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d6f51648d8c56c366144378a33290049eafdd784071077f6fe37dae64c1c4cb"
checksum = "8bc359e5dd3b46cb9687a051d50a2fdd228e4ba7cf6fcf861a5365c3d671a642"
dependencies = [
"js-sys",
"wasm-bindgen",
@ -3312,5 +3334,5 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d"
dependencies = [
"linked-hash-map 0.5.2",
"linked-hash-map 0.5.3",
]

18
server/Cargo.toml vendored
View file

@ -8,17 +8,17 @@ edition = "2018"
diesel = { version = "1.4.4", features = ["postgres","chrono","r2d2","64-column-tables","serde_json"] }
diesel_migrations = "1.4.0"
dotenv = "0.15.0"
activitystreams = "0.6.0"
bcrypt = "0.6.2"
activitystreams = "0.6.1"
bcrypt = "0.8.0"
chrono = { version = "0.4.7", features = ["serde"] }
failure = "0.1.5"
failure = "0.1.8"
serde_json = { version = "1.0.48", features = ["preserve_order"]}
serde = { version = "1.0.105", features = ["derive"] }
actix = "0.9.0"
actix-web = "2.0.0"
actix-files = "0.2.1"
actix-web-actors = "2.0.0"
actix-rt = "1.0.0"
actix-rt = "1.1.1"
log = "0.4.0"
env_logger = "0.7.1"
rand = "0.7.3"
@ -36,13 +36,13 @@ config = "0.10.1"
hjson = "0.8.2"
url = { version = "2.1.1", features = ["serde"] }
percent-encoding = "2.1.0"
isahc = "0.9"
isahc = "0.9.2"
comrak = "0.7"
openssl = "0.10"
http = "0.2.1"
http-signature-normalization = "0.4.1"
base64 = "0.12.0"
tokio = "0.2.18"
futures = "0.3.4"
http-signature-normalization = "0.5.1"
base64 = "0.12.1"
tokio = "0.2.21"
futures = "0.3.5"
itertools = "0.9.0"
uuid = { version = "0.8", features = ["serde", "v4"] }

View file

@ -76,8 +76,6 @@ impl Perform for Oper<CreateComment> {
let user_id = claims.id;
let hostname = &format!("https://{}", Settings::get().hostname);
let conn = pool.get()?;
// Check for a community ban
@ -120,107 +118,9 @@ impl Perform for Oper<CreateComment> {
updated_comment.send_create(&user, &conn)?;
let mut recipient_ids = Vec::new();
// Scan the comment for user mentions, add those rows
let extracted_usernames = extract_usernames(&comment_form.content);
for username_mention in &extracted_usernames {
if let Ok(mention_user) = User_::read_from_name(&conn, username_mention) {
// You can't mention yourself
// At some point, make it so you can't tag the parent creator either
// This can cause two notifications, one for reply and the other for mention
if mention_user.id != user_id {
recipient_ids.push(mention_user.id);
let user_mention_form = UserMentionForm {
recipient_id: mention_user.id,
comment_id: inserted_comment.id,
read: None,
};
// Allow this to fail softly, since comment edits might re-update or replace it
// Let the uniqueness handle this fail
match UserMention::create(&conn, &user_mention_form) {
Ok(_mention) => (),
Err(_e) => error!("{}", &_e),
};
// Send an email to those users that have notifications on
if mention_user.send_notifications_to_email {
if let Some(mention_email) = mention_user.email {
let subject = &format!(
"{} - Mentioned by {}",
Settings::get().hostname,
claims.username
);
let html = &format!(
"<h1>User Mention</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
claims.username, comment_form.content, hostname
);
match send_email(subject, &mention_email, &mention_user.name, html) {
Ok(_o) => _o,
Err(e) => error!("{}", e),
};
}
}
}
}
}
// Send notifs to the parent commenter / poster
match data.parent_id {
Some(parent_id) => {
let parent_comment = Comment::read(&conn, parent_id)?;
if parent_comment.creator_id != user_id {
let parent_user = User_::read(&conn, parent_comment.creator_id)?;
recipient_ids.push(parent_user.id);
if parent_user.send_notifications_to_email {
if let Some(comment_reply_email) = parent_user.email {
let subject = &format!(
"{} - Reply from {}",
Settings::get().hostname,
claims.username
);
let html = &format!(
"<h1>Comment Reply</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
claims.username, comment_form.content, hostname
);
match send_email(subject, &comment_reply_email, &parent_user.name, html) {
Ok(_o) => _o,
Err(e) => error!("{}", e),
};
}
}
}
}
// Its a post
None => {
if post.creator_id != user_id {
let parent_user = User_::read(&conn, post.creator_id)?;
recipient_ids.push(parent_user.id);
if parent_user.send_notifications_to_email {
if let Some(post_reply_email) = parent_user.email {
let subject = &format!(
"{} - Reply from {}",
Settings::get().hostname,
claims.username
);
let html = &format!(
"<h1>Post Reply</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
claims.username, comment_form.content, hostname
);
match send_email(subject, &post_reply_email, &parent_user.name, html) {
Ok(_o) => _o,
Err(e) => error!("{}", e),
};
}
}
}
}
};
let mentions = scrape_text_for_mentions(&comment_form.content);
let recipient_ids = send_local_notifs(&conn, &mentions, &updated_comment, &user, &post);
// You like your own comment by default
let like_form = CommentLikeForm {
@ -353,53 +253,10 @@ impl Perform for Oper<EditComment> {
updated_comment.send_update(&user, &conn)?;
}
let mut recipient_ids = Vec::new();
// Scan the comment for user mentions, add those rows
let extracted_usernames = extract_usernames(&comment_form.content);
for username_mention in &extracted_usernames {
let mention_user = User_::read_from_name(&conn, username_mention);
if mention_user.is_ok() {
let mention_user_id = mention_user?.id;
// You can't mention yourself
// At some point, make it so you can't tag the parent creator either
// This can cause two notifications, one for reply and the other for mention
if mention_user_id != user_id {
recipient_ids.push(mention_user_id);
let user_mention_form = UserMentionForm {
recipient_id: mention_user_id,
comment_id: data.edit_id,
read: None,
};
// Allow this to fail softly, since comment edits might re-update or replace it
// Let the uniqueness handle this fail
match UserMention::create(&conn, &user_mention_form) {
Ok(_mention) => (),
Err(_e) => error!("{}", &_e),
}
}
}
}
// Add to recipient ids
match data.parent_id {
Some(parent_id) => {
let parent_comment = Comment::read(&conn, parent_id)?;
if parent_comment.creator_id != user_id {
let parent_user = User_::read(&conn, parent_comment.creator_id)?;
recipient_ids.push(parent_user.id);
}
}
None => {
let post = Post::read(&conn, data.post_id)?;
recipient_ids.push(post.creator_id);
}
}
let mentions = scrape_text_for_mentions(&comment_form.content);
let recipient_ids = send_local_notifs(&conn, &mentions, &updated_comment, &user, &post);
// Mod tables
if let Some(removed) = data.removed.to_owned() {
@ -646,3 +503,106 @@ impl Perform for Oper<GetComments> {
Ok(GetCommentsResponse { comments })
}
}
pub fn send_local_notifs(
conn: &PgConnection,
mentions: &[MentionData],
comment: &Comment,
user: &User_,
post: &Post,
) -> Vec<i32> {
let mut recipient_ids = Vec::new();
let hostname = &format!("https://{}", Settings::get().hostname);
// Send the local mentions
for mention in mentions
.iter()
.filter(|m| m.is_local() && m.name.ne(&user.name))
.collect::<Vec<&MentionData>>()
{
if let Ok(mention_user) = User_::read_from_name(&conn, &mention.name) {
// TODO
// At some point, make it so you can't tag the parent creator either
// This can cause two notifications, one for reply and the other for mention
recipient_ids.push(mention_user.id);
let user_mention_form = UserMentionForm {
recipient_id: mention_user.id,
comment_id: comment.id,
read: None,
};
// Allow this to fail softly, since comment edits might re-update or replace it
// Let the uniqueness handle this fail
match UserMention::create(&conn, &user_mention_form) {
Ok(_mention) => (),
Err(_e) => error!("{}", &_e),
};
// Send an email to those users that have notifications on
if mention_user.send_notifications_to_email {
if let Some(mention_email) = mention_user.email {
let subject = &format!("{} - Mentioned by {}", Settings::get().hostname, user.name,);
let html = &format!(
"<h1>User Mention</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
user.name, comment.content, hostname
);
match send_email(subject, &mention_email, &mention_user.name, html) {
Ok(_o) => _o,
Err(e) => error!("{}", e),
};
}
}
}
}
// Send notifs to the parent commenter / poster
match comment.parent_id {
Some(parent_id) => {
if let Ok(parent_comment) = Comment::read(&conn, parent_id) {
if parent_comment.creator_id != user.id {
if let Ok(parent_user) = User_::read(&conn, parent_comment.creator_id) {
recipient_ids.push(parent_user.id);
if parent_user.send_notifications_to_email {
if let Some(comment_reply_email) = parent_user.email {
let subject = &format!("{} - Reply from {}", Settings::get().hostname, user.name,);
let html = &format!(
"<h1>Comment Reply</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
user.name, comment.content, hostname
);
match send_email(subject, &comment_reply_email, &parent_user.name, html) {
Ok(_o) => _o,
Err(e) => error!("{}", e),
};
}
}
}
}
}
}
// Its a post
None => {
if post.creator_id != user.id {
if let Ok(parent_user) = User_::read(&conn, post.creator_id) {
recipient_ids.push(parent_user.id);
if parent_user.send_notifications_to_email {
if let Some(post_reply_email) = parent_user.email {
let subject = &format!("{} - Reply from {}", Settings::get().hostname, user.name,);
let html = &format!(
"<h1>Post Reply</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
user.name, comment.content, hostname
);
match send_email(subject, &post_reply_email, &parent_user.name, html) {
Ok(_o) => _o,
Err(e) => error!("{}", e),
};
}
}
}
}
}
};
recipient_ids
}

View file

@ -18,8 +18,8 @@ use crate::db::user_mention_view::*;
use crate::db::user_view::*;
use crate::db::*;
use crate::{
extract_usernames, fetch_iframely_and_pictshare_data, generate_random_string, naive_from_unix,
naive_now, remove_slurs, send_email, slur_check, slurs_vec_to_str,
fetch_iframely_and_pictshare_data, generate_random_string, naive_from_unix, naive_now,
remove_slurs, scrape_text_for_mentions, send_email, slur_check, slurs_vec_to_str, MentionData,
};
use crate::apub::{

View file

@ -2,7 +2,7 @@ use super::*;
pub fn populate_object_props(
props: &mut ObjectProperties,
addressed_to: &str,
addressed_ccs: Vec<String>,
object_id: &str,
) -> Result<(), Error> {
props
@ -12,7 +12,7 @@ pub fn populate_object_props(
// TODO: should to/cc go on the Create, or on the Post? or on both?
// TODO: handle privacy on the receiving side (at least ignore anything thats not public)
.set_to_xsd_any_uri(public())?
.set_cc_xsd_any_uri(addressed_to)?;
.set_many_cc_xsd_any_uris(addressed_ccs)?;
Ok(())
}

View file

@ -88,6 +88,8 @@ impl FromApub for CommentForm {
None => None,
};
// TODO this failed because a mention on a post that wasn't on this server yet. Has to do with
// fetching replytos
let post = Post::read_from_apub_id(&conn, &post_ap_id)?;
Ok(CommentForm {
@ -121,12 +123,15 @@ impl ApubObjectType for Comment {
let community = Community::read(conn, post.community_id)?;
let id = format!("{}/create/{}", self.ap_id, uuid::Uuid::new_v4());
let maa: MentionsAndAddresses =
collect_non_local_mentions_and_addresses(&conn, &self.content, &community)?;
let mut create = Create::new();
populate_object_props(
&mut create.object_props,
&community.get_followers_url(),
&id,
)?;
populate_object_props(&mut create.object_props, maa.addressed_ccs, &id)?;
// Set the mention tags
create.object_props.set_many_tag_base_boxes(maa.tags)?;
create
.create_props
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
@ -134,7 +139,7 @@ impl ApubObjectType for Comment {
insert_activity(&conn, creator.id, &create, true)?;
send_activity(&create, creator, community.get_follower_inboxes(&conn)?)?;
send_activity(&create, creator, maa.inboxes)?;
Ok(())
}
@ -145,12 +150,15 @@ impl ApubObjectType for Comment {
let community = Community::read(&conn, post.community_id)?;
let id = format!("{}/update/{}", self.ap_id, uuid::Uuid::new_v4());
let maa: MentionsAndAddresses =
collect_non_local_mentions_and_addresses(&conn, &self.content, &community)?;
let mut update = Update::new();
populate_object_props(
&mut update.object_props,
&community.get_followers_url(),
&id,
)?;
populate_object_props(&mut update.object_props, maa.addressed_ccs, &id)?;
// Set the mention tags
update.object_props.set_many_tag_base_boxes(maa.tags)?;
update
.update_props
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
@ -158,7 +166,7 @@ impl ApubObjectType for Comment {
insert_activity(&conn, creator.id, &update, true)?;
send_activity(&update, creator, community.get_follower_inboxes(&conn)?)?;
send_activity(&update, creator, maa.inboxes)?;
Ok(())
}
@ -171,7 +179,7 @@ impl ApubObjectType for Comment {
populate_object_props(
&mut delete.object_props,
&community.get_followers_url(),
vec![community.get_followers_url()],
&id,
)?;
@ -197,7 +205,7 @@ impl ApubObjectType for Comment {
populate_object_props(
&mut delete.object_props,
&community.get_followers_url(),
vec![community.get_followers_url()],
&id,
)?;
@ -213,7 +221,7 @@ impl ApubObjectType for Comment {
populate_object_props(
&mut undo.object_props,
&community.get_followers_url(),
vec![community.get_followers_url()],
&undo_id,
)?;
@ -237,7 +245,7 @@ impl ApubObjectType for Comment {
populate_object_props(
&mut remove.object_props,
&community.get_followers_url(),
vec![community.get_followers_url()],
&id,
)?;
@ -263,7 +271,7 @@ impl ApubObjectType for Comment {
populate_object_props(
&mut remove.object_props,
&community.get_followers_url(),
vec![community.get_followers_url()],
&id,
)?;
@ -278,7 +286,7 @@ impl ApubObjectType for Comment {
populate_object_props(
&mut undo.object_props,
&community.get_followers_url(),
vec![community.get_followers_url()],
&undo_id,
)?;
@ -302,7 +310,11 @@ impl ApubLikeableType for Comment {
let id = format!("{}/like/{}", self.ap_id, uuid::Uuid::new_v4());
let mut like = Like::new();
populate_object_props(&mut like.object_props, &community.get_followers_url(), &id)?;
populate_object_props(
&mut like.object_props,
vec![community.get_followers_url()],
&id,
)?;
like
.like_props
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
@ -323,7 +335,7 @@ impl ApubLikeableType for Comment {
let mut dislike = Dislike::new();
populate_object_props(
&mut dislike.object_props,
&community.get_followers_url(),
vec![community.get_followers_url()],
&id,
)?;
dislike
@ -344,7 +356,11 @@ impl ApubLikeableType for Comment {
let id = format!("{}/dislike/{}", self.ap_id, uuid::Uuid::new_v4());
let mut like = Like::new();
populate_object_props(&mut like.object_props, &community.get_followers_url(), &id)?;
populate_object_props(
&mut like.object_props,
vec![community.get_followers_url()],
&id,
)?;
like
.like_props
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
@ -357,7 +373,7 @@ impl ApubLikeableType for Comment {
populate_object_props(
&mut undo.object_props,
&community.get_followers_url(),
vec![community.get_followers_url()],
&undo_id,
)?;
@ -372,3 +388,57 @@ impl ApubLikeableType for Comment {
Ok(())
}
}
struct MentionsAndAddresses {
addressed_ccs: Vec<String>,
inboxes: Vec<String>,
tags: Vec<Mention>,
}
/// This takes a comment, and builds a list of to_addresses, inboxes,
/// and mention tags, so they know where to be sent to.
/// Addresses are the users / addresses that go in the cc field.
fn collect_non_local_mentions_and_addresses(
conn: &PgConnection,
content: &str,
community: &Community,
) -> Result<MentionsAndAddresses, Error> {
let mut addressed_ccs = vec![community.get_followers_url()];
// Add the mention tag
let mut tags = Vec::new();
// Get the inboxes for any mentions
let mentions = scrape_text_for_mentions(&content)
.into_iter()
// Filter only the non-local ones
.filter(|m| !m.is_local())
.collect::<Vec<MentionData>>();
let mut mention_inboxes = Vec::new();
for mention in &mentions {
// TODO should it be fetching it every time?
if let Ok(actor_id) = fetch_webfinger_url(mention) {
debug!("mention actor_id: {}", actor_id);
addressed_ccs.push(actor_id.to_owned());
let mention_user = get_or_fetch_and_upsert_remote_user(&actor_id, &conn)?;
let shared_inbox = mention_user.get_shared_inbox_url();
mention_inboxes.push(shared_inbox);
let mut mention_tag = Mention::new();
mention_tag
.link_props
.set_href(actor_id)?
.set_name_xsd_string(mention.full_name())?;
tags.push(mention_tag);
}
}
let mut inboxes = community.get_follower_inboxes(&conn)?;
inboxes.extend(mention_inboxes);
inboxes = inboxes.into_iter().unique().collect();
Ok(MentionsAndAddresses {
addressed_ccs,
inboxes,
tags,
})
}

View file

@ -114,7 +114,11 @@ impl ActorType for Community {
let id = format!("{}/delete/{}", self.actor_id, uuid::Uuid::new_v4());
let mut delete = Delete::default();
populate_object_props(&mut delete.object_props, &self.get_followers_url(), &id)?;
populate_object_props(
&mut delete.object_props,
vec![self.get_followers_url()],
&id,
)?;
delete
.delete_props
@ -135,7 +139,11 @@ impl ActorType for Community {
let id = format!("{}/delete/{}", self.actor_id, uuid::Uuid::new_v4());
let mut delete = Delete::default();
populate_object_props(&mut delete.object_props, &self.get_followers_url(), &id)?;
populate_object_props(
&mut delete.object_props,
vec![self.get_followers_url()],
&id,
)?;
delete
.delete_props
@ -147,7 +155,11 @@ impl ActorType for Community {
let undo_id = format!("{}/undo/delete/{}", self.actor_id, uuid::Uuid::new_v4());
let mut undo = Undo::default();
populate_object_props(&mut undo.object_props, &self.get_followers_url(), &undo_id)?;
populate_object_props(
&mut undo.object_props,
vec![self.get_followers_url()],
&undo_id,
)?;
undo
.undo_props
@ -168,7 +180,11 @@ impl ActorType for Community {
let id = format!("{}/remove/{}", self.actor_id, uuid::Uuid::new_v4());
let mut remove = Remove::default();
populate_object_props(&mut remove.object_props, &self.get_followers_url(), &id)?;
populate_object_props(
&mut remove.object_props,
vec![self.get_followers_url()],
&id,
)?;
remove
.remove_props
@ -189,7 +205,11 @@ impl ActorType for Community {
let id = format!("{}/remove/{}", self.actor_id, uuid::Uuid::new_v4());
let mut remove = Remove::default();
populate_object_props(&mut remove.object_props, &self.get_followers_url(), &id)?;
populate_object_props(
&mut remove.object_props,
vec![self.get_followers_url()],
&id,
)?;
remove
.remove_props
@ -200,7 +220,11 @@ impl ActorType for Community {
let undo_id = format!("{}/undo/remove/{}", self.actor_id, uuid::Uuid::new_v4());
let mut undo = Undo::default();
populate_object_props(&mut undo.object_props, &self.get_followers_url(), &undo_id)?;
populate_object_props(
&mut undo.object_props,
vec![self.get_followers_url()],
&undo_id,
)?;
undo
.undo_props

View file

@ -55,7 +55,7 @@ pub fn sign(request: &Builder, actor: &dyn ActorType) -> Result<String, Error> {
.unwrap()
.as_str(),
headers,
)
)?
.sign(signing_key_id, |signing_string| {
let private_key = PKey::private_key_from_pem(actor.private_key().as_bytes())?;
let mut signer = Signer::new(MessageDigest::sha256(), &private_key).unwrap();

View file

@ -9,7 +9,6 @@ pub mod private_message;
pub mod shared_inbox;
pub mod user;
pub mod user_inbox;
use crate::api::community::CommunityResponse;
use crate::db::activity::insert_activity;
use crate::websocket::server::SendCommunityRoomMessage;
@ -21,6 +20,7 @@ use activitystreams::{
context,
endpoint::EndpointProperties,
ext::{Ext, Extensible},
link::Mention,
object::{properties::ObjectProperties, Note, Page, Tombstone},
public, BaseBox,
};
@ -38,7 +38,7 @@ use serde::{Deserialize, Serialize};
use std::time::Duration;
use url::Url;
use crate::api::comment::CommentResponse;
use crate::api::comment::{send_local_notifs, CommentResponse};
use crate::api::post::PostResponse;
use crate::api::site::SearchResponse;
use crate::api::user::PrivateMessageResponse;
@ -57,12 +57,13 @@ use crate::db::user::{UserForm, User_};
use crate::db::user_view::UserView;
use crate::db::{Crud, Followable, Joinable, Likeable, SearchType};
use crate::routes::nodeinfo::{NodeInfo, NodeInfoWellKnown};
use crate::routes::webfinger::WebFingerResponse;
use crate::routes::{ChatServerParam, DbPoolParam};
use crate::websocket::{
server::{SendComment, SendPost, SendUserRoomMessage},
UserOperation,
};
use crate::{convert_datetime, naive_now, Settings};
use crate::{convert_datetime, naive_now, scrape_text_for_mentions, MentionData, Settings};
use crate::apub::extensions::group_extensions::GroupExtension;
use crate::apub::extensions::page_extension::PageExtension;
@ -280,3 +281,25 @@ pub trait ActorType {
.to_ext()
}
}
pub fn fetch_webfinger_url(mention: &MentionData) -> Result<String, Error> {
let fetch_url = format!(
"{}://{}/.well-known/webfinger?resource=acct:{}@{}",
get_apub_protocol_string(),
mention.domain,
mention.name,
mention.domain
);
debug!("Fetching webfinger url: {}", &fetch_url);
let text = isahc::get(&fetch_url)?.text()?;
let res: WebFingerResponse = serde_json::from_str(&text)?;
let link = res
.links
.iter()
.find(|l| l.type_.eq(&Some("application/activity+json".to_string())))
.ok_or_else(|| format_err!("No application/activity+json link found."))?;
link
.href
.to_owned()
.ok_or_else(|| format_err!("No href found."))
}

View file

@ -124,7 +124,7 @@ impl ApubObjectType for Post {
let mut create = Create::new();
populate_object_props(
&mut create.object_props,
&community.get_followers_url(),
vec![community.get_followers_url()],
&id,
)?;
create
@ -147,7 +147,7 @@ impl ApubObjectType for Post {
let mut update = Update::new();
populate_object_props(
&mut update.object_props,
&community.get_followers_url(),
vec![community.get_followers_url()],
&id,
)?;
update
@ -169,7 +169,7 @@ impl ApubObjectType for Post {
populate_object_props(
&mut delete.object_props,
&community.get_followers_url(),
vec![community.get_followers_url()],
&id,
)?;
@ -193,7 +193,7 @@ impl ApubObjectType for Post {
populate_object_props(
&mut delete.object_props,
&community.get_followers_url(),
vec![community.get_followers_url()],
&id,
)?;
@ -209,7 +209,7 @@ impl ApubObjectType for Post {
populate_object_props(
&mut undo.object_props,
&community.get_followers_url(),
vec![community.get_followers_url()],
&undo_id,
)?;
@ -233,7 +233,7 @@ impl ApubObjectType for Post {
populate_object_props(
&mut remove.object_props,
&community.get_followers_url(),
vec![community.get_followers_url()],
&id,
)?;
@ -256,7 +256,7 @@ impl ApubObjectType for Post {
populate_object_props(
&mut remove.object_props,
&community.get_followers_url(),
vec![community.get_followers_url()],
&id,
)?;
@ -271,7 +271,7 @@ impl ApubObjectType for Post {
populate_object_props(
&mut undo.object_props,
&community.get_followers_url(),
vec![community.get_followers_url()],
&undo_id,
)?;
@ -295,7 +295,11 @@ impl ApubLikeableType for Post {
let id = format!("{}/like/{}", self.ap_id, uuid::Uuid::new_v4());
let mut like = Like::new();
populate_object_props(&mut like.object_props, &community.get_followers_url(), &id)?;
populate_object_props(
&mut like.object_props,
vec![community.get_followers_url()],
&id,
)?;
like
.like_props
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
@ -315,7 +319,7 @@ impl ApubLikeableType for Post {
let mut dislike = Dislike::new();
populate_object_props(
&mut dislike.object_props,
&community.get_followers_url(),
vec![community.get_followers_url()],
&id,
)?;
dislike
@ -335,7 +339,11 @@ impl ApubLikeableType for Post {
let id = format!("{}/like/{}", self.ap_id, uuid::Uuid::new_v4());
let mut like = Like::new();
populate_object_props(&mut like.object_props, &community.get_followers_url(), &id)?;
populate_object_props(
&mut like.object_props,
vec![community.get_followers_url()],
&id,
)?;
like
.like_props
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
@ -348,7 +356,7 @@ impl ApubLikeableType for Post {
populate_object_props(
&mut undo.object_props,
&community.get_followers_url(),
vec![community.get_followers_url()],
&undo_id,
)?;

View file

@ -167,12 +167,18 @@ fn receive_create_comment(
let comment = CommentForm::from_apub(&note, &conn)?;
let inserted_comment = Comment::create(conn, &comment)?;
let post = Post::read(&conn, inserted_comment.post_id)?;
// Note:
// Although mentions could be gotten from the post tags (they are included there), or the ccs,
// Its much easier to scrape them from the comment body, since the API has to do that
// anyway.
let mentions = scrape_text_for_mentions(&inserted_comment.content);
let recipient_ids = send_local_notifs(&conn, &mentions, &inserted_comment, &user, &post);
// Refetch the view
let comment_view = CommentView::read(&conn, inserted_comment.id, None)?;
// TODO get those recipient actor ids from somewhere
let recipient_ids = vec![];
let res = CommentResponse {
comment: comment_view,
recipient_ids,
@ -353,13 +359,15 @@ fn receive_update_comment(
let comment = CommentForm::from_apub(&note, &conn)?;
let comment_id = Comment::read_from_apub_id(conn, &comment.ap_id)?.id;
Comment::update(conn, comment_id, &comment)?;
let updated_comment = Comment::update(conn, comment_id, &comment)?;
let post = Post::read(&conn, updated_comment.post_id)?;
let mentions = scrape_text_for_mentions(&updated_comment.content);
let recipient_ids = send_local_notifs(&conn, &mentions, &updated_comment, &user, &post);
// Refetch the view
let comment_view = CommentView::read(&conn, comment_id, None)?;
// TODO get those recipient actor ids from somewhere
let recipient_ids = vec![];
let res = CommentResponse {
comment: comment_view,
recipient_ids,

View file

@ -92,10 +92,6 @@ impl Community {
use crate::schema::community::dsl::*;
community.filter(local.eq(true)).load::<Community>(conn)
}
pub fn get_url(&self) -> String {
format!("https://{}/c/{}", Settings::get().hostname, self.name)
}
}
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]

View file

@ -40,6 +40,7 @@ use crate::settings::Settings;
use actix_web::dev::ConnectionInfo;
use chrono::{DateTime, FixedOffset, Local, NaiveDateTime, Utc};
use isahc::prelude::*;
use itertools::Itertools;
use lettre::smtp::authentication::{Credentials, Mechanism};
use lettre::smtp::extension::ClientId;
use lettre::smtp::ConnectionReuseParameters;
@ -103,20 +104,6 @@ pub fn slurs_vec_to_str(slurs: Vec<&str>) -> String {
[start, combined].concat()
}
pub fn extract_usernames(test: &str) -> Vec<&str> {
let mut matches: Vec<&str> = USERNAME_MATCHES_REGEX
.find_iter(test)
.map(|mat| mat.as_str())
.collect();
// Unique
matches.sort_unstable();
matches.dedup();
// Remove /u/
matches.iter().map(|t| &t[3..]).collect()
}
pub fn generate_random_string() -> String {
thread_rng().sample_iter(&Alphanumeric).take(30).collect()
}
@ -249,9 +236,48 @@ pub fn get_ip(conn_info: &ConnectionInfo) -> String {
.to_string()
}
// TODO nothing is done with community / group webfingers yet, so just ignore those for now
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct MentionData {
pub name: String,
pub domain: String,
}
impl MentionData {
pub fn is_local(&self) -> bool {
Settings::get().hostname.eq(&self.domain)
}
pub fn full_name(&self) -> String {
format!("@{}@{}", &self.name, &self.domain)
}
}
pub fn scrape_text_for_mentions(text: &str) -> Vec<MentionData> {
let mut out: Vec<MentionData> = Vec::new();
for caps in WEBFINGER_USER_REGEX.captures_iter(text) {
out.push(MentionData {
name: caps["name"].to_string(),
domain: caps["domain"].to_string(),
});
}
out.into_iter().unique().collect()
}
#[cfg(test)]
mod tests {
use crate::{extract_usernames, is_email_regex, remove_slurs, slur_check, slurs_vec_to_str};
use crate::{
is_email_regex, remove_slurs, scrape_text_for_mentions, slur_check, slurs_vec_to_str,
};
#[test]
fn test_mentions_regex() {
let text = "Just read a great blog post by [@tedu@honk.teduangst.com](/u/test). And another by !test_community@fish.teduangst.com . Another [@lemmy@lemmy_alpha:8540](/u/fish)";
let mentions = scrape_text_for_mentions(text);
assert_eq!(mentions[0].name, "tedu".to_string());
assert_eq!(mentions[0].domain, "honk.teduangst.com".to_string());
assert_eq!(mentions[1].domain, "lemmy_alpha:8540".to_string());
}
#[test]
fn test_email() {
@ -287,13 +313,6 @@ mod tests {
}
}
#[test]
fn test_extract_usernames() {
let usernames = extract_usernames("this is a user mention for [/u/testme](/u/testme) and thats all. Oh [/u/another](/u/another) user. And the first again [/u/testme](/u/testme) okay");
let expected = vec!["another", "testme"];
assert_eq!(usernames, expected);
}
// These helped with testing
// #[test]
// fn test_iframely() {
@ -320,4 +339,7 @@ lazy_static! {
static ref EMAIL_REGEX: Regex = Regex::new(r"^[a-zA-Z0-9.!#$%&*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$").unwrap();
static ref SLUR_REGEX: Regex = RegexBuilder::new(r"(fag(g|got|tard)?|maricos?|cock\s?sucker(s|ing)?|nig(\b|g?(a|er)?(s|z)?)\b|dindu(s?)|mudslime?s?|kikes?|mongoloids?|towel\s*heads?|\bspi(c|k)s?\b|\bchinks?|niglets?|beaners?|\bnips?\b|\bcoons?\b|jungle\s*bunn(y|ies?)|jigg?aboo?s?|\bpakis?\b|rag\s*heads?|gooks?|cunts?|bitch(es|ing|y)?|puss(y|ies?)|twats?|feminazis?|whor(es?|ing)|\bslut(s|t?y)?|\btrann?(y|ies?)|ladyboy(s?)|\b(b|re|r)tard(ed)?s?)").case_insensitive(true).build().unwrap();
static ref USERNAME_MATCHES_REGEX: Regex = Regex::new(r"/u/[a-zA-Z][0-9a-zA-Z_]*").unwrap();
// TODO keep this old one, it didn't work with port well tho
// static ref WEBFINGER_USER_REGEX: Regex = Regex::new(r"@(?P<name>[\w.]+)@(?P<domain>[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)").unwrap();
static ref WEBFINGER_USER_REGEX: Regex = Regex::new(r"@(?P<name>[\w.]+)@(?P<domain>[a-zA-Z0-9._:-]+)").unwrap();
}

View file

@ -142,7 +142,6 @@ fn get_feed_community(
) -> Result<ChannelBuilder, failure::Error> {
let site_view = SiteView::read(&conn)?;
let community = Community::read_from_name(&conn, &community_name)?;
let community_url = community.get_url();
let posts = PostQueryBuilder::create(&conn)
.listing_type(ListingType::All)
@ -155,7 +154,7 @@ fn get_feed_community(
let mut channel_builder = ChannelBuilder::default();
channel_builder
.title(&format!("{} - {}", site_view.name, community.name))
.link(community_url)
.link(community.actor_id)
.items(items);
if let Some(community_desc) = community.description {

View file

@ -1,6 +1,8 @@
use crate::api::{Oper, Perform};
use crate::apub::get_apub_protocol_string;
use crate::db::community::Community;
use crate::db::site_view::SiteView;
use crate::db::user::User_;
use crate::rate_limit::rate_limiter::RateLimiter;
use crate::websocket::{server::ChatServer, WebsocketInfo};
use crate::{get_ip, markdown_to_html, version, Settings};
@ -13,11 +15,10 @@ use diesel::{
r2d2::{ConnectionManager, Pool},
PgConnection,
};
use log::{error, info};
use log::{debug, error, info};
use regex::Regex;
use rss::{CategoryBuilder, ChannelBuilder, GuidBuilder, Item, ItemBuilder};
use serde::{Deserialize, Serialize};
use serde_json::json;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};

View file

@ -1,11 +1,27 @@
use super::*;
use crate::db::community::Community;
#[derive(Deserialize)]
pub struct Params {
resource: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct WebFingerResponse {
pub subject: String,
pub aliases: Vec<String>,
pub links: Vec<WebFingerLink>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct WebFingerLink {
pub rel: Option<String>,
#[serde(rename(serialize = "type", deserialize = "type"))]
pub type_: Option<String>,
pub href: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub template: Option<String>,
}
pub fn config(cfg: &mut web::ServiceConfig) {
if Settings::get().federation.enabled {
cfg.route(
@ -21,6 +37,11 @@ lazy_static! {
Settings::get().hostname
))
.unwrap();
static ref WEBFINGER_USER_REGEX: Regex = Regex::new(&format!(
"^acct:([a-z0-9_]{{3, 20}})@{}$",
Settings::get().hostname
))
.unwrap();
}
/// Responds to webfinger requests of the following format. There isn't any real documentation for
@ -36,46 +57,58 @@ async fn get_webfinger_response(
let res = web::block(move || {
let conn = db.get()?;
let regex_parsed = WEBFINGER_COMMUNITY_REGEX
let community_regex_parsed = WEBFINGER_COMMUNITY_REGEX
.captures(&info.resource)
.map(|c| c.get(1))
.flatten();
let community_name = match regex_parsed {
Some(c) => c.as_str(),
None => return Err(format_err!("not_found")),
};
let user_regex_parsed = WEBFINGER_USER_REGEX
.captures(&info.resource)
.map(|c| c.get(1))
.flatten();
let url = if let Some(community_name) = community_regex_parsed {
// Make sure the requested community exists.
let community = match Community::read_from_name(&conn, &community_name) {
let community = match Community::read_from_name(&conn, &community_name.as_str()) {
Ok(o) => o,
Err(_) => return Err(format_err!("not_found")),
};
community.actor_id
} else if let Some(user_name) = user_regex_parsed {
// Make sure the requested user exists.
let user = match User_::read_from_name(&conn, &user_name.as_str()) {
Ok(o) => o,
Err(_) => return Err(format_err!("not_found")),
};
user.actor_id
} else {
return Err(format_err!("not_found"));
};
let community_url = community.get_url();
Ok(json!({
"subject": info.resource,
"aliases": [
community_url,
],
"links": [
{
"rel": "http://webfinger.net/rel/profile-page",
"type": "text/html",
"href": community.get_url(),
let wf_res = WebFingerResponse {
subject: info.resource.to_owned(),
aliases: vec![url.to_owned()],
links: vec![
WebFingerLink {
rel: Some("http://webfinger.net/rel/profile-page".to_string()),
type_: Some("text/html".to_string()),
href: Some(url.to_owned()),
template: None,
},
{
"rel": "self",
"type": "application/activity+json",
"href": community_url
}
// TODO: this also needs to return the subscribe link once that's implemented
WebFingerLink {
rel: Some("self".to_string()),
type_: Some("application/activity+json".to_string()),
href: Some(url),
template: None,
}, // TODO: this also needs to return the subscribe link once that's implemented
//{
// "rel": "http://ostatus.org/schema/1.0/subscribe",
// "template": "https://my_instance.com/authorize_interaction?uri={uri}"
//}
]
}))
],
};
Ok(wf_res)
})
.await
.map(|json| HttpResponse::Ok().json(json))

View file

@ -143,7 +143,7 @@ impl WSSession {
// check client heartbeats
if Instant::now().duration_since(act.hb) > CLIENT_TIMEOUT {
// heartbeat timed out
error!("Websocket Client heartbeat failed, disconnecting!");
debug!("Websocket Client heartbeat failed, disconnecting!");
// notify chat server
act.cs_addr.do_send(Disconnect {

View file

@ -22,6 +22,7 @@ import {
EditPrivateMessageForm,
PrivateMessageResponse,
PrivateMessagesResponse,
GetUserMentionsResponse,
} from '../interfaces';
let lemmyAlphaUrl = 'http://localhost:8540';
@ -379,6 +380,44 @@ describe('main', () => {
expect(getPostResAlpha.comments[0].community_local).toBe(false);
expect(getPostResAlpha.comments[0].creator_local).toBe(false);
expect(getPostResAlpha.comments[0].score).toBe(1);
// Lemmy alpha responds to their own comment, but mentions lemmy beta.
// Make sure lemmy beta gets that in their inbox.
let mentionContent = 'A test mention of @lemmy_beta@lemmy_beta:8550';
let mentionCommentForm: CommentForm = {
content: mentionContent,
post_id: 2,
parent_id: createResponse.comment.id,
auth: lemmyAlphaAuth,
};
let createMentionRes: CommentResponse = await fetch(
`${lemmyAlphaApiUrl}/comment`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(mentionCommentForm),
}
).then(d => d.json());
expect(createMentionRes.comment.content).toBe(mentionContent);
expect(createMentionRes.comment.community_local).toBe(false);
expect(createMentionRes.comment.creator_local).toBe(true);
expect(createMentionRes.comment.score).toBe(1);
// Make sure lemmy beta sees that new mention
let getMentionUrl = `${lemmyBetaApiUrl}/user/mention?sort=New&unread_only=false&auth=${lemmyBetaAuth}`;
let getMentionsRes: GetUserMentionsResponse = await fetch(getMentionUrl, {
method: 'GET',
}).then(d => d.json());
// The newest show up first
expect(getMentionsRes.mentions[0].content).toBe(mentionContent);
expect(getMentionsRes.mentions[0].community_local).toBe(true);
expect(getMentionsRes.mentions[0].creator_local).toBe(false);
expect(getMentionsRes.mentions[0].score).toBe(1);
});
});
@ -413,9 +452,9 @@ describe('main', () => {
method: 'GET',
}).then(d => d.json());
expect(getPostRes.comments[1].content).toBe(content);
expect(getPostRes.comments[1].community_local).toBe(true);
expect(getPostRes.comments[1].creator_local).toBe(false);
expect(getPostRes.comments[2].content).toBe(content);
expect(getPostRes.comments[2].community_local).toBe(true);
expect(getPostRes.comments[2].creator_local).toBe(false);
});
});

21
ui/src/utils.ts vendored
View file

@ -502,8 +502,8 @@ export function setupTribute(): Tribute {
trigger: '@',
selectTemplate: (item: any) => {
let link = item.original.local
? `[@${item.original.key}](/u/${item.original.key})`
: `[@${item.original.key}](/user/${item.original.id})`;
? `[${item.original.key}](/u/${item.original.name})`
: `[${item.original.key}](/user/${item.original.id})`;
return link;
},
values: (text: string, cb: any) => {
@ -520,8 +520,8 @@ export function setupTribute(): Tribute {
trigger: '!',
selectTemplate: (item: any) => {
let link = item.original.local
? `[!${item.original.key}](/c/${item.original.key})`
: `[!${item.original.key}](/community/${item.original.id})`;
? `[${item.original.key}](/c/${item.original.name})`
: `[${item.original.key}](/community/${item.original.id})`;
return link;
},
values: (text: string, cb: any) => {
@ -565,9 +565,9 @@ function userSearch(text: string, cb: any) {
if (res.op == UserOperation.Search) {
let data = res.data as SearchResponse;
let users = data.users.map(u => {
let name_ = u.local ? u.name : `${u.name}@${hostname(u.actor_id)}`;
return {
key: name_,
key: `@${u.name}@${hostname(u.actor_id)}`,
name: u.name,
local: u.local,
id: u.id,
};
@ -602,9 +602,9 @@ function communitySearch(text: string, cb: any) {
if (res.op == UserOperation.Search) {
let data = res.data as SearchResponse;
let communities = data.communities.map(c => {
let name_ = c.local ? c.name : `${c.name}@${hostname(c.actor_id)}`;
return {
key: name_,
key: `!${c.name}@${hostname(c.actor_id)}`,
name: c.name,
local: c.local,
id: c.id,
};
@ -859,5 +859,8 @@ export function previewLines(text: string, lines: number = 3): string {
}
export function hostname(url: string): string {
return new URL(url).hostname;
let cUrl = new URL(url);
return window.location.port
? `${cUrl.hostname}:${cUrl.port}`
: `${cUrl.hostname}`;
}