Iframely and pictshare backend mostly done.
This commit is contained in:
parent
52f5178649
commit
966a6fc70b
22 changed files with 714 additions and 203 deletions
166
server/Cargo.lock
generated
vendored
166
server/Cargo.lock
generated
vendored
|
@ -148,7 +148,7 @@ dependencies = [
|
||||||
"futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"h2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -586,6 +586,15 @@ name = "byteorder"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytes"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
|
@ -628,6 +637,25 @@ dependencies = [
|
||||||
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chttp"
|
||||||
|
version = "0.5.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"curl 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"curl-sys 0.4.28+curl-7.69.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"futures-io-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"futures-util-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"sluice 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cloudabi"
|
name = "cloudabi"
|
||||||
version = "0.0.3"
|
version = "0.0.3"
|
||||||
|
@ -678,6 +706,14 @@ dependencies = [
|
||||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -686,6 +722,15 @@ dependencies = [
|
||||||
"crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.6.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
@ -696,6 +741,35 @@ dependencies = [
|
||||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "curl"
|
||||||
|
version = "0.4.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"curl-sys 0.4.28+curl-7.69.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "curl-sys"
|
||||||
|
version = "0.4.28+curl-7.69.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libnghttp2-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling"
|
name = "darling"
|
||||||
version = "0.10.2"
|
version = "0.10.2"
|
||||||
|
@ -1038,11 +1112,24 @@ dependencies = [
|
||||||
"futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-channel-preview"
|
||||||
|
version = "0.3.0-alpha.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-core-preview"
|
||||||
|
version = "0.3.0-alpha.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-executor"
|
name = "futures-executor"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -1058,6 +1145,11 @@ name = "futures-io"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-io-preview"
|
||||||
|
version = "0.3.0-alpha.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-macro"
|
name = "futures-macro"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -1097,6 +1189,18 @@ dependencies = [
|
||||||
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-util-preview"
|
||||||
|
version = "0.3.0-alpha.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"futures-io-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fxhash"
|
name = "fxhash"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
@ -1125,7 +1229,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "h2"
|
||||||
version = "0.2.1"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1182,6 +1286,16 @@ name = "htmlescape"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "http"
|
||||||
|
version = "0.1.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http"
|
name = "http"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -1314,6 +1428,7 @@ dependencies = [
|
||||||
"actix-web-actors 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"actix-web-actors 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bcrypt 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bcrypt 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"chttp 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"config 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"config 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"diesel 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"diesel 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"diesel_migrations 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"diesel_migrations 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1326,6 +1441,7 @@ dependencies = [
|
||||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lettre 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lettre 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lettre_email 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lettre_email 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rss 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rss 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1383,6 +1499,26 @@ name = "libc"
|
||||||
version = "0.2.66"
|
version = "0.2.66"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libnghttp2-sys"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libz-sys"
|
||||||
|
version = "1.0.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linked-hash-map"
|
name = "linked-hash-map"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
@ -2233,6 +2369,16 @@ name = "slab"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sluice"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"futures-channel-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"futures-core-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"futures-io-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -2806,20 +2952,26 @@ dependencies = [
|
||||||
"checksum bumpalo 3.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb8038c1ddc0a5f73787b130f4cc75151e96ed33e417fde765eb5a81e3532f4"
|
"checksum bumpalo 3.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb8038c1ddc0a5f73787b130f4cc75151e96ed33e417fde765eb5a81e3532f4"
|
||||||
"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
||||||
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
||||||
|
"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
|
||||||
"checksum bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10004c15deb332055f7a4a208190aed362cf9a7c2f6ab70a305fba50e1105f38"
|
"checksum bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10004c15deb332055f7a4a208190aed362cf9a7c2f6ab70a305fba50e1105f38"
|
||||||
"checksum bytestring 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b24c107a4432e408d2caa58d3f5e763b219236221406ea58a4076b62343a039d"
|
"checksum bytestring 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b24c107a4432e408d2caa58d3f5e763b219236221406ea58a4076b62343a039d"
|
||||||
"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"
|
"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"
|
||||||
"checksum cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76"
|
"checksum cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76"
|
||||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||||
"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01"
|
"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01"
|
||||||
|
"checksum chttp 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ca699a61cc91c90af209d6bf546fc69d29e9d474c77fa86b9410eb3cf1e6eb31"
|
||||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||||
"checksum config 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "19b076e143e1d9538dde65da30f8481c2a6c44040edb8e02b9bf1351edb92ce3"
|
"checksum config 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "19b076e143e1d9538dde65da30f8481c2a6c44040edb8e02b9bf1351edb92ce3"
|
||||||
"checksum copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ff9c56c9fb2a49c05ef0e431485a22400af20d33226dc0764d891d09e724127"
|
"checksum copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ff9c56c9fb2a49c05ef0e431485a22400af20d33226dc0764d891d09e724127"
|
||||||
"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"
|
"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"
|
||||||
"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
|
"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
|
||||||
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
|
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
|
||||||
|
"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa"
|
||||||
"checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c"
|
"checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c"
|
||||||
|
"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
|
||||||
"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4"
|
"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4"
|
||||||
|
"checksum curl 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "ecb534fed9060d04bccaa8b8e1e2d3d5a0d7a9ec6d9c667691c80a3c6b7d19ef"
|
||||||
|
"checksum curl-sys 0.4.28+curl-7.69.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2c6b7fa5d36aa192e410788b77af65f339af24c8786419e8b48173689a484bf"
|
||||||
"checksum darling 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858"
|
"checksum darling 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858"
|
||||||
"checksum darling_core 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b"
|
"checksum darling_core 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b"
|
||||||
"checksum darling_macro 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
|
"checksum darling_macro 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
|
||||||
|
@ -2859,22 +3011,27 @@ dependencies = [
|
||||||
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||||
"checksum futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987"
|
"checksum futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987"
|
||||||
"checksum futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86"
|
"checksum futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86"
|
||||||
|
"checksum futures-channel-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)" = "21c71ed547606de08e9ae744bb3c6d80f5627527ef31ecf2a7210d0e67bc8fae"
|
||||||
"checksum futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866"
|
"checksum futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866"
|
||||||
|
"checksum futures-core-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4b141ccf9b7601ef987f36f1c0d9522f76df3bba1cf2e63bfacccc044c4558f5"
|
||||||
"checksum futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231"
|
"checksum futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231"
|
||||||
"checksum futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff"
|
"checksum futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff"
|
||||||
|
"checksum futures-io-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)" = "082e402605fcb8b1ae1e5ba7d7fdfd3e31ef510e2a8367dd92927bb41ae41b3a"
|
||||||
"checksum futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764"
|
"checksum futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764"
|
||||||
"checksum futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16"
|
"checksum futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16"
|
||||||
"checksum futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9"
|
"checksum futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9"
|
||||||
"checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76"
|
"checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76"
|
||||||
|
"checksum futures-util-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)" = "af8198c48b222f02326940ce2b3aa9e6e91a32886eeaad7ca3b8e4c70daa3f4e"
|
||||||
"checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
"checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
||||||
"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
|
"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
|
||||||
"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407"
|
"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407"
|
||||||
"checksum h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9433d71e471c1736fd5a61b671fc0b148d7a2992f666c958d03cd8feb3b88d1"
|
"checksum h2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9d5c295d1c0c68e4e42003d75f908f5e16a1edd1cbe0b0d02e4dc2006a384f47"
|
||||||
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
||||||
"checksum hermit-abi 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f629dc602392d3ec14bfc8a09b5e644d7ffd725102b48b81e59f90f2633621d7"
|
"checksum hermit-abi 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f629dc602392d3ec14bfc8a09b5e644d7ffd725102b48b81e59f90f2633621d7"
|
||||||
"checksum hjson 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0849d73a64ec77d1c8354aff489cf31943c4b4d3716de1eabfba572c70fde530"
|
"checksum hjson 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0849d73a64ec77d1c8354aff489cf31943c4b4d3716de1eabfba572c70fde530"
|
||||||
"checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e"
|
"checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e"
|
||||||
"checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163"
|
"checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163"
|
||||||
|
"checksum http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0"
|
||||||
"checksum http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b708cc7f06493459026f53b9a61a7a121a5d1ec6238dee58ea4941132b30156b"
|
"checksum http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b708cc7f06493459026f53b9a61a7a121a5d1ec6238dee58ea4941132b30156b"
|
||||||
"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
|
"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
|
||||||
"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
|
"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
|
||||||
|
@ -2895,6 +3052,8 @@ dependencies = [
|
||||||
"checksum lettre_email 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bbb68ca999042d965476e47bbdbacd52db0927348b6f8062c44dd04a3b1fd43b"
|
"checksum lettre_email 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bbb68ca999042d965476e47bbdbacd52db0927348b6f8062c44dd04a3b1fd43b"
|
||||||
"checksum lexical-core 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2304bccb228c4b020f3a4835d247df0a02a7c4686098d4167762cfbbe4c5cb14"
|
"checksum lexical-core 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2304bccb228c4b020f3a4835d247df0a02a7c4686098d4167762cfbbe4c5cb14"
|
||||||
"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
|
"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
|
||||||
|
"checksum libnghttp2-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b359f5ec8106bc297694c9a562ace312be2cfd17a5fc68dc12249845aa144b11"
|
||||||
|
"checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe"
|
||||||
"checksum linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd"
|
"checksum linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd"
|
||||||
"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
|
"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
|
||||||
"checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586"
|
"checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586"
|
||||||
|
@ -2995,6 +3154,7 @@ dependencies = [
|
||||||
"checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41"
|
"checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41"
|
||||||
"checksum simple_asn1 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b25ecba7165254f0c97d6c22a64b1122a03634b18d20a34daf21e18f892e618"
|
"checksum simple_asn1 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b25ecba7165254f0c97d6c22a64b1122a03634b18d20a34daf21e18f892e618"
|
||||||
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
||||||
|
"checksum sluice 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ec70d7c3b17c262d4a18f7291c6ce62bf47170915f3b795434d3c5c49a4e59b7"
|
||||||
"checksum smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4"
|
"checksum smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4"
|
||||||
"checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85"
|
"checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85"
|
||||||
"checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3"
|
"checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3"
|
||||||
|
|
4
server/Cargo.toml
vendored
4
server/Cargo.toml
vendored
|
@ -5,7 +5,7 @@ authors = ["Dessalines <happydooby@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
diesel = { version = "1.4.2", features = ["postgres","chrono", "r2d2"] }
|
diesel = { version = "1.4.2", features = ["postgres","chrono", "r2d2", "64-column-tables"] }
|
||||||
diesel_migrations = "1.4.0"
|
diesel_migrations = "1.4.0"
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
bcrypt = "0.6.1"
|
bcrypt = "0.6.1"
|
||||||
|
@ -33,3 +33,5 @@ rss = "1.9.0"
|
||||||
htmlescape = "0.3.1"
|
htmlescape = "0.3.1"
|
||||||
config = "0.10.1"
|
config = "0.10.1"
|
||||||
hjson = "0.8.2"
|
hjson = "0.8.2"
|
||||||
|
percent-encoding = "2.1.0"
|
||||||
|
chttp = "0.5.5"
|
||||||
|
|
112
server/migrations/2020-03-06-202329_add_post_iframely_data/down.sql
vendored
Normal file
112
server/migrations/2020-03-06-202329_add_post_iframely_data/down.sql
vendored
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
-- Adds a newest_activity_time for the post_views, in order to sort by newest comment
|
||||||
|
drop view post_view;
|
||||||
|
drop view post_mview;
|
||||||
|
drop materialized view post_aggregates_mview;
|
||||||
|
drop view post_aggregates_view;
|
||||||
|
|
||||||
|
-- Drop the columns
|
||||||
|
alter table post drop column embed_title;
|
||||||
|
alter table post drop column embed_description;
|
||||||
|
alter table post drop column embed_html;
|
||||||
|
alter table post drop column thumbnail_url;
|
||||||
|
|
||||||
|
-- regen post view
|
||||||
|
create view post_aggregates_view as
|
||||||
|
select
|
||||||
|
p.*,
|
||||||
|
(select u.banned from user_ u where p.creator_id = u.id) as banned,
|
||||||
|
(select cb.id::bool from community_user_ban cb where p.creator_id = cb.user_id and p.community_id = cb.community_id) as banned_from_community,
|
||||||
|
(select name from user_ where p.creator_id = user_.id) as creator_name,
|
||||||
|
(select avatar from user_ where p.creator_id = user_.id) as creator_avatar,
|
||||||
|
(select name from community where p.community_id = community.id) as community_name,
|
||||||
|
(select removed from community c where p.community_id = c.id) as community_removed,
|
||||||
|
(select deleted from community c where p.community_id = c.id) as community_deleted,
|
||||||
|
(select nsfw from community c where p.community_id = c.id) as community_nsfw,
|
||||||
|
(select count(*) from comment where comment.post_id = p.id) as number_of_comments,
|
||||||
|
coalesce(sum(pl.score), 0) as score,
|
||||||
|
count (case when pl.score = 1 then 1 else null end) as upvotes,
|
||||||
|
count (case when pl.score = -1 then 1 else null end) as downvotes,
|
||||||
|
hot_rank(coalesce(sum(pl.score) , 0),
|
||||||
|
(
|
||||||
|
case when (p.published < ('now'::timestamp - '1 month'::interval)) then p.published -- Prevents necro-bumps
|
||||||
|
else greatest(c.recent_comment_time, p.published)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
) as hot_rank,
|
||||||
|
(
|
||||||
|
case when (p.published < ('now'::timestamp - '1 month'::interval)) then p.published -- Prevents necro-bumps
|
||||||
|
else greatest(c.recent_comment_time, p.published)
|
||||||
|
end
|
||||||
|
) as newest_activity_time
|
||||||
|
from post p
|
||||||
|
left join post_like pl on p.id = pl.post_id
|
||||||
|
left join (
|
||||||
|
select post_id,
|
||||||
|
max(published) as recent_comment_time
|
||||||
|
from comment
|
||||||
|
group by 1
|
||||||
|
) c on p.id = c.post_id
|
||||||
|
group by p.id, c.recent_comment_time;
|
||||||
|
|
||||||
|
create materialized view post_aggregates_mview as select * from post_aggregates_view;
|
||||||
|
|
||||||
|
create unique index idx_post_aggregates_mview_id on post_aggregates_mview (id);
|
||||||
|
|
||||||
|
create view post_view as
|
||||||
|
with all_post as (
|
||||||
|
select
|
||||||
|
pa.*
|
||||||
|
from post_aggregates_view pa
|
||||||
|
)
|
||||||
|
select
|
||||||
|
ap.*,
|
||||||
|
u.id as user_id,
|
||||||
|
coalesce(pl.score, 0) as my_vote,
|
||||||
|
(select cf.id::bool from community_follower cf where u.id = cf.user_id and cf.community_id = ap.community_id) as subscribed,
|
||||||
|
(select pr.id::bool from post_read pr where u.id = pr.user_id and pr.post_id = ap.id) as read,
|
||||||
|
(select ps.id::bool from post_saved ps where u.id = ps.user_id and ps.post_id = ap.id) as saved
|
||||||
|
from user_ u
|
||||||
|
cross join all_post ap
|
||||||
|
left join post_like pl on u.id = pl.user_id and ap.id = pl.post_id
|
||||||
|
|
||||||
|
union all
|
||||||
|
|
||||||
|
select
|
||||||
|
ap.*,
|
||||||
|
null as user_id,
|
||||||
|
null as my_vote,
|
||||||
|
null as subscribed,
|
||||||
|
null as read,
|
||||||
|
null as saved
|
||||||
|
from all_post ap
|
||||||
|
;
|
||||||
|
|
||||||
|
create view post_mview as
|
||||||
|
with all_post as (
|
||||||
|
select
|
||||||
|
pa.*
|
||||||
|
from post_aggregates_mview pa
|
||||||
|
)
|
||||||
|
select
|
||||||
|
ap.*,
|
||||||
|
u.id as user_id,
|
||||||
|
coalesce(pl.score, 0) as my_vote,
|
||||||
|
(select cf.id::bool from community_follower cf where u.id = cf.user_id and cf.community_id = ap.community_id) as subscribed,
|
||||||
|
(select pr.id::bool from post_read pr where u.id = pr.user_id and pr.post_id = ap.id) as read,
|
||||||
|
(select ps.id::bool from post_saved ps where u.id = ps.user_id and ps.post_id = ap.id) as saved
|
||||||
|
from user_ u
|
||||||
|
cross join all_post ap
|
||||||
|
left join post_like pl on u.id = pl.user_id and ap.id = pl.post_id
|
||||||
|
|
||||||
|
union all
|
||||||
|
|
||||||
|
select
|
||||||
|
ap.*,
|
||||||
|
null as user_id,
|
||||||
|
null as my_vote,
|
||||||
|
null as subscribed,
|
||||||
|
null as read,
|
||||||
|
null as saved
|
||||||
|
from all_post ap
|
||||||
|
;
|
||||||
|
|
115
server/migrations/2020-03-06-202329_add_post_iframely_data/up.sql
vendored
Normal file
115
server/migrations/2020-03-06-202329_add_post_iframely_data/up.sql
vendored
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
-- Add the columns
|
||||||
|
alter table post add column embed_title text;
|
||||||
|
alter table post add column embed_description text;
|
||||||
|
alter table post add column embed_html text;
|
||||||
|
alter table post add column thumbnail_url text;
|
||||||
|
|
||||||
|
-- Regenerate the views
|
||||||
|
|
||||||
|
-- Adds a newest_activity_time for the post_views, in order to sort by newest comment
|
||||||
|
drop view post_view;
|
||||||
|
drop view post_mview;
|
||||||
|
drop materialized view post_aggregates_mview;
|
||||||
|
drop view post_aggregates_view;
|
||||||
|
|
||||||
|
-- regen post view
|
||||||
|
create view post_aggregates_view as
|
||||||
|
select
|
||||||
|
p.*,
|
||||||
|
(select u.banned from user_ u where p.creator_id = u.id) as banned,
|
||||||
|
(select cb.id::bool from community_user_ban cb where p.creator_id = cb.user_id and p.community_id = cb.community_id) as banned_from_community,
|
||||||
|
(select name from user_ where p.creator_id = user_.id) as creator_name,
|
||||||
|
(select avatar from user_ where p.creator_id = user_.id) as creator_avatar,
|
||||||
|
(select name from community where p.community_id = community.id) as community_name,
|
||||||
|
(select removed from community c where p.community_id = c.id) as community_removed,
|
||||||
|
(select deleted from community c where p.community_id = c.id) as community_deleted,
|
||||||
|
(select nsfw from community c where p.community_id = c.id) as community_nsfw,
|
||||||
|
(select count(*) from comment where comment.post_id = p.id) as number_of_comments,
|
||||||
|
coalesce(sum(pl.score), 0) as score,
|
||||||
|
count (case when pl.score = 1 then 1 else null end) as upvotes,
|
||||||
|
count (case when pl.score = -1 then 1 else null end) as downvotes,
|
||||||
|
hot_rank(coalesce(sum(pl.score) , 0),
|
||||||
|
(
|
||||||
|
case when (p.published < ('now'::timestamp - '1 month'::interval)) then p.published -- Prevents necro-bumps
|
||||||
|
else greatest(c.recent_comment_time, p.published)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
) as hot_rank,
|
||||||
|
(
|
||||||
|
case when (p.published < ('now'::timestamp - '1 month'::interval)) then p.published -- Prevents necro-bumps
|
||||||
|
else greatest(c.recent_comment_time, p.published)
|
||||||
|
end
|
||||||
|
) as newest_activity_time
|
||||||
|
from post p
|
||||||
|
left join post_like pl on p.id = pl.post_id
|
||||||
|
left join (
|
||||||
|
select post_id,
|
||||||
|
max(published) as recent_comment_time
|
||||||
|
from comment
|
||||||
|
group by 1
|
||||||
|
) c on p.id = c.post_id
|
||||||
|
group by p.id, c.recent_comment_time;
|
||||||
|
|
||||||
|
create materialized view post_aggregates_mview as select * from post_aggregates_view;
|
||||||
|
|
||||||
|
create unique index idx_post_aggregates_mview_id on post_aggregates_mview (id);
|
||||||
|
|
||||||
|
create view post_view as
|
||||||
|
with all_post as (
|
||||||
|
select
|
||||||
|
pa.*
|
||||||
|
from post_aggregates_view pa
|
||||||
|
)
|
||||||
|
select
|
||||||
|
ap.*,
|
||||||
|
u.id as user_id,
|
||||||
|
coalesce(pl.score, 0) as my_vote,
|
||||||
|
(select cf.id::bool from community_follower cf where u.id = cf.user_id and cf.community_id = ap.community_id) as subscribed,
|
||||||
|
(select pr.id::bool from post_read pr where u.id = pr.user_id and pr.post_id = ap.id) as read,
|
||||||
|
(select ps.id::bool from post_saved ps where u.id = ps.user_id and ps.post_id = ap.id) as saved
|
||||||
|
from user_ u
|
||||||
|
cross join all_post ap
|
||||||
|
left join post_like pl on u.id = pl.user_id and ap.id = pl.post_id
|
||||||
|
|
||||||
|
union all
|
||||||
|
|
||||||
|
select
|
||||||
|
ap.*,
|
||||||
|
null as user_id,
|
||||||
|
null as my_vote,
|
||||||
|
null as subscribed,
|
||||||
|
null as read,
|
||||||
|
null as saved
|
||||||
|
from all_post ap
|
||||||
|
;
|
||||||
|
|
||||||
|
create view post_mview as
|
||||||
|
with all_post as (
|
||||||
|
select
|
||||||
|
pa.*
|
||||||
|
from post_aggregates_mview pa
|
||||||
|
)
|
||||||
|
select
|
||||||
|
ap.*,
|
||||||
|
u.id as user_id,
|
||||||
|
coalesce(pl.score, 0) as my_vote,
|
||||||
|
(select cf.id::bool from community_follower cf where u.id = cf.user_id and cf.community_id = ap.community_id) as subscribed,
|
||||||
|
(select pr.id::bool from post_read pr where u.id = pr.user_id and pr.post_id = ap.id) as read,
|
||||||
|
(select ps.id::bool from post_saved ps where u.id = ps.user_id and ps.post_id = ap.id) as saved
|
||||||
|
from user_ u
|
||||||
|
cross join all_post ap
|
||||||
|
left join post_like pl on u.id = pl.user_id and ap.id = pl.post_id
|
||||||
|
|
||||||
|
union all
|
||||||
|
|
||||||
|
select
|
||||||
|
ap.*,
|
||||||
|
null as user_id,
|
||||||
|
null as my_vote,
|
||||||
|
null as subscribed,
|
||||||
|
null as read,
|
||||||
|
null as saved
|
||||||
|
from all_post ap
|
||||||
|
;
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,8 @@ use crate::db::user_mention_view::*;
|
||||||
use crate::db::user_view::*;
|
use crate::db::user_view::*;
|
||||||
use crate::db::*;
|
use crate::db::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
extract_usernames, naive_from_unix, naive_now, remove_slurs, slur_check, slurs_vec_to_str,
|
extract_usernames, fetch_iframely_and_pictshare_data, naive_from_unix, naive_now, remove_slurs,
|
||||||
|
slur_check, slurs_vec_to_str,
|
||||||
};
|
};
|
||||||
use diesel::PgConnection;
|
use diesel::PgConnection;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
|
|
@ -110,6 +110,10 @@ impl Perform<PostResponse> for Oper<CreatePost> {
|
||||||
return Err(APIError::err("site_ban").into());
|
return Err(APIError::err("site_ban").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch Iframely and Pictshare cached image
|
||||||
|
let (iframely_title, iframely_description, iframely_html, pictshare_thumbnail) =
|
||||||
|
fetch_iframely_and_pictshare_data(data.url.to_owned());
|
||||||
|
|
||||||
let post_form = PostForm {
|
let post_form = PostForm {
|
||||||
name: data.name.to_owned(),
|
name: data.name.to_owned(),
|
||||||
url: data.url.to_owned(),
|
url: data.url.to_owned(),
|
||||||
|
@ -122,6 +126,10 @@ impl Perform<PostResponse> for Oper<CreatePost> {
|
||||||
locked: None,
|
locked: None,
|
||||||
stickied: None,
|
stickied: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
|
embed_title: iframely_title,
|
||||||
|
embed_description: iframely_description,
|
||||||
|
embed_html: iframely_html,
|
||||||
|
thumbnail_url: pictshare_thumbnail,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_post = match Post::create(&conn, &post_form) {
|
let inserted_post = match Post::create(&conn, &post_form) {
|
||||||
|
@ -353,6 +361,10 @@ impl Perform<PostResponse> for Oper<EditPost> {
|
||||||
return Err(APIError::err("site_ban").into());
|
return Err(APIError::err("site_ban").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch Iframely and Pictshare cached image
|
||||||
|
let (iframely_title, iframely_description, iframely_html, pictshare_thumbnail) =
|
||||||
|
fetch_iframely_and_pictshare_data(data.url.to_owned());
|
||||||
|
|
||||||
let post_form = PostForm {
|
let post_form = PostForm {
|
||||||
name: data.name.to_owned(),
|
name: data.name.to_owned(),
|
||||||
url: data.url.to_owned(),
|
url: data.url.to_owned(),
|
||||||
|
@ -365,6 +377,10 @@ impl Perform<PostResponse> for Oper<EditPost> {
|
||||||
locked: data.locked.to_owned(),
|
locked: data.locked.to_owned(),
|
||||||
stickied: data.stickied.to_owned(),
|
stickied: data.stickied.to_owned(),
|
||||||
updated: Some(naive_now()),
|
updated: Some(naive_now()),
|
||||||
|
embed_title: iframely_title,
|
||||||
|
embed_description: iframely_description,
|
||||||
|
embed_html: iframely_html,
|
||||||
|
thumbnail_url: pictshare_thumbnail,
|
||||||
};
|
};
|
||||||
|
|
||||||
let _updated_post = match Post::update(&conn, data.edit_id, &post_form) {
|
let _updated_post = match Post::update(&conn, data.edit_id, &post_form) {
|
||||||
|
|
|
@ -883,6 +883,10 @@ impl Perform<LoginResponse> for Oper<DeleteAccount> {
|
||||||
locked: None,
|
locked: None,
|
||||||
stickied: None,
|
stickied: None,
|
||||||
updated: Some(naive_now()),
|
updated: Some(naive_now()),
|
||||||
|
embed_title: None,
|
||||||
|
embed_description: None,
|
||||||
|
embed_html: None,
|
||||||
|
thumbnail_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let _updated_post = match Post::update(&conn, post.id, &post_form) {
|
let _updated_post = match Post::update(&conn, post.id, &post_form) {
|
||||||
|
|
|
@ -83,6 +83,10 @@ mod tests {
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
deleted: false,
|
deleted: false,
|
||||||
updated: None,
|
updated: None,
|
||||||
|
embed_title: None,
|
||||||
|
embed_description: None,
|
||||||
|
embed_html: None,
|
||||||
|
thumbnail_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let page = post.as_page();
|
let page = post.as_page();
|
||||||
|
|
|
@ -216,6 +216,10 @@ mod tests {
|
||||||
stickied: None,
|
stickied: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
|
embed_title: None,
|
||||||
|
embed_description: None,
|
||||||
|
embed_html: None,
|
||||||
|
thumbnail_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_post = Post::create(&conn, &new_post).unwrap();
|
let inserted_post = Post::create(&conn, &new_post).unwrap();
|
||||||
|
|
|
@ -480,6 +480,10 @@ mod tests {
|
||||||
stickied: None,
|
stickied: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
|
embed_title: None,
|
||||||
|
embed_description: None,
|
||||||
|
embed_html: None,
|
||||||
|
thumbnail_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_post = Post::create(&conn, &new_post).unwrap();
|
let inserted_post = Post::create(&conn, &new_post).unwrap();
|
||||||
|
|
|
@ -506,6 +506,10 @@ mod tests {
|
||||||
stickied: None,
|
stickied: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
|
embed_title: None,
|
||||||
|
embed_description: None,
|
||||||
|
embed_html: None,
|
||||||
|
thumbnail_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_post = Post::create(&conn, &new_post).unwrap();
|
let inserted_post = Post::create(&conn, &new_post).unwrap();
|
||||||
|
|
|
@ -17,6 +17,10 @@ pub struct Post {
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
pub nsfw: bool,
|
pub nsfw: bool,
|
||||||
pub stickied: bool,
|
pub stickied: bool,
|
||||||
|
pub embed_title: Option<String>,
|
||||||
|
pub embed_description: Option<String>,
|
||||||
|
pub embed_html: Option<String>,
|
||||||
|
pub thumbnail_url: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Insertable, AsChangeset, Clone)]
|
#[derive(Insertable, AsChangeset, Clone)]
|
||||||
|
@ -33,6 +37,10 @@ pub struct PostForm {
|
||||||
pub deleted: Option<bool>,
|
pub deleted: Option<bool>,
|
||||||
pub nsfw: bool,
|
pub nsfw: bool,
|
||||||
pub stickied: Option<bool>,
|
pub stickied: Option<bool>,
|
||||||
|
pub embed_title: Option<String>,
|
||||||
|
pub embed_description: Option<String>,
|
||||||
|
pub embed_html: Option<String>,
|
||||||
|
pub thumbnail_url: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<PostForm> for Post {
|
impl Crud<PostForm> for Post {
|
||||||
|
@ -229,6 +237,10 @@ mod tests {
|
||||||
stickied: None,
|
stickied: None,
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
updated: None,
|
updated: None,
|
||||||
|
embed_title: None,
|
||||||
|
embed_description: None,
|
||||||
|
embed_html: None,
|
||||||
|
thumbnail_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_post = Post::create(&conn, &new_post).unwrap();
|
let inserted_post = Post::create(&conn, &new_post).unwrap();
|
||||||
|
@ -247,6 +259,10 @@ mod tests {
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
deleted: false,
|
deleted: false,
|
||||||
updated: None,
|
updated: None,
|
||||||
|
embed_title: None,
|
||||||
|
embed_description: None,
|
||||||
|
embed_html: None,
|
||||||
|
thumbnail_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Post Like
|
// Post Like
|
||||||
|
|
|
@ -17,9 +17,54 @@ table! {
|
||||||
updated -> Nullable<Timestamp>,
|
updated -> Nullable<Timestamp>,
|
||||||
deleted -> Bool,
|
deleted -> Bool,
|
||||||
nsfw -> Bool,
|
nsfw -> Bool,
|
||||||
|
stickied -> Bool,
|
||||||
|
embed_title -> Nullable<Text>,
|
||||||
|
embed_description -> Nullable<Text>,
|
||||||
|
embed_html -> Nullable<Text>,
|
||||||
|
thumbnail_url -> Nullable<Text>,
|
||||||
banned -> Bool,
|
banned -> Bool,
|
||||||
banned_from_community -> Bool,
|
banned_from_community -> Bool,
|
||||||
|
creator_name -> Varchar,
|
||||||
|
creator_avatar -> Nullable<Text>,
|
||||||
|
community_name -> Varchar,
|
||||||
|
community_removed -> Bool,
|
||||||
|
community_deleted -> Bool,
|
||||||
|
community_nsfw -> Bool,
|
||||||
|
number_of_comments -> BigInt,
|
||||||
|
score -> BigInt,
|
||||||
|
upvotes -> BigInt,
|
||||||
|
downvotes -> BigInt,
|
||||||
|
hot_rank -> Int4,
|
||||||
|
newest_activity_time -> Timestamp,
|
||||||
|
user_id -> Nullable<Int4>,
|
||||||
|
my_vote -> Nullable<Int4>,
|
||||||
|
subscribed -> Nullable<Bool>,
|
||||||
|
read -> Nullable<Bool>,
|
||||||
|
saved -> Nullable<Bool>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table! {
|
||||||
|
post_mview (id) {
|
||||||
|
id -> Int4,
|
||||||
|
name -> Varchar,
|
||||||
|
url -> Nullable<Text>,
|
||||||
|
body -> Nullable<Text>,
|
||||||
|
creator_id -> Int4,
|
||||||
|
community_id -> Int4,
|
||||||
|
removed -> Bool,
|
||||||
|
locked -> Bool,
|
||||||
|
published -> Timestamp,
|
||||||
|
updated -> Nullable<Timestamp>,
|
||||||
|
deleted -> Bool,
|
||||||
|
nsfw -> Bool,
|
||||||
stickied -> Bool,
|
stickied -> Bool,
|
||||||
|
embed_title -> Nullable<Text>,
|
||||||
|
embed_description -> Nullable<Text>,
|
||||||
|
embed_html -> Nullable<Text>,
|
||||||
|
thumbnail_url -> Nullable<Text>,
|
||||||
|
banned -> Bool,
|
||||||
|
banned_from_community -> Bool,
|
||||||
creator_name -> Varchar,
|
creator_name -> Varchar,
|
||||||
creator_avatar -> Nullable<Text>,
|
creator_avatar -> Nullable<Text>,
|
||||||
community_name -> Varchar,
|
community_name -> Varchar,
|
||||||
|
@ -57,9 +102,13 @@ pub struct PostView {
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
pub nsfw: bool,
|
pub nsfw: bool,
|
||||||
|
pub stickied: bool,
|
||||||
|
pub embed_title: Option<String>,
|
||||||
|
pub embed_description: Option<String>,
|
||||||
|
pub embed_html: Option<String>,
|
||||||
|
pub thumbnail_url: Option<String>,
|
||||||
pub banned: bool,
|
pub banned: bool,
|
||||||
pub banned_from_community: bool,
|
pub banned_from_community: bool,
|
||||||
pub stickied: bool,
|
|
||||||
pub creator_name: String,
|
pub creator_name: String,
|
||||||
pub creator_avatar: Option<String>,
|
pub creator_avatar: Option<String>,
|
||||||
pub community_name: String,
|
pub community_name: String,
|
||||||
|
@ -79,44 +128,6 @@ pub struct PostView {
|
||||||
pub saved: Option<bool>,
|
pub saved: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// The faked schema since diesel doesn't do views
|
|
||||||
table! {
|
|
||||||
post_mview (id) {
|
|
||||||
id -> Int4,
|
|
||||||
name -> Varchar,
|
|
||||||
url -> Nullable<Text>,
|
|
||||||
body -> Nullable<Text>,
|
|
||||||
creator_id -> Int4,
|
|
||||||
community_id -> Int4,
|
|
||||||
removed -> Bool,
|
|
||||||
locked -> Bool,
|
|
||||||
published -> Timestamp,
|
|
||||||
updated -> Nullable<Timestamp>,
|
|
||||||
deleted -> Bool,
|
|
||||||
nsfw -> Bool,
|
|
||||||
banned -> Bool,
|
|
||||||
banned_from_community -> Bool,
|
|
||||||
stickied -> Bool,
|
|
||||||
creator_name -> Varchar,
|
|
||||||
creator_avatar -> Nullable<Text>,
|
|
||||||
community_name -> Varchar,
|
|
||||||
community_removed -> Bool,
|
|
||||||
community_deleted -> Bool,
|
|
||||||
community_nsfw -> Bool,
|
|
||||||
number_of_comments -> BigInt,
|
|
||||||
score -> BigInt,
|
|
||||||
upvotes -> BigInt,
|
|
||||||
downvotes -> BigInt,
|
|
||||||
hot_rank -> Int4,
|
|
||||||
newest_activity_time -> Timestamp,
|
|
||||||
user_id -> Nullable<Int4>,
|
|
||||||
my_vote -> Nullable<Int4>,
|
|
||||||
subscribed -> Nullable<Bool>,
|
|
||||||
read -> Nullable<Bool>,
|
|
||||||
saved -> Nullable<Bool>,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PostQueryBuilder<'a> {
|
pub struct PostQueryBuilder<'a> {
|
||||||
conn: &'a PgConnection,
|
conn: &'a PgConnection,
|
||||||
query: BoxedQuery<'a, Pg>,
|
query: BoxedQuery<'a, Pg>,
|
||||||
|
@ -394,6 +405,10 @@ mod tests {
|
||||||
stickied: None,
|
stickied: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
|
embed_title: None,
|
||||||
|
embed_description: None,
|
||||||
|
embed_html: None,
|
||||||
|
thumbnail_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_post = Post::create(&conn, &new_post).unwrap();
|
let inserted_post = Post::create(&conn, &new_post).unwrap();
|
||||||
|
@ -454,6 +469,10 @@ mod tests {
|
||||||
read: None,
|
read: None,
|
||||||
saved: None,
|
saved: None,
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
|
embed_title: None,
|
||||||
|
embed_description: None,
|
||||||
|
embed_html: None,
|
||||||
|
thumbnail_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let expected_post_listing_with_user = PostView {
|
let expected_post_listing_with_user = PostView {
|
||||||
|
@ -489,6 +508,10 @@ mod tests {
|
||||||
read: None,
|
read: None,
|
||||||
saved: None,
|
saved: None,
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
|
embed_title: None,
|
||||||
|
embed_description: None,
|
||||||
|
embed_html: None,
|
||||||
|
thumbnail_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let read_post_listings_with_user = PostQueryBuilder::create(&conn)
|
let read_post_listings_with_user = PostQueryBuilder::create(&conn)
|
||||||
|
|
|
@ -132,6 +132,10 @@ mod tests {
|
||||||
stickied: None,
|
stickied: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
|
embed_title: None,
|
||||||
|
embed_description: None,
|
||||||
|
embed_html: None,
|
||||||
|
thumbnail_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_post = Post::create(&conn, &new_post).unwrap();
|
let inserted_post = Post::create(&conn, &new_post).unwrap();
|
||||||
|
|
|
@ -33,14 +33,17 @@ pub mod websocket;
|
||||||
|
|
||||||
use crate::settings::Settings;
|
use crate::settings::Settings;
|
||||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||||
|
use chttp::prelude::*;
|
||||||
use lettre::smtp::authentication::{Credentials, Mechanism};
|
use lettre::smtp::authentication::{Credentials, Mechanism};
|
||||||
use lettre::smtp::extension::ClientId;
|
use lettre::smtp::extension::ClientId;
|
||||||
use lettre::smtp::ConnectionReuseParameters;
|
use lettre::smtp::ConnectionReuseParameters;
|
||||||
use lettre::{ClientSecurity, SmtpClient, Transport};
|
use lettre::{ClientSecurity, SmtpClient, Transport};
|
||||||
use lettre_email::Email;
|
use lettre_email::Email;
|
||||||
|
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
|
||||||
use rand::distributions::Alphanumeric;
|
use rand::distributions::Alphanumeric;
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use regex::{Regex, RegexBuilder};
|
use regex::{Regex, RegexBuilder};
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
pub fn to_datetime_utc(ndt: NaiveDateTime) -> DateTime<Utc> {
|
pub fn to_datetime_utc(ndt: NaiveDateTime) -> DateTime<Utc> {
|
||||||
DateTime::<Utc>::from_utc(ndt, Utc)
|
DateTime::<Utc>::from_utc(ndt, Utc)
|
||||||
|
@ -143,6 +146,77 @@ pub fn send_email(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct IframelyResponse {
|
||||||
|
title: Option<String>,
|
||||||
|
description: Option<String>,
|
||||||
|
thumbnail_url: Option<String>,
|
||||||
|
html: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fetch_iframely(url: &str) -> Result<IframelyResponse, failure::Error> {
|
||||||
|
let fetch_url = format!("http://lemmy_iframely:8061/oembed?url={}", url);
|
||||||
|
let text = chttp::get(&fetch_url)?.text()?;
|
||||||
|
let res: IframelyResponse = serde_json::from_str(&text)?;
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct PictshareResponse {
|
||||||
|
status: String,
|
||||||
|
url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fetch_pictshare(image_url: &str) -> Result<PictshareResponse, failure::Error> {
|
||||||
|
let fetch_url = format!(
|
||||||
|
"http://lemmy_pictshare/api/geturl.php?url={}",
|
||||||
|
utf8_percent_encode(image_url, NON_ALPHANUMERIC)
|
||||||
|
);
|
||||||
|
let text = chttp::get(&fetch_url)?.text()?;
|
||||||
|
let res: PictshareResponse = serde_json::from_str(&text)?;
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fetch_iframely_and_pictshare_data(
|
||||||
|
url: Option<String>,
|
||||||
|
) -> (
|
||||||
|
Option<String>,
|
||||||
|
Option<String>,
|
||||||
|
Option<String>,
|
||||||
|
Option<String>,
|
||||||
|
) {
|
||||||
|
// Fetch iframely data
|
||||||
|
let (iframely_title, iframely_description, iframely_thumbnail_url, iframely_html) = match url {
|
||||||
|
Some(url) => match fetch_iframely(&url) {
|
||||||
|
Ok(res) => (res.title, res.description, res.thumbnail_url, res.html),
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("iframely err: {}", e);
|
||||||
|
(None, None, None, None)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => (None, None, None, None),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fetch pictshare thumbnail
|
||||||
|
let pictshare_thumbnail = match iframely_thumbnail_url {
|
||||||
|
Some(iframely_thumbnail_url) => match fetch_pictshare(&iframely_thumbnail_url) {
|
||||||
|
Ok(res) => Some(res.url),
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("pictshare err: {}", e);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
(
|
||||||
|
iframely_title,
|
||||||
|
iframely_description,
|
||||||
|
iframely_html,
|
||||||
|
pictshare_thumbnail,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{extract_usernames, is_email_regex, remove_slurs, slur_check, slurs_vec_to_str};
|
use crate::{extract_usernames, is_email_regex, remove_slurs, slur_check, slurs_vec_to_str};
|
||||||
|
@ -188,6 +262,21 @@ mod tests {
|
||||||
assert_eq!(usernames, expected);
|
assert_eq!(usernames, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These helped with testing
|
||||||
|
// #[test]
|
||||||
|
// fn test_iframely() {
|
||||||
|
// let res = fetch_iframely("https://www.redspark.nu/?p=15341");
|
||||||
|
// assert!(res.is_ok());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
// fn test_pictshare() {
|
||||||
|
// let res = fetch_pictshare("https://upload.wikimedia.org/wikipedia/en/2/27/The_Mandalorian_logo.jpg");
|
||||||
|
// assert!(res.is_ok());
|
||||||
|
// let res_other = fetch_pictshare("https://upload.wikimedia.org/wikipedia/en/2/27/The_Mandalorian_logo.jpgaoeu");
|
||||||
|
// assert!(res_other.is_err());
|
||||||
|
// }
|
||||||
|
|
||||||
// #[test]
|
// #[test]
|
||||||
// fn test_send_email() {
|
// fn test_send_email() {
|
||||||
// let result = send_email("not a subject", "test_email@gmail.com", "ur user", "<h1>HI there</h1>");
|
// let result = send_email("not a subject", "test_email@gmail.com", "ur user", "<h1>HI there</h1>");
|
||||||
|
|
|
@ -207,6 +207,10 @@ table! {
|
||||||
deleted -> Bool,
|
deleted -> Bool,
|
||||||
nsfw -> Bool,
|
nsfw -> Bool,
|
||||||
stickied -> Bool,
|
stickied -> Bool,
|
||||||
|
embed_title -> Nullable<Text>,
|
||||||
|
embed_description -> Nullable<Text>,
|
||||||
|
embed_html -> Nullable<Text>,
|
||||||
|
thumbnail_url -> Nullable<Text>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
24
ui/src/components/iframely-card.tsx
vendored
24
ui/src/components/iframely-card.tsx
vendored
|
@ -1,10 +1,10 @@
|
||||||
import { Component, linkEvent } from 'inferno';
|
import { Component, linkEvent } from 'inferno';
|
||||||
import { FramelyData } from '../interfaces';
|
import { Post } from '../interfaces';
|
||||||
import { mdToHtml } from '../utils';
|
import { mdToHtml } from '../utils';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
|
|
||||||
interface FramelyCardProps {
|
interface FramelyCardProps {
|
||||||
iframely: FramelyData;
|
post: Post;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FramelyCardState {
|
interface FramelyCardState {
|
||||||
|
@ -25,18 +25,18 @@ export class IFramelyCard extends Component<
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let iframely = this.props.iframely;
|
let post = this.props.post;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{iframely.title && !this.state.expanded && (
|
{post.embed_title && !this.state.expanded && (
|
||||||
<div class="card mt-3 mb-2">
|
<div class="card mt-3 mb-2">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title d-inline">
|
<h5 class="card-title d-inline">
|
||||||
<span>
|
<span>
|
||||||
<a class="text-body" target="_blank" href={iframely.url}>
|
<a class="text-body" target="_blank" href={post.url}>
|
||||||
{iframely.title}
|
{post.embed_title}
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
</h5>
|
</h5>
|
||||||
|
@ -44,14 +44,14 @@ export class IFramelyCard extends Component<
|
||||||
<a
|
<a
|
||||||
class="text-muted font-italic"
|
class="text-muted font-italic"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
href={iframely.url}
|
href={post.url}
|
||||||
>
|
>
|
||||||
{new URL(iframely.url).hostname}
|
{new URL(post.url).hostname}
|
||||||
<svg class="ml-1 icon">
|
<svg class="ml-1 icon">
|
||||||
<use xlinkHref="#icon-external-link"></use>
|
<use xlinkHref="#icon-external-link"></use>
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
{iframely.html && (
|
{post.embed_html && (
|
||||||
<span
|
<span
|
||||||
class="ml-2 pointer text-monospace"
|
class="ml-2 pointer text-monospace"
|
||||||
onClick={linkEvent(this, this.handleIframeExpand)}
|
onClick={linkEvent(this, this.handleIframeExpand)}
|
||||||
|
@ -61,10 +61,10 @@ export class IFramelyCard extends Component<
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
{iframely.description && (
|
{post.embed_description && (
|
||||||
<div
|
<div
|
||||||
className="card-text small text-muted md-div"
|
className="card-text small text-muted md-div"
|
||||||
dangerouslySetInnerHTML={mdToHtml(iframely.description)}
|
dangerouslySetInnerHTML={mdToHtml(post.embed_description)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -75,7 +75,7 @@ export class IFramelyCard extends Component<
|
||||||
{this.state.expanded && (
|
{this.state.expanded && (
|
||||||
<div
|
<div
|
||||||
class="mt-3 mb-2"
|
class="mt-3 mb-2"
|
||||||
dangerouslySetInnerHTML={{ __html: iframely.html }}
|
dangerouslySetInnerHTML={{ __html: post.embed_html }}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|
6
ui/src/components/inbox.tsx
vendored
6
ui/src/components/inbox.tsx
vendored
|
@ -28,6 +28,7 @@ import {
|
||||||
saveCommentRes,
|
saveCommentRes,
|
||||||
createCommentLikeRes,
|
createCommentLikeRes,
|
||||||
commentsToFlatNodes,
|
commentsToFlatNodes,
|
||||||
|
setupTippy,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import { CommentNodes } from './comment-nodes';
|
import { CommentNodes } from './comment-nodes';
|
||||||
import { PrivateMessage } from './private-message';
|
import { PrivateMessage } from './private-message';
|
||||||
|
@ -333,18 +334,21 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
this.sendUnreadCount();
|
this.sendUnreadCount();
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
|
setupTippy();
|
||||||
} else if (res.op == UserOperation.GetUserMentions) {
|
} else if (res.op == UserOperation.GetUserMentions) {
|
||||||
let data = res.data as GetUserMentionsResponse;
|
let data = res.data as GetUserMentionsResponse;
|
||||||
this.state.mentions = data.mentions;
|
this.state.mentions = data.mentions;
|
||||||
this.sendUnreadCount();
|
this.sendUnreadCount();
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
|
setupTippy();
|
||||||
} else if (res.op == UserOperation.GetPrivateMessages) {
|
} else if (res.op == UserOperation.GetPrivateMessages) {
|
||||||
let data = res.data as PrivateMessagesResponse;
|
let data = res.data as PrivateMessagesResponse;
|
||||||
this.state.messages = data.messages;
|
this.state.messages = data.messages;
|
||||||
this.sendUnreadCount();
|
this.sendUnreadCount();
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
|
setupTippy();
|
||||||
} else if (res.op == UserOperation.EditPrivateMessage) {
|
} else if (res.op == UserOperation.EditPrivateMessage) {
|
||||||
let data = res.data as PrivateMessageResponse;
|
let data = res.data as PrivateMessageResponse;
|
||||||
let found: PrivateMessageI = this.state.messages.find(
|
let found: PrivateMessageI = this.state.messages.find(
|
||||||
|
@ -387,6 +391,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
}
|
}
|
||||||
this.sendUnreadCount();
|
this.sendUnreadCount();
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
|
setupTippy();
|
||||||
} else if (res.op == UserOperation.EditUserMention) {
|
} else if (res.op == UserOperation.EditUserMention) {
|
||||||
let data = res.data as UserMentionResponse;
|
let data = res.data as UserMentionResponse;
|
||||||
|
|
||||||
|
@ -430,6 +435,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
let data = res.data as CommentResponse;
|
let data = res.data as CommentResponse;
|
||||||
saveCommentRes(data, this.state.replies);
|
saveCommentRes(data, this.state.replies);
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
|
setupTippy();
|
||||||
} else if (res.op == UserOperation.CreateCommentLike) {
|
} else if (res.op == UserOperation.CreateCommentLike) {
|
||||||
let data = res.data as CommentResponse;
|
let data = res.data as CommentResponse;
|
||||||
createCommentLikeRes(data, this.state.replies);
|
createCommentLikeRes(data, this.state.replies);
|
||||||
|
|
2
ui/src/components/post-form.tsx
vendored
2
ui/src/components/post-form.tsx
vendored
|
@ -497,7 +497,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
})
|
})
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(res => {
|
.then(res => {
|
||||||
let url = `${window.location.origin}/pictshare/${res.url}`;
|
let url = `${window.location.origin}/pictshare/${encodeURI(res.url)}`;
|
||||||
if (res.filetype == 'mp4') {
|
if (res.filetype == 'mp4') {
|
||||||
url += '/raw';
|
url += '/raw';
|
||||||
}
|
}
|
||||||
|
|
193
ui/src/components/post-listing.tsx
vendored
193
ui/src/components/post-listing.tsx
vendored
|
@ -15,7 +15,6 @@ import {
|
||||||
AddAdminForm,
|
AddAdminForm,
|
||||||
TransferSiteForm,
|
TransferSiteForm,
|
||||||
TransferCommunityForm,
|
TransferCommunityForm,
|
||||||
FramelyData,
|
|
||||||
} from '../interfaces';
|
} from '../interfaces';
|
||||||
import { MomentTime } from './moment-time';
|
import { MomentTime } from './moment-time';
|
||||||
import { PostForm } from './post-form';
|
import { PostForm } from './post-form';
|
||||||
|
@ -29,7 +28,7 @@ import {
|
||||||
getUnixTime,
|
getUnixTime,
|
||||||
pictshareAvatarThumbnail,
|
pictshareAvatarThumbnail,
|
||||||
showAvatars,
|
showAvatars,
|
||||||
imageThumbnailer,
|
pictshareImage,
|
||||||
setupTippy,
|
setupTippy,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
|
@ -51,9 +50,6 @@ interface PostListingState {
|
||||||
score: number;
|
score: number;
|
||||||
upvotes: number;
|
upvotes: number;
|
||||||
downvotes: number;
|
downvotes: number;
|
||||||
url: string;
|
|
||||||
iframely: FramelyData;
|
|
||||||
thumbnail: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PostListingProps {
|
interface PostListingProps {
|
||||||
|
@ -82,9 +78,6 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
score: this.props.post.score,
|
score: this.props.post.score,
|
||||||
upvotes: this.props.post.upvotes,
|
upvotes: this.props.post.upvotes,
|
||||||
downvotes: this.props.post.downvotes,
|
downvotes: this.props.post.downvotes,
|
||||||
url: this.props.post.url,
|
|
||||||
iframely: null,
|
|
||||||
thumbnail: null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props: any, context: any) {
|
constructor(props: any, context: any) {
|
||||||
|
@ -95,11 +88,6 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
this.handlePostDisLike = this.handlePostDisLike.bind(this);
|
this.handlePostDisLike = this.handlePostDisLike.bind(this);
|
||||||
this.handleEditPost = this.handleEditPost.bind(this);
|
this.handleEditPost = this.handleEditPost.bind(this);
|
||||||
this.handleEditCancel = this.handleEditCancel.bind(this);
|
this.handleEditCancel = this.handleEditCancel.bind(this);
|
||||||
|
|
||||||
if (this.state.url) {
|
|
||||||
this.setThumbnail();
|
|
||||||
this.fetchIframely();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps: PostListingProps) {
|
componentWillReceiveProps(nextProps: PostListingProps) {
|
||||||
|
@ -107,18 +95,6 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
this.state.upvotes = nextProps.post.upvotes;
|
this.state.upvotes = nextProps.post.upvotes;
|
||||||
this.state.downvotes = nextProps.post.downvotes;
|
this.state.downvotes = nextProps.post.downvotes;
|
||||||
this.state.score = nextProps.post.score;
|
this.state.score = nextProps.post.score;
|
||||||
|
|
||||||
if (nextProps.post.url !== this.state.url) {
|
|
||||||
this.state.url = nextProps.post.url;
|
|
||||||
if (this.state.url) {
|
|
||||||
this.setThumbnail();
|
|
||||||
this.fetchIframely();
|
|
||||||
} else {
|
|
||||||
this.state.iframely = null;
|
|
||||||
this.state.thumbnail = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,9 +123,11 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
return (
|
return (
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
{this.state.url && this.props.showBody && this.state.iframely && (
|
{this.props.post.url &&
|
||||||
<IFramelyCard iframely={this.state.iframely} />
|
this.props.showBody &&
|
||||||
)}
|
this.props.post.embed_title && (
|
||||||
|
<IFramelyCard post={this.props.post} />
|
||||||
|
)}
|
||||||
{this.props.showBody && this.props.post.body && (
|
{this.props.showBody && this.props.post.body && (
|
||||||
<>
|
<>
|
||||||
{this.state.viewSource ? (
|
{this.state.viewSource ? (
|
||||||
|
@ -167,61 +145,90 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
imgThumb() {
|
imgThumb(src: string) {
|
||||||
let post = this.props.post;
|
let post = this.props.post;
|
||||||
return (
|
return (
|
||||||
<img
|
<img
|
||||||
className={`img-fluid thumbnail rounded ${(post.nsfw ||
|
className={`img-fluid thumbnail rounded ${(post.nsfw ||
|
||||||
post.community_nsfw) &&
|
post.community_nsfw) &&
|
||||||
'img-blur'}`}
|
'img-blur'}`}
|
||||||
src={imageThumbnailer(this.state.thumbnail)}
|
src={src}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getImage(thumbnail: boolean = false) {
|
||||||
|
let post = this.props.post;
|
||||||
|
if (isImage(post.url)) {
|
||||||
|
if (post.url.includes('pictshare')) {
|
||||||
|
return pictshareImage(post.url, thumbnail);
|
||||||
|
} else {
|
||||||
|
return post.url;
|
||||||
|
}
|
||||||
|
} else if (post.thumbnail_url) {
|
||||||
|
return pictshareImage(post.thumbnail_url, thumbnail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
thumbnail() {
|
thumbnail() {
|
||||||
let post = this.props.post;
|
let post = this.props.post;
|
||||||
|
|
||||||
if (isImage(this.state.url)) {
|
if (isImage(post.url)) {
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
class="text-body pointer"
|
class="text-body pointer"
|
||||||
data-tippy-content={i18n.t('expand_here')}
|
data-tippy-content={i18n.t('expand_here')}
|
||||||
onClick={linkEvent(this, this.handleImageExpandClick)}
|
onClick={linkEvent(this, this.handleImageExpandClick)}
|
||||||
>
|
>
|
||||||
{this.imgThumb()}
|
{this.imgThumb(this.getImage(true))}
|
||||||
<svg class="icon mini-overlay">
|
<svg class="icon mini-overlay">
|
||||||
<use xlinkHref="#icon-image"></use>
|
<use xlinkHref="#icon-image"></use>
|
||||||
</svg>
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
} else if (this.state.thumbnail) {
|
} else if (post.thumbnail_url) {
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
className="text-body"
|
className="text-body"
|
||||||
href={this.state.url}
|
href={post.url}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
title={this.state.url}
|
title={post.url}
|
||||||
>
|
>
|
||||||
{this.imgThumb()}
|
{this.imgThumb(this.getImage(true))}
|
||||||
<svg class="icon mini-overlay">
|
<svg class="icon mini-overlay">
|
||||||
<use xlinkHref="#icon-external-link"></use>
|
<use xlinkHref="#icon-external-link"></use>
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
} else if (this.state.url && !this.state.thumbnail) {
|
} else if (post.url) {
|
||||||
return (
|
if (isVideo(post.url)) {
|
||||||
<a
|
return (
|
||||||
className="text-body"
|
<div class="embed-responsive embed-responsive-16by9">
|
||||||
href={this.state.url}
|
<video
|
||||||
target="_blank"
|
playsinline
|
||||||
title={this.state.url}
|
muted
|
||||||
>
|
loop
|
||||||
<svg class="icon thumbnail">
|
controls
|
||||||
<use xlinkHref="#icon-external-link"></use>
|
class="embed-responsive-item"
|
||||||
</svg>
|
>
|
||||||
</a>
|
<source src={post.url} type="video/mp4" />
|
||||||
);
|
</video>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
className="text-body"
|
||||||
|
href={post.url}
|
||||||
|
target="_blank"
|
||||||
|
title={post.url}
|
||||||
|
>
|
||||||
|
<svg class="icon thumbnail">
|
||||||
|
<use xlinkHref="#icon-external-link"></use>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
|
@ -280,19 +287,6 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
<div class="position-relative">{this.thumbnail()}</div>
|
<div class="position-relative">{this.thumbnail()}</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{this.state.url && isVideo(this.state.url) && (
|
|
||||||
<video
|
|
||||||
playsinline
|
|
||||||
muted
|
|
||||||
loop
|
|
||||||
controls
|
|
||||||
class="col-11 col-sm-2 pr-0 mt-1"
|
|
||||||
height="100"
|
|
||||||
width="150"
|
|
||||||
>
|
|
||||||
<source src={this.state.url} type="video/mp4" />
|
|
||||||
</video>
|
|
||||||
)}
|
|
||||||
<div
|
<div
|
||||||
class={`${this.state.imageExpanded ? 'col-12' : 'col-8 col-sm-9'}`}
|
class={`${this.state.imageExpanded ? 'col-12' : 'col-8 col-sm-9'}`}
|
||||||
>
|
>
|
||||||
|
@ -300,12 +294,12 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<div className="post-title">
|
<div className="post-title">
|
||||||
<h5 className="mb-0 d-inline">
|
<h5 className="mb-0 d-inline">
|
||||||
{this.props.showBody && this.state.url ? (
|
{this.props.showBody && post.url ? (
|
||||||
<a
|
<a
|
||||||
className="text-body"
|
className="text-body"
|
||||||
href={this.state.url}
|
href={post.url}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
title={this.state.url}
|
title={post.url}
|
||||||
>
|
>
|
||||||
{post.name}
|
{post.name}
|
||||||
</a>
|
</a>
|
||||||
|
@ -319,25 +313,23 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
</h5>
|
</h5>
|
||||||
{this.state.url &&
|
{post.url &&
|
||||||
!(
|
!(new URL(post.url).hostname == window.location.hostname) && (
|
||||||
new URL(this.state.url).hostname == window.location.hostname
|
|
||||||
) && (
|
|
||||||
<small class="d-inline-block">
|
<small class="d-inline-block">
|
||||||
<a
|
<a
|
||||||
className="ml-2 text-muted font-italic"
|
className="ml-2 text-muted font-italic"
|
||||||
href={this.state.url}
|
href={post.url}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
title={this.state.url}
|
title={post.url}
|
||||||
>
|
>
|
||||||
{new URL(this.state.url).hostname}
|
{new URL(post.url).hostname}
|
||||||
<svg class="ml-1 icon icon-inline">
|
<svg class="ml-1 icon icon-inline">
|
||||||
<use xlinkHref="#icon-external-link"></use>
|
<use xlinkHref="#icon-external-link"></use>
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
</small>
|
</small>
|
||||||
)}
|
)}
|
||||||
{this.state.thumbnail && (
|
{(isImage(post.url) || this.props.post.thumbnail_url) && (
|
||||||
<>
|
<>
|
||||||
{!this.state.imageExpanded ? (
|
{!this.state.imageExpanded ? (
|
||||||
<span
|
<span
|
||||||
|
@ -369,7 +361,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
class="img-fluid img-expanded"
|
class="img-fluid img-expanded"
|
||||||
src={this.state.thumbnail}
|
src={this.getImage()}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -999,53 +991,6 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchIframely() {
|
|
||||||
fetch(`/iframely/oembed?url=${this.state.url}`)
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(res => {
|
|
||||||
this.state.iframely = res;
|
|
||||||
this.setState(this.state);
|
|
||||||
|
|
||||||
// Store and fetch the image in pictshare
|
|
||||||
if (
|
|
||||||
this.state.iframely.thumbnail_url &&
|
|
||||||
isImage(this.state.iframely.thumbnail_url)
|
|
||||||
) {
|
|
||||||
fetch(
|
|
||||||
`/pictshare/api/geturl.php?url=${this.state.iframely.thumbnail_url}`
|
|
||||||
)
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(res => {
|
|
||||||
if (res.status == 'ok') {
|
|
||||||
let url = `${window.location.origin}/pictshare/${res.url}`;
|
|
||||||
if (res.filetype == 'mp4') {
|
|
||||||
url += '/raw';
|
|
||||||
}
|
|
||||||
this.state.thumbnail = url;
|
|
||||||
this.setState(this.state);
|
|
||||||
} else {
|
|
||||||
console.error(
|
|
||||||
`Couldn't cache pictshare url: ${this.state.iframely.thumbnail_url}`
|
|
||||||
);
|
|
||||||
console.error(res);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error(`Iframely service not set up properly. ${error}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setThumbnail() {
|
|
||||||
let simpleImg = isImage(this.state.url);
|
|
||||||
if (simpleImg) {
|
|
||||||
this.state.thumbnail = this.state.url;
|
|
||||||
} else {
|
|
||||||
this.state.thumbnail = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handlePostLike(i: PostListing) {
|
handlePostLike(i: PostListing) {
|
||||||
let new_vote = i.state.my_vote == 1 ? 0 : 1;
|
let new_vote = i.state.my_vote == 1 ? 0 : 1;
|
||||||
|
|
||||||
|
@ -1141,8 +1086,10 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
|
|
||||||
get crossPostParams(): string {
|
get crossPostParams(): string {
|
||||||
let params = `?title=${this.props.post.name}`;
|
let params = `?title=${this.props.post.name}`;
|
||||||
if (this.state.url) {
|
let post = this.props.post;
|
||||||
params += `&url=${this.state.url}`;
|
|
||||||
|
if (post.url) {
|
||||||
|
params += `&url=${post.url}`;
|
||||||
}
|
}
|
||||||
if (this.props.post.body) {
|
if (this.props.post.body) {
|
||||||
params += `&body=${this.props.post.body}`;
|
params += `&body=${this.props.post.body}`;
|
||||||
|
|
19
ui/src/interfaces.ts
vendored
19
ui/src/interfaces.ts
vendored
|
@ -156,6 +156,10 @@ export interface Post {
|
||||||
deleted: boolean;
|
deleted: boolean;
|
||||||
locked: boolean;
|
locked: boolean;
|
||||||
stickied: boolean;
|
stickied: boolean;
|
||||||
|
embed_title?: string;
|
||||||
|
embed_description?: string;
|
||||||
|
embed_html?: string;
|
||||||
|
thumbnail_url?: string;
|
||||||
nsfw: boolean;
|
nsfw: boolean;
|
||||||
banned: boolean;
|
banned: boolean;
|
||||||
banned_from_community: boolean;
|
banned_from_community: boolean;
|
||||||
|
@ -877,18 +881,3 @@ export interface WebSocketJsonResponse {
|
||||||
error?: string;
|
error?: string;
|
||||||
reconnect?: boolean;
|
reconnect?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FramelyData {
|
|
||||||
url: string;
|
|
||||||
type: string;
|
|
||||||
version?: string;
|
|
||||||
title: string;
|
|
||||||
author?: string;
|
|
||||||
author_url?: string;
|
|
||||||
provider_name?: string;
|
|
||||||
thumbnail_url?: string;
|
|
||||||
thumbnail_width?: number;
|
|
||||||
thumbnail_height?: number;
|
|
||||||
description?: string;
|
|
||||||
html?: string;
|
|
||||||
}
|
|
||||||
|
|
23
ui/src/utils.ts
vendored
23
ui/src/utils.ts
vendored
|
@ -404,15 +404,22 @@ export function showAvatars(): boolean {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts to image thumbnail (only supports pictshare currently)
|
// Converts to image thumbnail
|
||||||
export function imageThumbnailer(url: string): string {
|
export function pictshareImage(
|
||||||
let split = url.split('pictshare');
|
hash: string,
|
||||||
if (split.length > 1) {
|
thumbnail: boolean = false
|
||||||
let out = `${split[0]}pictshare/192${split[1]}`;
|
): string {
|
||||||
return out;
|
let root = `/pictshare`;
|
||||||
} else {
|
|
||||||
return url;
|
// Necessary for other servers / domains
|
||||||
|
if (hash.includes('pictshare')) {
|
||||||
|
let split = hash.split('/pictshare/');
|
||||||
|
root = `${split[0]}/pictshare`;
|
||||||
|
hash = split[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let out = `${root}/${thumbnail ? '192/' : ''}${hash}`;
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isCommentType(item: Comment | PrivateMessage): item is Comment {
|
export function isCommentType(item: Comment | PrivateMessage): item is Comment {
|
||||||
|
|
Loading…
Reference in a new issue