Merge pull request 'Search Actor' (#870) from search-actor into main
Reviewed-on: https://git.joinplu.me/Plume/Plume/pulls/870
This commit is contained in:
		
						commit
						46fc030df4
					
				| @ -143,6 +143,7 @@ jobs: | ||||
|         cache: <<#parameters.postgres>>postgres<</ parameters.postgres>><<^parameters.postgres>>sqlite<</parameters.postgres>> | ||||
|     - run_with_coverage: | ||||
|         cmd: | | ||||
|           cargo run -p plume-cli --no-default-features --features=${FEATURES} -- migration run | ||||
|           cmd="cargo test --all --exclude plume-front --exclude plume-macro --no-run --no-default-features --features=${FEATURES} -j" | ||||
|           for i in 36 4 2 1 1; do | ||||
|               $cmd $i && break | ||||
|  | ||||
| @ -9,6 +9,7 @@ | ||||
| - Allow `dir` attributes for LtoR text in RtoL document (#860) | ||||
| - More translation languages (#862) | ||||
| - Proxy support (#829) | ||||
| - Riker a actor system library (#870) | ||||
| 
 | ||||
| ### Changed | ||||
| 
 | ||||
| @ -16,6 +17,7 @@ | ||||
| - Use tracing crate (#868) | ||||
| - Update Rust version to nightly-2021-01-15 (#878) | ||||
| - Upgrade Tantivy to 0.13.3 and lindera-tantivy to 0.7.1 (#878) | ||||
| - Run searcher on actor system (#870) | ||||
| 
 | ||||
| ### Fixed | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										289
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										289
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -9,7 +9,7 @@ dependencies = [ | ||||
|  "activitystreams-derive", | ||||
|  "activitystreams-traits", | ||||
|  "activitystreams-types", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_derive", | ||||
|  "serde_json", | ||||
| ] | ||||
| @ -32,7 +32,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "670ef03168e704b0cae242e7a5d8b40506772b339687e01a3496fc4afe2e8542" | ||||
| dependencies = [ | ||||
|  "failure", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_json", | ||||
| ] | ||||
| 
 | ||||
| @ -46,7 +46,7 @@ dependencies = [ | ||||
|  "activitystreams-traits", | ||||
|  "chrono", | ||||
|  "mime 0.3.16", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_derive", | ||||
|  "serde_json", | ||||
| ] | ||||
| @ -126,6 +126,9 @@ name = "ahash" | ||||
| version = "0.3.8" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" | ||||
| dependencies = [ | ||||
|  "const-random", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "aho-corasick" | ||||
| @ -168,6 +171,12 @@ dependencies = [ | ||||
|  "winapi 0.3.9", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "arc-swap" | ||||
| version = "0.4.8" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "dabe5a181f83789739c194cbe5a897dde195078fac08568d09221fd6137a7ba8" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "array_tool" | ||||
| version = "1.0.3" | ||||
| @ -344,7 +353,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d" | ||||
| dependencies = [ | ||||
|  "byteorder 1.3.4", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| @ -516,8 +525,8 @@ checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" | ||||
| dependencies = [ | ||||
|  "libc", | ||||
|  "num-integer", | ||||
|  "num-traits", | ||||
|  "serde", | ||||
|  "num-traits 0.2.14", | ||||
|  "serde 1.0.118", | ||||
|  "time", | ||||
|  "winapi 0.3.9", | ||||
| ] | ||||
| @ -555,6 +564,44 @@ dependencies = [ | ||||
|  "memchr", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "config" | ||||
| version = "0.10.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "19b076e143e1d9538dde65da30f8481c2a6c44040edb8e02b9bf1351edb92ce3" | ||||
| dependencies = [ | ||||
|  "lazy_static", | ||||
|  "nom 5.1.2", | ||||
|  "rust-ini", | ||||
|  "serde 1.0.118", | ||||
|  "serde-hjson", | ||||
|  "serde_json", | ||||
|  "toml 0.5.8", | ||||
|  "yaml-rust", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "const-random" | ||||
| version = "0.1.13" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f590d95d011aa80b063ffe3253422ed5aa462af4e9867d43ce8337562bac77c4" | ||||
| dependencies = [ | ||||
|  "const-random-macro", | ||||
|  "proc-macro-hack 0.5.19", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "const-random-macro" | ||||
| version = "0.1.13" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "615f6e27d000a2bffbc7f2f6a8669179378fa27ee4d0a509e985dfc0a7defb40" | ||||
| dependencies = [ | ||||
|  "getrandom 0.2.1", | ||||
|  "lazy_static", | ||||
|  "proc-macro-hack 0.5.19", | ||||
|  "tiny-keccak", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "const_fn" | ||||
| version = "0.4.4" | ||||
| @ -607,7 +654,7 @@ dependencies = [ | ||||
|  "idna 0.1.5", | ||||
|  "log 0.4.11", | ||||
|  "publicsuffix", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_json", | ||||
|  "time", | ||||
|  "try_from", | ||||
| @ -789,6 +836,17 @@ version = "0.1.7" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "dashmap" | ||||
| version = "3.11.10" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0f260e2fc850179ef410018660006951c1b55b79e8087e87111a2c388994b9b5" | ||||
| dependencies = [ | ||||
|  "ahash", | ||||
|  "cfg-if 0.1.10", | ||||
|  "num_cpus", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "data-encoding" | ||||
| version = "2.1.2" | ||||
| @ -1370,6 +1428,17 @@ dependencies = [ | ||||
|  "wasi 0.9.0+wasi-snapshot-preview1", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "getrandom" | ||||
| version = "0.2.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "4060f4657be78b8e766215b02b18a2e862d83745545de804638e2b545e81aee6" | ||||
| dependencies = [ | ||||
|  "cfg-if 1.0.0", | ||||
|  "libc", | ||||
|  "wasi 0.10.0+wasi-snapshot-preview1", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "gettext" | ||||
| version = "0.3.0" | ||||
| @ -1943,7 +2012,7 @@ dependencies = [ | ||||
|  "log 0.4.11", | ||||
|  "native-tls", | ||||
|  "nom 4.2.3", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_derive", | ||||
|  "serde_json", | ||||
| ] | ||||
| @ -2010,7 +2079,7 @@ dependencies = [ | ||||
|  "lindera-dictionary", | ||||
|  "lindera-ipadic", | ||||
|  "lindera-ipadic-builder", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_json", | ||||
| ] | ||||
| 
 | ||||
| @ -2023,7 +2092,7 @@ dependencies = [ | ||||
|  "bincode", | ||||
|  "byteorder 1.3.4", | ||||
|  "encoding", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "yada", | ||||
| ] | ||||
| 
 | ||||
| @ -2091,9 +2160,13 @@ dependencies = [ | ||||
| 
 | ||||
| [[package]] | ||||
| name = "linked-hash-map" | ||||
| version = "0.5.3" | ||||
| version = "0.3.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" | ||||
| checksum = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd" | ||||
| dependencies = [ | ||||
|  "serde 0.8.23", | ||||
|  "serde_test", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "lock_api" | ||||
| @ -2152,7 +2225,7 @@ dependencies = [ | ||||
|  "log 0.4.11", | ||||
|  "phf", | ||||
|  "phf_codegen", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_derive", | ||||
|  "serde_json", | ||||
|  "string_cache", | ||||
| @ -2504,7 +2577,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" | ||||
| dependencies = [ | ||||
|  "autocfg 1.0.1", | ||||
|  "num-traits", | ||||
|  "num-traits 0.2.14", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| @ -2515,7 +2588,16 @@ checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" | ||||
| dependencies = [ | ||||
|  "autocfg 1.0.1", | ||||
|  "num-integer", | ||||
|  "num-traits", | ||||
|  "num-traits 0.2.14", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "num-traits" | ||||
| version = "0.1.43" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" | ||||
| dependencies = [ | ||||
|  "num-traits 0.2.14", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| @ -2826,7 +2908,7 @@ dependencies = [ | ||||
|  "chrono", | ||||
|  "indexmap", | ||||
|  "line-wrap", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "xml-rs", | ||||
| ] | ||||
| 
 | ||||
| @ -2854,6 +2936,7 @@ dependencies = [ | ||||
|  "plume-api", | ||||
|  "plume-common", | ||||
|  "plume-models", | ||||
|  "riker", | ||||
|  "rocket", | ||||
|  "rocket_contrib", | ||||
|  "rocket_csrf", | ||||
| @ -2862,7 +2945,7 @@ dependencies = [ | ||||
|  "rsass", | ||||
|  "ructe", | ||||
|  "scheduled-thread-pool", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_json", | ||||
|  "shrinkwraprs 0.2.3", | ||||
|  "tracing", | ||||
| @ -2876,7 +2959,7 @@ dependencies = [ | ||||
| name = "plume-api" | ||||
| version = "0.6.1-dev" | ||||
| dependencies = [ | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_derive", | ||||
| ] | ||||
| 
 | ||||
| @ -2909,7 +2992,7 @@ dependencies = [ | ||||
|  "regex-syntax 0.6.21", | ||||
|  "reqwest 0.9.24", | ||||
|  "rocket", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_derive", | ||||
|  "serde_json", | ||||
|  "shrinkwraprs 0.3.0", | ||||
| @ -2926,7 +3009,7 @@ dependencies = [ | ||||
|  "gettext-macros", | ||||
|  "gettext-utils", | ||||
|  "lazy_static", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_json", | ||||
|  "stdweb", | ||||
|  "stdweb-internal-runtime", | ||||
| @ -2961,15 +3044,17 @@ dependencies = [ | ||||
|  "ldap3", | ||||
|  "lindera-tantivy", | ||||
|  "migrations_internals", | ||||
|  "once_cell", | ||||
|  "openssl", | ||||
|  "plume-api", | ||||
|  "plume-common", | ||||
|  "plume-macro", | ||||
|  "reqwest 0.9.24", | ||||
|  "riker", | ||||
|  "rocket", | ||||
|  "rocket_i18n", | ||||
|  "scheduled-thread-pool", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_derive", | ||||
|  "serde_json", | ||||
|  "shrinkwraprs 0.2.3", | ||||
| @ -3220,7 +3305,7 @@ version = "0.7.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" | ||||
| dependencies = [ | ||||
|  "getrandom", | ||||
|  "getrandom 0.1.15", | ||||
|  "libc", | ||||
|  "rand_chacha 0.2.2", | ||||
|  "rand_core 0.5.1", | ||||
| @ -3268,7 +3353,7 @@ version = "0.5.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" | ||||
| dependencies = [ | ||||
|  "getrandom", | ||||
|  "getrandom 0.1.15", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| @ -3445,7 +3530,7 @@ dependencies = [ | ||||
|  "mime 0.3.16", | ||||
|  "mime_guess 2.0.3", | ||||
|  "native-tls", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_json", | ||||
|  "serde_urlencoded 0.5.5", | ||||
|  "socks", | ||||
| @ -3484,7 +3569,7 @@ dependencies = [ | ||||
|  "native-tls", | ||||
|  "percent-encoding 2.1.0", | ||||
|  "pin-project-lite 0.2.0", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_urlencoded 0.7.0", | ||||
|  "tokio 0.2.24", | ||||
|  "tokio-tls", | ||||
| @ -3495,6 +3580,38 @@ dependencies = [ | ||||
|  "winreg 0.7.0", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "riker" | ||||
| version = "0.4.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "abff93ece5a5d3d7f2c54dfba7550657a644c9dc0a871c7ddf8c31381971c41b" | ||||
| dependencies = [ | ||||
|  "chrono", | ||||
|  "config", | ||||
|  "dashmap", | ||||
|  "futures 0.3.8", | ||||
|  "num_cpus", | ||||
|  "pin-utils", | ||||
|  "rand 0.7.3", | ||||
|  "regex", | ||||
|  "riker-macros", | ||||
|  "slog", | ||||
|  "slog-scope", | ||||
|  "slog-stdlog", | ||||
|  "uuid 0.8.1", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "riker-macros" | ||||
| version = "0.2.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d2a8e8f71c9e7980a596c39c7e3537ea8563054526e15712a610ac97a02dba15" | ||||
| dependencies = [ | ||||
|  "proc-macro2 0.4.30", | ||||
|  "quote 0.6.13", | ||||
|  "syn 0.15.44", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "ring" | ||||
| version = "0.13.5" | ||||
| @ -3523,7 +3640,7 @@ dependencies = [ | ||||
|  "rocket_http", | ||||
|  "state", | ||||
|  "time", | ||||
|  "toml", | ||||
|  "toml 0.4.10", | ||||
|  "version_check 0.9.2", | ||||
|  "yansi", | ||||
| ] | ||||
| @ -3552,7 +3669,7 @@ dependencies = [ | ||||
|  "log 0.4.11", | ||||
|  "notify", | ||||
|  "rocket", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_json", | ||||
| ] | ||||
| 
 | ||||
| @ -3564,7 +3681,7 @@ dependencies = [ | ||||
|  "data-encoding", | ||||
|  "ring", | ||||
|  "rocket", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "time", | ||||
| ] | ||||
| 
 | ||||
| @ -3623,7 +3740,7 @@ dependencies = [ | ||||
|  "lazy_static", | ||||
|  "nom 4.2.3", | ||||
|  "num-rational", | ||||
|  "num-traits", | ||||
|  "num-traits 0.2.14", | ||||
|  "rand 0.6.5", | ||||
| ] | ||||
| 
 | ||||
| @ -3640,13 +3757,19 @@ dependencies = [ | ||||
|  "nom 5.1.2", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "rust-ini" | ||||
| version = "0.13.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "rust-stemmers" | ||||
| version = "1.2.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e46a2036019fdb888131db7a4c847a1063a7493f971ed94ea82c67eada63ca54" | ||||
| dependencies = [ | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_derive", | ||||
| ] | ||||
| 
 | ||||
| @ -3749,6 +3872,12 @@ version = "0.7.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde" | ||||
| version = "0.8.23" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde" | ||||
| version = "1.0.118" | ||||
| @ -3758,6 +3887,19 @@ dependencies = [ | ||||
|  "serde_derive", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde-hjson" | ||||
| version = "0.9.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "6a3a4e0ea8a88553209f6cc6cfe8724ecad22e1acf372793c27d995290fe74f8" | ||||
| dependencies = [ | ||||
|  "lazy_static", | ||||
|  "linked-hash-map", | ||||
|  "num-traits 0.1.43", | ||||
|  "regex", | ||||
|  "serde 0.8.23", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde_derive" | ||||
| version = "1.0.118" | ||||
| @ -3777,7 +3919,16 @@ checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a" | ||||
| dependencies = [ | ||||
|  "itoa", | ||||
|  "ryu", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde_test" | ||||
| version = "0.8.23" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "110b3dbdf8607ec493c22d5d947753282f3bae73c0f56d322af1e8c78e4c23d5" | ||||
| dependencies = [ | ||||
|  "serde 0.8.23", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| @ -3788,7 +3939,7 @@ checksum = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" | ||||
| dependencies = [ | ||||
|  "dtoa", | ||||
|  "itoa", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "url 1.7.2", | ||||
| ] | ||||
| 
 | ||||
| @ -3801,7 +3952,7 @@ dependencies = [ | ||||
|  "form_urlencoded", | ||||
|  "itoa", | ||||
|  "ryu", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| @ -3878,6 +4029,34 @@ version = "0.4.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "slog" | ||||
| version = "2.7.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8347046d4ebd943127157b94d63abb990fcf729dc4e9978927fdf4ac3c998d06" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "slog-scope" | ||||
| version = "4.3.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7c44c89dd8b0ae4537d1ae318353eaf7840b4869c536e31c41e963d1ea523ee6" | ||||
| dependencies = [ | ||||
|  "arc-swap", | ||||
|  "lazy_static", | ||||
|  "slog", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "slog-stdlog" | ||||
| version = "4.1.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8228ab7302adbf4fcb37e66f3cda78003feb521e7fd9e3847ec117a7784d0f5a" | ||||
| dependencies = [ | ||||
|  "log 0.4.11", | ||||
|  "slog", | ||||
|  "slog-scope", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "smallvec" | ||||
| version = "0.6.13" | ||||
| @ -3948,7 +4127,7 @@ checksum = "a68c0ce28cf7400ed022e18da3c4591e14e1df02c70e93573cc59921b3923aeb" | ||||
| dependencies = [ | ||||
|  "discard", | ||||
|  "rustc_version", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_json", | ||||
|  "stdweb-derive", | ||||
|  "stdweb-internal-macros", | ||||
| @ -3964,7 +4143,7 @@ checksum = "0e21ebd9179de08f2300a65454268a17ea3de204627458588c84319c4def3930" | ||||
| dependencies = [ | ||||
|  "proc-macro2 0.4.30", | ||||
|  "quote 0.6.13", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_derive", | ||||
|  "syn 0.15.44", | ||||
| ] | ||||
| @ -3978,7 +4157,7 @@ dependencies = [ | ||||
|  "base-x", | ||||
|  "proc-macro2 0.4.30", | ||||
|  "quote 0.6.13", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_derive", | ||||
|  "serde_json", | ||||
|  "sha1", | ||||
| @ -4010,7 +4189,7 @@ dependencies = [ | ||||
|  "new_debug_unreachable", | ||||
|  "phf_shared", | ||||
|  "precomputed-hash", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "string_cache_codegen", | ||||
|  "string_cache_shared", | ||||
| ] | ||||
| @ -4154,7 +4333,7 @@ dependencies = [ | ||||
|  "onig", | ||||
|  "plist", | ||||
|  "regex-syntax 0.6.21", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_derive", | ||||
|  "serde_json", | ||||
|  "walkdir", | ||||
| @ -4194,7 +4373,7 @@ dependencies = [ | ||||
|  "rayon", | ||||
|  "regex", | ||||
|  "rust-stemmers", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_json", | ||||
|  "smallvec 1.5.1", | ||||
|  "snap", | ||||
| @ -4322,6 +4501,15 @@ dependencies = [ | ||||
|  "winapi 0.3.9", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tiny-keccak" | ||||
| version = "2.0.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" | ||||
| dependencies = [ | ||||
|  "crunchy", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tinyvec" | ||||
| version = "1.1.0" | ||||
| @ -4605,7 +4793,16 @@ version = "0.4.10" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" | ||||
| dependencies = [ | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "toml" | ||||
| version = "0.5.8" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" | ||||
| dependencies = [ | ||||
|  "serde 1.0.118", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| @ -4674,7 +4871,7 @@ version = "0.1.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b" | ||||
| dependencies = [ | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "tracing-core", | ||||
| ] | ||||
| 
 | ||||
| @ -4689,7 +4886,7 @@ dependencies = [ | ||||
|  "lazy_static", | ||||
|  "matchers", | ||||
|  "regex", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_json", | ||||
|  "sharded-slab", | ||||
|  "smallvec 1.5.1", | ||||
| @ -4875,7 +5072,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" | ||||
| dependencies = [ | ||||
|  "rand 0.7.3", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| @ -4887,7 +5084,7 @@ dependencies = [ | ||||
|  "idna 0.1.5", | ||||
|  "lazy_static", | ||||
|  "regex", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_derive", | ||||
|  "serde_json", | ||||
|  "url 1.7.2", | ||||
| @ -4989,7 +5186,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e" | ||||
| dependencies = [ | ||||
|  "cfg-if 1.0.0", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_json", | ||||
|  "wasm-bindgen-macro", | ||||
| ] | ||||
| @ -5067,7 +5264,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ec24b1b0700d4b466d280228ed0f62274eedeaa80206820f071fdc8ed787b664" | ||||
| dependencies = [ | ||||
|  "reqwest 0.9.24", | ||||
|  "serde", | ||||
|  "serde 1.0.118", | ||||
|  "serde_derive", | ||||
| ] | ||||
| 
 | ||||
|  | ||||
| @ -32,6 +32,7 @@ validator_derive = "0.8" | ||||
| webfinger = "0.4.1" | ||||
| tracing = "0.1.22" | ||||
| tracing-subscriber = "0.2.15" | ||||
| riker = "0.4.2" | ||||
| 
 | ||||
| [[bin]] | ||||
| name = "plume" | ||||
|  | ||||
| @ -33,6 +33,8 @@ diesel-derive-newtype = "0.1.2" | ||||
| glob = "0.3.0" | ||||
| lindera-tantivy = { version = "0.7.1", optional = true } | ||||
| tracing = "0.1.22" | ||||
| riker = "0.4.2" | ||||
| once_cell = "1.5.2" | ||||
| 
 | ||||
| [dependencies.chrono] | ||||
| features = ["serde"] | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| use crate::{ | ||||
|     ap_url, instance::*, medias::Media, posts::Post, safe_string::SafeString, schema::blogs, | ||||
|     search::Searcher, users::User, Connection, Error, PlumeRocket, Result, CONFIG, ITEMS_PER_PAGE, | ||||
|     users::User, Connection, Error, PlumeRocket, Result, CONFIG, ITEMS_PER_PAGE, | ||||
| }; | ||||
| use activitypub::{ | ||||
|     actor::Group, | ||||
| @ -317,9 +317,9 @@ impl Blog { | ||||
|             .and_then(|c| c.url().ok()) | ||||
|     } | ||||
| 
 | ||||
|     pub fn delete(&self, conn: &Connection, searcher: &Searcher) -> Result<()> { | ||||
|     pub fn delete(&self, conn: &Connection) -> Result<()> { | ||||
|         for post in Post::get_for_blog(conn, &self)? { | ||||
|             post.delete(conn, searcher)?; | ||||
|             post.delete(conn)?; | ||||
|         } | ||||
|         diesel::delete(self) | ||||
|             .execute(conn) | ||||
| @ -497,10 +497,8 @@ pub(crate) mod tests { | ||||
|     use super::*; | ||||
|     use crate::{ | ||||
|         blog_authors::*, | ||||
|         config::CONFIG, | ||||
|         instance::tests as instance_tests, | ||||
|         medias::NewMedia, | ||||
|         search::tests::get_searcher, | ||||
|         tests::{db, rockets}, | ||||
|         users::tests as usersTests, | ||||
|         Connection as Conn, | ||||
| @ -767,9 +765,7 @@ pub(crate) mod tests { | ||||
|         conn.test_transaction::<_, (), _>(|| { | ||||
|             let (_, blogs) = fill_database(conn); | ||||
| 
 | ||||
|             blogs[0] | ||||
|                 .delete(conn, &get_searcher(&CONFIG.search_tokenizers)) | ||||
|                 .unwrap(); | ||||
|             blogs[0].delete(conn).unwrap(); | ||||
|             assert!(Blog::get(conn, blogs[0].id).is_err()); | ||||
|             Ok(()) | ||||
|         }) | ||||
| @ -779,7 +775,6 @@ pub(crate) mod tests { | ||||
|     fn delete_via_user() { | ||||
|         let conn = &db(); | ||||
|         conn.test_transaction::<_, (), _>(|| { | ||||
|             let searcher = get_searcher(&CONFIG.search_tokenizers); | ||||
|             let (user, _) = fill_database(conn); | ||||
| 
 | ||||
|             let b1 = Blog::insert( | ||||
| @ -836,10 +831,10 @@ pub(crate) mod tests { | ||||
|             ) | ||||
|             .unwrap(); | ||||
| 
 | ||||
|             user[0].delete(conn, &searcher).unwrap(); | ||||
|             user[0].delete(conn).unwrap(); | ||||
|             assert!(Blog::get(conn, blog[0].id).is_ok()); | ||||
|             assert!(Blog::get(conn, blog[1].id).is_err()); | ||||
|             user[1].delete(conn, &searcher).unwrap(); | ||||
|             user[1].delete(conn).unwrap(); | ||||
|             assert!(Blog::get(conn, blog[0].id).is_err()); | ||||
|             Ok(()) | ||||
|         }) | ||||
| @ -886,7 +881,7 @@ pub(crate) mod tests { | ||||
|             let _: Blog = blogs[0].save_changes(conn).unwrap(); | ||||
| 
 | ||||
|             let ap_repr = blogs[0].to_activity(conn).unwrap(); | ||||
|             blogs[0].delete(conn, &*r.searcher).unwrap(); | ||||
|             blogs[0].delete(conn).unwrap(); | ||||
|             let blog = Blog::from_activity(&r, ap_repr).unwrap(); | ||||
| 
 | ||||
|             assert_eq!(blog.actor_id, blogs[0].actor_id); | ||||
|  | ||||
| @ -97,7 +97,6 @@ pub(crate) mod tests { | ||||
|                 source: String::new(), | ||||
|                 cover_id: None, | ||||
|             }, | ||||
|             &rockets.searcher, | ||||
|         ) | ||||
|         .unwrap(); | ||||
| 
 | ||||
|  | ||||
| @ -17,7 +17,10 @@ extern crate serde_json; | ||||
| #[macro_use] | ||||
| extern crate tantivy; | ||||
| 
 | ||||
| use once_cell::sync::Lazy; | ||||
| use plume_common::activity_pub::inbox::InboxError; | ||||
| use posts::PostEvent; | ||||
| use riker::actors::{channel, ActorSystem, ChannelRef, SystemBuilder}; | ||||
| 
 | ||||
| #[cfg(not(any(feature = "sqlite", feature = "postgres")))] | ||||
| compile_error!("Either feature \"sqlite\" or \"postgres\" must be enabled for this crate."); | ||||
| @ -30,6 +33,16 @@ pub type Connection = diesel::SqliteConnection; | ||||
| #[cfg(all(not(feature = "sqlite"), feature = "postgres"))] | ||||
| pub type Connection = diesel::PgConnection; | ||||
| 
 | ||||
| pub(crate) static ACTOR_SYS: Lazy<ActorSystem> = Lazy::new(|| { | ||||
|     SystemBuilder::new() | ||||
|         .name("plume") | ||||
|         .create() | ||||
|         .expect("Failed to create actor system") | ||||
| }); | ||||
| 
 | ||||
| pub(crate) static POST_CHAN: Lazy<ChannelRef<PostEvent>> = | ||||
|     Lazy::new(|| channel("post_events", &*ACTOR_SYS).expect("Failed to create post channel")); | ||||
| 
 | ||||
| /// All the possible errors that can be encoutered in this crate
 | ||||
| #[derive(Debug)] | ||||
| pub enum Error { | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| use crate::{ | ||||
|     ap_url, blogs::Blog, instance::Instance, medias::Media, mentions::Mention, post_authors::*, | ||||
|     safe_string::SafeString, schema::posts, search::Searcher, tags::*, timeline::*, users::User, | ||||
|     Connection, Error, PlumeRocket, Result, CONFIG, | ||||
|     safe_string::SafeString, schema::posts, tags::*, timeline::*, users::User, Connection, Error, | ||||
|     PlumeRocket, PostEvent::*, Result, CONFIG, POST_CHAN, | ||||
| }; | ||||
| use activitypub::{ | ||||
|     activity::{Create, Delete, Update}, | ||||
| @ -19,11 +19,13 @@ use plume_common::{ | ||||
|     }, | ||||
|     utils::md_to_html, | ||||
| }; | ||||
| use riker::actors::{Publish, Tell}; | ||||
| use std::collections::HashSet; | ||||
| use std::sync::Arc; | ||||
| 
 | ||||
| pub type LicensedArticle = CustomObject<Licensed, Article>; | ||||
| 
 | ||||
| #[derive(Queryable, Identifiable, Clone, AsChangeset)] | ||||
| #[derive(Queryable, Identifiable, Clone, AsChangeset, Debug)] | ||||
| #[changeset_options(treat_none_as_null = "true")] | ||||
| pub struct Post { | ||||
|     pub id: i32, | ||||
| @ -62,7 +64,7 @@ impl Post { | ||||
|     find_by!(posts, find_by_ap_url, ap_url as &str); | ||||
| 
 | ||||
|     last!(posts); | ||||
|     pub fn insert(conn: &Connection, new: NewPost, searcher: &Searcher) -> Result<Self> { | ||||
|     pub fn insert(conn: &Connection, new: NewPost) -> Result<Self> { | ||||
|         diesel::insert_into(posts::table) | ||||
|             .values(new) | ||||
|             .execute(conn)?; | ||||
| @ -77,23 +79,29 @@ impl Post { | ||||
|             let _: Post = post.save_changes(conn)?; | ||||
|         } | ||||
| 
 | ||||
|         searcher.add_document(conn, &post)?; | ||||
|         if post.published { | ||||
|             post.publish_published(); | ||||
|         } | ||||
| 
 | ||||
|         Ok(post) | ||||
|     } | ||||
| 
 | ||||
|     pub fn update(&self, conn: &Connection, searcher: &Searcher) -> Result<Self> { | ||||
|     pub fn update(&self, conn: &Connection) -> Result<Self> { | ||||
|         diesel::update(self).set(self).execute(conn)?; | ||||
|         let post = Self::get(conn, self.id)?; | ||||
|         searcher.update_document(conn, &post)?; | ||||
|         // TODO: Call publish_published() when newly published
 | ||||
|         if post.published { | ||||
|             self.publish_updated(); | ||||
|         } | ||||
|         Ok(post) | ||||
|     } | ||||
| 
 | ||||
|     pub fn delete(&self, conn: &Connection, searcher: &Searcher) -> Result<()> { | ||||
|     pub fn delete(&self, conn: &Connection) -> Result<()> { | ||||
|         for m in Mention::list_for_post(&conn, self.id)? { | ||||
|             m.delete(conn)?; | ||||
|         } | ||||
|         diesel::delete(self).execute(conn)?; | ||||
|         searcher.delete_document(self); | ||||
|         self.publish_deleted(); | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
| @ -545,6 +553,36 @@ impl Post { | ||||
|             .set_to_link_vec(vec![Id::new(PUBLIC_VISIBILITY)])?; | ||||
|         Ok(act) | ||||
|     } | ||||
| 
 | ||||
|     fn publish_published(&self) { | ||||
|         POST_CHAN.tell( | ||||
|             Publish { | ||||
|                 msg: PostPublished(Arc::new(self.clone())), | ||||
|                 topic: "post.published".into(), | ||||
|             }, | ||||
|             None, | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     fn publish_updated(&self) { | ||||
|         POST_CHAN.tell( | ||||
|             Publish { | ||||
|                 msg: PostUpdated(Arc::new(self.clone())), | ||||
|                 topic: "post.updated".into(), | ||||
|             }, | ||||
|             None, | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     fn publish_deleted(&self) { | ||||
|         POST_CHAN.tell( | ||||
|             Publish { | ||||
|                 msg: PostDeleted(Arc::new(self.clone())), | ||||
|                 topic: "post.deleted".into(), | ||||
|             }, | ||||
|             None, | ||||
|         ) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl FromId<PlumeRocket> for Post { | ||||
| @ -557,7 +595,6 @@ impl FromId<PlumeRocket> for Post { | ||||
| 
 | ||||
|     fn from_activity(c: &PlumeRocket, article: LicensedArticle) -> Result<Self> { | ||||
|         let conn = &*c.conn; | ||||
|         let searcher = &c.searcher; | ||||
|         let license = article.custom_props.license_string().unwrap_or_default(); | ||||
|         let article = article.object; | ||||
| 
 | ||||
| @ -605,7 +642,6 @@ impl FromId<PlumeRocket> for Post { | ||||
|                 source: article.ap_object_props.source_object::<Source>()?.content, | ||||
|                 cover_id: cover, | ||||
|             }, | ||||
|             searcher, | ||||
|         )?; | ||||
| 
 | ||||
|         for author in authors { | ||||
| @ -670,7 +706,7 @@ impl AsObject<User, Delete, &PlumeRocket> for Post { | ||||
|             .into_iter() | ||||
|             .any(|a| actor.id == a.id); | ||||
|         if can_delete { | ||||
|             self.delete(&c.conn, &c.searcher).map(|_| ()) | ||||
|             self.delete(&c.conn).map(|_| ()) | ||||
|         } else { | ||||
|             Err(Error::Unauthorized) | ||||
|         } | ||||
| @ -727,7 +763,6 @@ impl AsObject<User, Update, &PlumeRocket> for PostUpdate { | ||||
| 
 | ||||
|     fn activity(self, c: &PlumeRocket, actor: User, _id: &str) -> Result<()> { | ||||
|         let conn = &*c.conn; | ||||
|         let searcher = &c.searcher; | ||||
|         let mut post = Post::from_id(c, &self.ap_url, None, CONFIG.proxy()).map_err(|(_, e)| e)?; | ||||
| 
 | ||||
|         if !post.is_author(conn, actor.id)? { | ||||
| @ -789,7 +824,7 @@ impl AsObject<User, Update, &PlumeRocket> for PostUpdate { | ||||
|             post.update_hashtags(conn, hashtags)?; | ||||
|         } | ||||
| 
 | ||||
|         post.update(conn, searcher)?; | ||||
|         post.update(conn)?; | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
| @ -800,6 +835,25 @@ impl IntoId for Post { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub enum PostEvent { | ||||
|     PostPublished(Arc<Post>), | ||||
|     PostUpdated(Arc<Post>), | ||||
|     PostDeleted(Arc<Post>), | ||||
| } | ||||
| 
 | ||||
| impl From<PostEvent> for Arc<Post> { | ||||
|     fn from(event: PostEvent) -> Self { | ||||
|         use PostEvent::*; | ||||
| 
 | ||||
|         match event { | ||||
|             PostPublished(post) => post, | ||||
|             PostUpdated(post) => post, | ||||
|             PostDeleted(post) => post, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     use super::*; | ||||
| @ -831,7 +885,6 @@ mod tests { | ||||
|                     source: "Hello".into(), | ||||
|                     cover_id: None, | ||||
|                 }, | ||||
|                 &r.searcher, | ||||
|             ) | ||||
|             .unwrap(); | ||||
|             PostAuthor::insert( | ||||
| @ -843,7 +896,7 @@ mod tests { | ||||
|             ) | ||||
|             .unwrap(); | ||||
|             let create = post.create_activity(conn).unwrap(); | ||||
|             post.delete(conn, &r.searcher).unwrap(); | ||||
|             post.delete(conn).unwrap(); | ||||
| 
 | ||||
|             match inbox(&r, serde_json::to_value(create).unwrap()).unwrap() { | ||||
|                 InboxResult::Post(p) => { | ||||
|  | ||||
							
								
								
									
										207
									
								
								plume-models/src/search/actor.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								plume-models/src/search/actor.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,207 @@ | ||||
| use super::Searcher; | ||||
| use crate::{db_conn::DbPool, posts::PostEvent, ACTOR_SYS, POST_CHAN}; | ||||
| use riker::actors::{Actor, ActorFactoryArgs, ActorRefFactory, Context, Sender, Subscribe, Tell}; | ||||
| use std::sync::Arc; | ||||
| use std::thread::sleep; | ||||
| use std::time::Duration; | ||||
| use tracing::error; | ||||
| 
 | ||||
| pub struct SearchActor { | ||||
|     searcher: Arc<Searcher>, | ||||
|     conn: DbPool, | ||||
| } | ||||
| 
 | ||||
| impl SearchActor { | ||||
|     pub fn init(searcher: Arc<Searcher>, conn: DbPool) { | ||||
|         ACTOR_SYS | ||||
|             .actor_of_args::<SearchActor, _>("search", (searcher, conn)) | ||||
|             .expect("Failed to initialize searcher actor"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Actor for SearchActor { | ||||
|     type Msg = PostEvent; | ||||
| 
 | ||||
|     fn pre_start(&mut self, ctx: &Context<Self::Msg>) { | ||||
|         POST_CHAN.tell( | ||||
|             Subscribe { | ||||
|                 actor: Box::new(ctx.myself()), | ||||
|                 topic: "*".into(), | ||||
|             }, | ||||
|             None, | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     fn recv(&mut self, _ctx: &Context<Self::Msg>, msg: Self::Msg, _sender: Sender) { | ||||
|         use PostEvent::*; | ||||
| 
 | ||||
|         // Wait for transaction commited
 | ||||
|         sleep(Duration::from_millis(500)); | ||||
| 
 | ||||
|         match msg { | ||||
|             PostPublished(post) => { | ||||
|                 let conn = self.conn.get(); | ||||
|                 match conn { | ||||
|                     Ok(conn) => { | ||||
|                         self.searcher | ||||
|                             .add_document(&conn, &post) | ||||
|                             .unwrap_or_else(|e| error!("{:?}", e)); | ||||
|                     } | ||||
|                     _ => { | ||||
|                         error!("Failed to get database connection"); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             PostUpdated(post) => { | ||||
|                 let conn = self.conn.get(); | ||||
|                 match conn { | ||||
|                     Ok(_) => { | ||||
|                         self.searcher | ||||
|                             .update_document(&conn.unwrap(), &post) | ||||
|                             .unwrap_or_else(|e| error!("{:?}", e)); | ||||
|                     } | ||||
|                     _ => { | ||||
|                         error!("Failed to get database connection"); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             PostDeleted(post) => self.searcher.delete_document(&post), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl ActorFactoryArgs<(Arc<Searcher>, DbPool)> for SearchActor { | ||||
|     fn create_args((searcher, conn): (Arc<Searcher>, DbPool)) -> Self { | ||||
|         Self { searcher, conn } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     use crate::diesel::Connection; | ||||
|     use crate::diesel::RunQueryDsl; | ||||
|     use crate::{ | ||||
|         blog_authors::{BlogAuthor, NewBlogAuthor}, | ||||
|         blogs::{Blog, NewBlog}, | ||||
|         db_conn::{DbPool, PragmaForeignKey}, | ||||
|         instance::{Instance, NewInstance}, | ||||
|         post_authors::{NewPostAuthor, PostAuthor}, | ||||
|         posts::{NewPost, Post}, | ||||
|         safe_string::SafeString, | ||||
|         search::{actor::SearchActor, tests::get_searcher, Query}, | ||||
|         users::{NewUser, User}, | ||||
|         Connection as Conn, CONFIG, | ||||
|     }; | ||||
|     use diesel::r2d2::ConnectionManager; | ||||
|     use plume_common::utils::random_hex; | ||||
|     use std::str::FromStr; | ||||
|     use std::sync::Arc; | ||||
|     use std::thread::sleep; | ||||
|     use std::time::Duration; | ||||
| 
 | ||||
|     #[test] | ||||
|     fn post_updated() { | ||||
|         // Need to commit so that searcher on another thread retrieve records.
 | ||||
|         // So, build DbPool instead of using DB_POOL for testing.
 | ||||
|         let manager = ConnectionManager::<Conn>::new(CONFIG.database_url.as_str()); | ||||
|         let db_pool = DbPool::builder() | ||||
|             .connection_customizer(Box::new(PragmaForeignKey)) | ||||
|             .build(manager) | ||||
|             .unwrap(); | ||||
| 
 | ||||
|         let searcher = Arc::new(get_searcher(&CONFIG.search_tokenizers)); | ||||
|         SearchActor::init(searcher.clone(), db_pool.clone()); | ||||
|         let conn = db_pool.clone().get().unwrap(); | ||||
| 
 | ||||
|         let title = random_hex()[..8].to_owned(); | ||||
|         let (instance, user, blog) = fill_database(&conn); | ||||
|         let author = &blog.list_authors(&conn).unwrap()[0]; | ||||
| 
 | ||||
|         let post = Post::insert( | ||||
|             &conn, | ||||
|             NewPost { | ||||
|                 blog_id: blog.id, | ||||
|                 slug: title.clone(), | ||||
|                 title: title.clone(), | ||||
|                 content: SafeString::new(""), | ||||
|                 published: true, | ||||
|                 license: "CC-BY-SA".to_owned(), | ||||
|                 ap_url: "".to_owned(), | ||||
|                 creation_date: None, | ||||
|                 subtitle: "".to_owned(), | ||||
|                 source: "".to_owned(), | ||||
|                 cover_id: None, | ||||
|             }, | ||||
|         ) | ||||
|         .unwrap(); | ||||
|         PostAuthor::insert( | ||||
|             &conn, | ||||
|             NewPostAuthor { | ||||
|                 post_id: post.id, | ||||
|                 author_id: author.id, | ||||
|             }, | ||||
|         ) | ||||
|         .unwrap(); | ||||
|         let post_id = post.id; | ||||
| 
 | ||||
|         // Wait for searcher on another thread add document asynchronously
 | ||||
|         sleep(Duration::from_millis(700)); | ||||
|         searcher.commit(); | ||||
|         assert_eq!( | ||||
|             searcher.search_document(&conn, Query::from_str(&title).unwrap(), (0, 1))[0].id, | ||||
|             post_id | ||||
|         ); | ||||
|         // TODO: Make sure records are deleted even when assertion failed
 | ||||
|         post.delete(&conn).unwrap(); | ||||
|         blog.delete(&conn).unwrap(); | ||||
|         user.delete(&conn).unwrap(); | ||||
|         diesel::delete(&instance).execute(&conn).unwrap(); | ||||
|     } | ||||
| 
 | ||||
|     fn fill_database(conn: &Conn) -> (Instance, User, Blog) { | ||||
|         conn.transaction::<(Instance, User, Blog), diesel::result::Error, _>(|| { | ||||
|             let instance = Instance::insert( | ||||
|                 conn, | ||||
|                 NewInstance { | ||||
|                     default_license: "CC-0-BY-SA".to_string(), | ||||
|                     local: true, | ||||
|                     long_description: SafeString::new("Good morning"), | ||||
|                     long_description_html: "<p>Good morning</p>".to_string(), | ||||
|                     short_description: SafeString::new("Hello"), | ||||
|                     short_description_html: "<p>Hello</p>".to_string(), | ||||
|                     name: random_hex().to_string(), | ||||
|                     open_registrations: true, | ||||
|                     public_domain: random_hex().to_string(), | ||||
|                 }, | ||||
|             ) | ||||
|             .unwrap(); | ||||
|             let mut user = NewUser::default(); | ||||
|             user.instance_id = instance.id; | ||||
|             user.username = random_hex().to_string(); | ||||
|             user.ap_url = random_hex().to_string(); | ||||
|             user.inbox_url = random_hex().to_string(); | ||||
|             user.outbox_url = random_hex().to_string(); | ||||
|             user.followers_endpoint = random_hex().to_string(); | ||||
|             let user = User::insert(conn, user).unwrap(); | ||||
|             let mut blog = NewBlog::default(); | ||||
|             blog.instance_id = instance.id; | ||||
|             blog.actor_id = random_hex().to_string(); | ||||
|             blog.ap_url = random_hex().to_string(); | ||||
|             blog.inbox_url = random_hex().to_string(); | ||||
|             blog.outbox_url = random_hex().to_string(); | ||||
|             let blog = Blog::insert(conn, blog).unwrap(); | ||||
|             BlogAuthor::insert( | ||||
|                 conn, | ||||
|                 NewBlogAuthor { | ||||
|                     blog_id: blog.id, | ||||
|                     author_id: user.id, | ||||
|                     is_owner: true, | ||||
|                 }, | ||||
|             ) | ||||
|             .unwrap(); | ||||
| 
 | ||||
|             Ok((instance, user, blog)) | ||||
|         }) | ||||
|         .unwrap() | ||||
|     } | ||||
| } | ||||
| @ -1,3 +1,4 @@ | ||||
| pub mod actor; | ||||
| mod query; | ||||
| mod searcher; | ||||
| mod tokenizer; | ||||
| @ -7,12 +8,7 @@ pub use self::tokenizer::TokenizerKind; | ||||
| 
 | ||||
| #[cfg(test)] | ||||
| pub(crate) mod tests { | ||||
|     use super::{Query, Searcher, TokenizerKind}; | ||||
|     use diesel::Connection; | ||||
|     use plume_common::utils::random_hex; | ||||
|     use std::env::temp_dir; | ||||
|     use std::str::FromStr; | ||||
| 
 | ||||
|     use super::{Query, Searcher}; | ||||
|     use crate::{ | ||||
|         blogs::tests::fill_database, | ||||
|         config::SearchTokenizerConfig, | ||||
| @ -22,6 +18,10 @@ pub(crate) mod tests { | ||||
|         tests::db, | ||||
|         CONFIG, | ||||
|     }; | ||||
|     use diesel::Connection; | ||||
|     use plume_common::utils::random_hex; | ||||
|     use std::env::temp_dir; | ||||
|     use std::str::FromStr; | ||||
| 
 | ||||
|     pub(crate) fn get_searcher(tokenizers: &SearchTokenizerConfig) -> Searcher { | ||||
|         let dir = temp_dir().join(&format!("plume-test-{}", random_hex())); | ||||
| @ -144,7 +144,6 @@ pub(crate) mod tests { | ||||
|                     source: "".to_owned(), | ||||
|                     cover_id: None, | ||||
|                 }, | ||||
|                 &searcher, | ||||
|             ) | ||||
|             .unwrap(); | ||||
|             PostAuthor::insert( | ||||
| @ -155,7 +154,7 @@ pub(crate) mod tests { | ||||
|                 }, | ||||
|             ) | ||||
|             .unwrap(); | ||||
| 
 | ||||
|             searcher.add_document(&conn, &post).unwrap(); | ||||
|             searcher.commit(); | ||||
|             assert_eq!( | ||||
|                 searcher.search_document(conn, Query::from_str(&title).unwrap(), (0, 1))[0].id, | ||||
| @ -164,7 +163,8 @@ pub(crate) mod tests { | ||||
| 
 | ||||
|             let newtitle = random_hex()[..8].to_owned(); | ||||
|             post.title = newtitle.clone(); | ||||
|             post.update(conn, &searcher).unwrap(); | ||||
|             post.update(conn).unwrap(); | ||||
|             searcher.update_document(conn, &post).unwrap(); | ||||
|             searcher.commit(); | ||||
|             assert_eq!( | ||||
|                 searcher.search_document(conn, Query::from_str(&newtitle).unwrap(), (0, 1))[0].id, | ||||
| @ -174,7 +174,7 @@ pub(crate) mod tests { | ||||
|                 .search_document(conn, Query::from_str(&title).unwrap(), (0, 1)) | ||||
|                 .is_empty()); | ||||
| 
 | ||||
|             post.delete(conn, &searcher).unwrap(); | ||||
|             searcher.delete_document(&post); | ||||
|             searcher.commit(); | ||||
|             assert!(searcher | ||||
|                 .search_document(conn, Query::from_str(&newtitle).unwrap(), (0, 1)) | ||||
| @ -213,7 +213,6 @@ pub(crate) mod tests { | ||||
|                     source: "".to_owned(), | ||||
|                     cover_id: None, | ||||
|                 }, | ||||
|                 &searcher, | ||||
|             ) | ||||
|             .unwrap(); | ||||
| 
 | ||||
|  | ||||
| @ -1,15 +1,17 @@ | ||||
| use crate::{ | ||||
|     config::SearchTokenizerConfig, instance::Instance, posts::Post, schema::posts, | ||||
|     search::query::PlumeQuery, tags::Tag, Connection, Result, | ||||
|     search::query::PlumeQuery, tags::Tag, Connection, Error, Result, | ||||
| }; | ||||
| use chrono::Datelike; | ||||
| use chrono::{Datelike, Utc}; | ||||
| use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl}; | ||||
| use itertools::Itertools; | ||||
| use std::fs; | ||||
| use std::{cmp, fs::create_dir_all, io, path::Path, sync::Mutex}; | ||||
| use tantivy::{ | ||||
|     collector::TopDocs, directory::MmapDirectory, schema::*, Index, IndexReader, IndexWriter, | ||||
|     ReloadPolicy, TantivyError, Term, | ||||
| }; | ||||
| use tracing::warn; | ||||
| use whatlang::{detect as detect_lang, Lang}; | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| @ -67,6 +69,58 @@ impl Searcher { | ||||
|         schema_builder.build() | ||||
|     } | ||||
| 
 | ||||
|     pub fn open_or_recreate(path: &dyn AsRef<Path>, tokenizers: &SearchTokenizerConfig) -> Self { | ||||
|         let mut open_searcher = Self::open(path, tokenizers); | ||||
|         if let Err(Error::Search(SearcherError::InvalidIndexDataError)) = open_searcher { | ||||
|             if Self::create(path, tokenizers).is_err() { | ||||
|                 let backup_path = format!("{}.{}", path.as_ref().display(), Utc::now().timestamp()); | ||||
|                 let backup_path = Path::new(&backup_path); | ||||
|                 fs::rename(path, backup_path) | ||||
|                     .expect("main: error on backing up search index directory for recreating"); | ||||
|                 if Self::create(path, tokenizers).is_ok() { | ||||
|                     if fs::remove_dir_all(backup_path).is_err() { | ||||
|                         warn!( | ||||
|                             "error on removing backup directory: {}. it remains", | ||||
|                             backup_path.display() | ||||
|                         ); | ||||
|                     } | ||||
|                 } else { | ||||
|                     panic!("main: error on recreating search index in new index format. remove search index and run `plm search init` manually"); | ||||
|                 } | ||||
|             } | ||||
|             open_searcher = Self::open(path, tokenizers); | ||||
|         } | ||||
|         match open_searcher { | ||||
|             Ok(s) => s, | ||||
|             Err(Error::Search(e)) => match e { | ||||
|                 SearcherError::WriteLockAcquisitionError => panic!( | ||||
|                     r#" | ||||
| Your search index is locked. Plume can't start. To fix this issue | ||||
| make sure no other Plume instance is started, and run: | ||||
| 
 | ||||
|     plm search unlock | ||||
| 
 | ||||
| Then try to restart Plume. | ||||
| "#
 | ||||
|                 ), | ||||
|                 SearcherError::IndexOpeningError => panic!( | ||||
|                     r#" | ||||
| Plume was unable to open the search index. If you created the index | ||||
| before, make sure to run Plume in the same directory it was created in, or | ||||
| to set SEARCH_INDEX accordingly. If you did not yet create the search | ||||
| index, run this command: | ||||
| 
 | ||||
|     plm search init | ||||
| 
 | ||||
| Then try to restart Plume | ||||
| "#
 | ||||
|                 ), | ||||
|                 e => Err(e).unwrap(), | ||||
|             }, | ||||
|             _ => panic!("Unexpected error while opening search index"), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn create(path: &dyn AsRef<Path>, tokenizers: &SearchTokenizerConfig) -> Result<Self> { | ||||
|         let schema = Self::schema(); | ||||
| 
 | ||||
|  | ||||
| @ -408,7 +408,6 @@ mod tests { | ||||
|                     source: "you must say GNU/Linux, not Linux!!!".to_string(), | ||||
|                     cover_id: None, | ||||
|                 }, | ||||
|                 &r.searcher, | ||||
|             ) | ||||
|             .unwrap(); | ||||
|             assert!(gnu_tl.matches(r, &gnu_post, Kind::Original).unwrap()); | ||||
| @ -428,7 +427,6 @@ mod tests { | ||||
|                     source: "so is Microsoft".to_string(), | ||||
|                     cover_id: None, | ||||
|                 }, | ||||
|                 &r.searcher, | ||||
|             ) | ||||
|             .unwrap(); | ||||
|             assert!(!gnu_tl.matches(r, &non_free_post, Kind::Original).unwrap()); | ||||
| @ -481,7 +479,6 @@ mod tests { | ||||
|                     subtitle: "".to_string(), | ||||
|                     cover_id: None, | ||||
|                 }, | ||||
|                 &r.searcher, | ||||
|             ) | ||||
|             .unwrap(); | ||||
|             assert!(my_tl.matches(r, &post, Kind::Original).unwrap()); // matches because of "blog in fav_blogs" (and there is no cover)
 | ||||
| @ -503,7 +500,6 @@ mod tests { | ||||
|                     subtitle: "".to_string(), | ||||
|                     cover_id: None, | ||||
|                 }, | ||||
|                 &r.searcher, | ||||
|             ) | ||||
|             .unwrap(); | ||||
|             assert!(!my_tl.matches(r, &post, Kind::Like(&users[1])).unwrap()); | ||||
| @ -549,7 +545,6 @@ mod tests { | ||||
|                     source: "you must say GNU/Linux, not Linux!!!".to_string(), | ||||
|                     cover_id: None, | ||||
|                 }, | ||||
|                 &r.searcher, | ||||
|             ) | ||||
|             .unwrap(); | ||||
| 
 | ||||
| @ -568,7 +563,6 @@ mod tests { | ||||
|                     source: "so is Microsoft".to_string(), | ||||
|                     cover_id: None, | ||||
|                 }, | ||||
|                 &r.searcher, | ||||
|             ) | ||||
|             .unwrap(); | ||||
| 
 | ||||
| @ -608,7 +602,6 @@ mod tests { | ||||
|                     source: "you must say GNU/Linux, not Linux!!!".to_string(), | ||||
|                     cover_id: None, | ||||
|                 }, | ||||
|                 &r.searcher, | ||||
|             ) | ||||
|             .unwrap(); | ||||
|             gnu_post | ||||
| @ -745,7 +738,6 @@ mod tests { | ||||
|                     source: "you must say GNU/Linux, not Linux!!!".to_string(), | ||||
|                     cover_id: None, | ||||
|                 }, | ||||
|                 &r.searcher, | ||||
|             ) | ||||
|             .unwrap(); | ||||
|             gnu_post.update_tags(conn, vec![Tag::build_activity("free".to_owned()).unwrap()]).unwrap(); | ||||
| @ -779,7 +771,6 @@ mod tests { | ||||
|                     source: "you must say GNU/Linux, not Linux!!!".to_string(), | ||||
|                     cover_id: None, | ||||
|                 }, | ||||
|                 &r.searcher, | ||||
|             ) | ||||
|             .unwrap(); | ||||
| 
 | ||||
|  | ||||
| @ -1,8 +1,8 @@ | ||||
| use crate::{ | ||||
|     ap_url, blocklisted_emails::BlocklistedEmail, blogs::Blog, db_conn::DbConn, follows::Follow, | ||||
|     instance::*, medias::Media, notifications::Notification, post_authors::PostAuthor, posts::Post, | ||||
|     safe_string::SafeString, schema::users, search::Searcher, timeline::Timeline, Connection, | ||||
|     Error, PlumeRocket, Result, CONFIG, ITEMS_PER_PAGE, | ||||
|     safe_string::SafeString, schema::users, timeline::Timeline, Connection, Error, PlumeRocket, | ||||
|     Result, CONFIG, ITEMS_PER_PAGE, | ||||
| }; | ||||
| use activitypub::{ | ||||
|     activity::Delete, | ||||
| @ -129,14 +129,14 @@ impl User { | ||||
|             .map_err(Error::from) | ||||
|     } | ||||
| 
 | ||||
|     pub fn delete(&self, conn: &Connection, searcher: &Searcher) -> Result<()> { | ||||
|     pub fn delete(&self, conn: &Connection) -> Result<()> { | ||||
|         use crate::schema::post_authors; | ||||
| 
 | ||||
|         for blog in Blog::find_for_author(conn, self)? | ||||
|             .iter() | ||||
|             .filter(|b| b.count_authors(conn).map(|c| c <= 1).unwrap_or(false)) | ||||
|         { | ||||
|             blog.delete(conn, searcher)?; | ||||
|             blog.delete(conn)?; | ||||
|         } | ||||
|         // delete the posts if they is the only author
 | ||||
|         let all_their_posts_ids: Vec<i32> = post_authors::table | ||||
| @ -156,7 +156,7 @@ impl User { | ||||
|                 .unwrap_or(&0) | ||||
|                 > &0; | ||||
|             if !has_other_authors { | ||||
|                 Post::get(conn, post_id)?.delete(conn, searcher)?; | ||||
|                 Post::get(conn, post_id)?.delete(conn)?; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -1037,7 +1037,7 @@ impl AsObject<User, Delete, &PlumeRocket> for User { | ||||
| 
 | ||||
|     fn activity(self, c: &PlumeRocket, actor: User, _id: &str) -> Result<()> { | ||||
|         if self.id == actor.id { | ||||
|             self.delete(&c.conn, &c.searcher).map(|_| ()) | ||||
|             self.delete(&c.conn).map(|_| ()) | ||||
|         } else { | ||||
|             Err(Error::Unauthorized) | ||||
|         } | ||||
| @ -1130,9 +1130,7 @@ impl NewUser { | ||||
| pub(crate) mod tests { | ||||
|     use super::*; | ||||
|     use crate::{ | ||||
|         config::CONFIG, | ||||
|         instance::{tests as instance_tests, Instance}, | ||||
|         search::tests::get_searcher, | ||||
|         tests::{db, rockets}, | ||||
|         Connection as Conn, | ||||
|     }; | ||||
| @ -1227,9 +1225,7 @@ pub(crate) mod tests { | ||||
|             let inserted = fill_database(conn); | ||||
| 
 | ||||
|             assert!(User::get(conn, inserted[0].id).is_ok()); | ||||
|             inserted[0] | ||||
|                 .delete(conn, &get_searcher(&CONFIG.search_tokenizers)) | ||||
|                 .unwrap(); | ||||
|             inserted[0].delete(conn).unwrap(); | ||||
|             assert!(User::get(conn, inserted[0].id).is_err()); | ||||
|             Ok(()) | ||||
|         }); | ||||
| @ -1319,7 +1315,7 @@ pub(crate) mod tests { | ||||
|             let users = fill_database(conn); | ||||
| 
 | ||||
|             let ap_repr = users[0].to_activity(conn).unwrap(); | ||||
|             users[0].delete(conn, &*r.searcher).unwrap(); | ||||
|             users[0].delete(conn).unwrap(); | ||||
|             let user = User::from_activity(&r, ap_repr).unwrap(); | ||||
| 
 | ||||
|             assert_eq!(user.username, users[0].username); | ||||
|  | ||||
| @ -10,12 +10,17 @@ msgstr "" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=6; plural=(n == 0) ? 0 : ((n == 1) ? 1 : ((n == 2) ? 2 : ((n == 3) ? 3 : ((n == 6) ? 4 : 5))));\n" | ||||
| "Plural-Forms: nplurals=6; plural=(n == 0) ? 0 : ((n == 1) ? 1 : ((n == 2) ? " | ||||
| "2 : ((n == 3) ? 3 : ((n == 6) ? 4 : 5))));\n" | ||||
| "X-Generator: crowdin.com\n" | ||||
| "X-Crowdin-Project: plume\n" | ||||
| "X-Crowdin-Language: cy\n" | ||||
| "X-Crowdin-File: /master/po/plume-front/plume-front.pot\n" | ||||
| 
 | ||||
| # plume-front/src/editor.rs:189 | ||||
| msgid "Do you want to load the local autosave last edited at {}?" | ||||
| msgstr "" | ||||
| 
 | ||||
| # plume-front/src/editor.rs:114 | ||||
| msgid "Open the rich text editor" | ||||
| msgstr "" | ||||
| @ -24,8 +29,8 @@ msgstr "" | ||||
| msgid "Title" | ||||
| msgstr "" | ||||
| 
 | ||||
| # plume-front/src/editor.rs:147 | ||||
| msgid "Subtitle or summary" | ||||
| # plume-front/src/editor.rs:319 | ||||
| msgid "Subtitle, or summary" | ||||
| msgstr "" | ||||
| 
 | ||||
| # plume-front/src/editor.rs:154 | ||||
| @ -55,4 +60,3 @@ msgstr "" | ||||
| # plume-front/src/editor.rs:259 | ||||
| msgid "Publish" | ||||
| msgstr "" | ||||
| 
 | ||||
|  | ||||
| @ -12,46 +12,46 @@ msgstr "" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" | ||||
| 
 | ||||
| # plume-front/src/editor.rs:189 | ||||
| # plume-front/src/editor.rs:188 | ||||
| msgid "Do you want to load the local autosave last edited at {}?" | ||||
| msgstr "" | ||||
| 
 | ||||
| # plume-front/src/editor.rs:282 | ||||
| # plume-front/src/editor.rs:281 | ||||
| msgid "Open the rich text editor" | ||||
| msgstr "" | ||||
| 
 | ||||
| # plume-front/src/editor.rs:315 | ||||
| # plume-front/src/editor.rs:314 | ||||
| msgid "Title" | ||||
| msgstr "" | ||||
| 
 | ||||
| # plume-front/src/editor.rs:319 | ||||
| # plume-front/src/editor.rs:318 | ||||
| msgid "Subtitle, or summary" | ||||
| msgstr "" | ||||
| 
 | ||||
| # plume-front/src/editor.rs:326 | ||||
| # plume-front/src/editor.rs:325 | ||||
| msgid "Write your article here. Markdown is supported." | ||||
| msgstr "" | ||||
| 
 | ||||
| # plume-front/src/editor.rs:337 | ||||
| # plume-front/src/editor.rs:336 | ||||
| msgid "Around {} characters left" | ||||
| msgstr "" | ||||
| 
 | ||||
| # plume-front/src/editor.rs:414 | ||||
| # plume-front/src/editor.rs:413 | ||||
| msgid "Tags" | ||||
| msgstr "" | ||||
| 
 | ||||
| # plume-front/src/editor.rs:415 | ||||
| # plume-front/src/editor.rs:414 | ||||
| msgid "License" | ||||
| msgstr "" | ||||
| 
 | ||||
| # plume-front/src/editor.rs:418 | ||||
| # plume-front/src/editor.rs:417 | ||||
| msgid "Cover" | ||||
| msgstr "" | ||||
| 
 | ||||
| # plume-front/src/editor.rs:438 | ||||
| # plume-front/src/editor.rs:437 | ||||
| msgid "This is a draft" | ||||
| msgstr "" | ||||
| 
 | ||||
| # plume-front/src/editor.rs:445 | ||||
| # plume-front/src/editor.rs:444 | ||||
| msgid "Publish" | ||||
| msgstr "" | ||||
|  | ||||
| @ -72,27 +72,27 @@ msgstr "" | ||||
| msgid "Your blog was successfully created!" | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/blogs.rs:160 | ||||
| # src/routes/blogs.rs:159 | ||||
| msgid "Your blog was deleted." | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/blogs.rs:168 | ||||
| # src/routes/blogs.rs:167 | ||||
| msgid "You are not allowed to delete this blog." | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/blogs.rs:219 | ||||
| # src/routes/blogs.rs:218 | ||||
| msgid "You are not allowed to edit this blog." | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/blogs.rs:275 | ||||
| # src/routes/blogs.rs:274 | ||||
| msgid "You can't use this media as a blog icon." | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/blogs.rs:293 | ||||
| # src/routes/blogs.rs:292 | ||||
| msgid "You can't use this media as a blog banner." | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/blogs.rs:327 | ||||
| # src/routes/blogs.rs:326 | ||||
| msgid "Your blog information have been updated." | ||||
| msgstr "" | ||||
| 
 | ||||
| @ -104,39 +104,39 @@ msgstr "" | ||||
| msgid "Your comment has been deleted." | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/instance.rs:119 | ||||
| # src/routes/instance.rs:118 | ||||
| msgid "Instance settings have been saved." | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/instance.rs:151 | ||||
| # src/routes/instance.rs:150 | ||||
| msgid "{} has been unblocked." | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/instance.rs:153 | ||||
| # src/routes/instance.rs:152 | ||||
| msgid "{} has been blocked." | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/instance.rs:202 | ||||
| # src/routes/instance.rs:201 | ||||
| msgid "Blocks deleted" | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/instance.rs:217 | ||||
| # src/routes/instance.rs:216 | ||||
| msgid "Email already blocked" | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/instance.rs:222 | ||||
| # src/routes/instance.rs:221 | ||||
| msgid "Email Blocked" | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/instance.rs:313 | ||||
| # src/routes/instance.rs:312 | ||||
| msgid "You can't change your own rights." | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/instance.rs:324 | ||||
| # src/routes/instance.rs:323 | ||||
| msgid "You are not allowed to take this action." | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/instance.rs:361 | ||||
| # src/routes/instance.rs:359 | ||||
| msgid "Done." | ||||
| msgstr "" | ||||
| 
 | ||||
| @ -188,31 +188,31 @@ msgstr "" | ||||
| msgid "You are not allowed to publish on this blog." | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/posts.rs:364 | ||||
| # src/routes/posts.rs:363 | ||||
| msgid "Your article has been updated." | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/posts.rs:555 | ||||
| # src/routes/posts.rs:553 | ||||
| msgid "Your article has been saved." | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/posts.rs:562 | ||||
| # src/routes/posts.rs:560 | ||||
| msgid "New article" | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/posts.rs:599 | ||||
| # src/routes/posts.rs:597 | ||||
| msgid "You are not allowed to delete this article." | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/posts.rs:624 | ||||
| # src/routes/posts.rs:622 | ||||
| msgid "Your article has been deleted." | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/posts.rs:629 | ||||
| # src/routes/posts.rs:627 | ||||
| msgid "It looks like the article you tried to delete doesn't exist. Maybe it is already gone?" | ||||
| msgstr "" | ||||
| 
 | ||||
| # src/routes/posts.rs:669 | ||||
| # src/routes/posts.rs:667 | ||||
| msgid "Couldn't obtain enough information about your account. Please make sure your username is correct." | ||||
| msgstr "" | ||||
| 
 | ||||
|  | ||||
| @ -105,7 +105,6 @@ pub fn create( | ||||
|     rockets: PlumeRocket, | ||||
| ) -> Api<PostData> { | ||||
|     let conn = &*rockets.conn; | ||||
|     let search = &rockets.searcher; | ||||
|     let worker = &rockets.worker; | ||||
| 
 | ||||
|     let author = User::get(conn, auth.0.user_id)?; | ||||
| @ -155,7 +154,6 @@ pub fn create( | ||||
|             source: payload.source.clone(), | ||||
|             cover_id: payload.cover_id, | ||||
|         }, | ||||
|         search, | ||||
|     )?; | ||||
| 
 | ||||
|     PostAuthor::insert( | ||||
| @ -232,7 +230,7 @@ pub fn delete(auth: Authorization<Write, Post>, rockets: PlumeRocket, id: i32) - | ||||
|     let author = User::get(&*rockets.conn, auth.0.user_id)?; | ||||
|     if let Ok(post) = Post::get(&*rockets.conn, id) { | ||||
|         if post.is_author(&*rockets.conn, author.id).unwrap_or(false) { | ||||
|             post.delete(&*rockets.conn, &rockets.searcher)?; | ||||
|             post.delete(&*rockets.conn)?; | ||||
|         } | ||||
|     } | ||||
|     Ok(Json(())) | ||||
|  | ||||
							
								
								
									
										65
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										65
									
								
								src/main.rs
									
									
									
									
									
								
							| @ -10,20 +10,17 @@ extern crate serde_json; | ||||
| #[macro_use] | ||||
| extern crate validator_derive; | ||||
| 
 | ||||
| use chrono::Utc; | ||||
| use clap::App; | ||||
| use diesel::r2d2::ConnectionManager; | ||||
| use plume_models::{ | ||||
|     db_conn::{DbPool, PragmaForeignKey}, | ||||
|     instance::Instance, | ||||
|     migrations::IMPORTED_MIGRATIONS, | ||||
|     search::{Searcher as UnmanagedSearcher, SearcherError}, | ||||
|     Connection, Error, CONFIG, | ||||
|     search::{actor::SearchActor, Searcher as UnmanagedSearcher}, | ||||
|     Connection, CONFIG, | ||||
| }; | ||||
| use rocket_csrf::CsrfFairingBuilder; | ||||
| use scheduled_thread_pool::ScheduledThreadPool; | ||||
| use std::fs; | ||||
| use std::path::Path; | ||||
| use std::process::exit; | ||||
| use std::sync::{Arc, Mutex}; | ||||
| use std::time::Duration; | ||||
| @ -103,59 +100,11 @@ Then try to restart Plume. | ||||
|     } | ||||
|     let workpool = ScheduledThreadPool::with_name("worker {}", num_cpus::get()); | ||||
|     // we want a fast exit here, so
 | ||||
|     let mut open_searcher = | ||||
|         UnmanagedSearcher::open(&CONFIG.search_index, &CONFIG.search_tokenizers); | ||||
|     if let Err(Error::Search(SearcherError::InvalidIndexDataError)) = open_searcher { | ||||
|         if UnmanagedSearcher::create(&CONFIG.search_index, &CONFIG.search_tokenizers).is_err() { | ||||
|             let current_path = Path::new(&CONFIG.search_index); | ||||
|             let backup_path = format!("{}.{}", ¤t_path.display(), Utc::now().timestamp()); | ||||
|             let backup_path = Path::new(&backup_path); | ||||
|             fs::rename(current_path, backup_path) | ||||
|                 .expect("main: error on backing up search index directory for recreating"); | ||||
|             if UnmanagedSearcher::create(&CONFIG.search_index, &CONFIG.search_tokenizers).is_ok() { | ||||
|                 if fs::remove_dir_all(backup_path).is_err() { | ||||
|                     warn!( | ||||
|                         "error on removing backup directory: {}. it remains", | ||||
|                         backup_path.display() | ||||
|                     ); | ||||
|                 } | ||||
|             } else { | ||||
|                 panic!("main: error on recreating search index in new index format. remove search index and run `plm search init` manually"); | ||||
|             } | ||||
|         } | ||||
|         open_searcher = UnmanagedSearcher::open(&CONFIG.search_index, &CONFIG.search_tokenizers); | ||||
|     } | ||||
|     #[allow(clippy::match_wild_err_arm)] | ||||
|     let searcher = match open_searcher { | ||||
|         Err(Error::Search(e)) => match e { | ||||
|             SearcherError::WriteLockAcquisitionError => panic!( | ||||
|                 r#" | ||||
| Your search index is locked. Plume can't start. To fix this issue | ||||
| make sure no other Plume instance is started, and run: | ||||
| 
 | ||||
|     plm search unlock | ||||
| 
 | ||||
| Then try to restart Plume. | ||||
| "#
 | ||||
|             ), | ||||
|             SearcherError::IndexOpeningError => panic!( | ||||
|                 r#" | ||||
| Plume was unable to open the search index. If you created the index | ||||
| before, make sure to run Plume in the same directory it was created in, or | ||||
| to set SEARCH_INDEX accordingly. If you did not yet create the search | ||||
| index, run this command: | ||||
| 
 | ||||
|     plm search init | ||||
| 
 | ||||
| Then try to restart Plume | ||||
| "#
 | ||||
|             ), | ||||
|             e => Err(e).unwrap(), | ||||
|         }, | ||||
|         Err(_) => panic!("Unexpected error while opening search index"), | ||||
|         Ok(s) => Arc::new(s), | ||||
|     }; | ||||
| 
 | ||||
|     let searcher = Arc::new(UnmanagedSearcher::open_or_recreate( | ||||
|         &CONFIG.search_index, | ||||
|         &CONFIG.search_tokenizers, | ||||
|     )); | ||||
|     SearchActor::init(searcher.clone(), dbpool.clone()); | ||||
|     let commiter = searcher.clone(); | ||||
|     workpool.execute_with_fixed_delay( | ||||
|         Duration::from_secs(5), | ||||
|  | ||||
| @ -153,8 +153,7 @@ pub fn delete(name: String, rockets: PlumeRocket) -> RespondOrRedirect { | ||||
|         .and_then(|u| u.is_author_in(&*conn, &blog).ok()) | ||||
|         .unwrap_or(false) | ||||
|     { | ||||
|         blog.delete(&conn, &rockets.searcher) | ||||
|             .expect("blog::expect: deletion error"); | ||||
|         blog.delete(&conn).expect("blog::expect: deletion error"); | ||||
|         Flash::success( | ||||
|             Redirect::to(uri!(super::instance::index)), | ||||
|             i18n!(rockets.intl.catalog, "Your blog was deleted."), | ||||
|  | ||||
| @ -21,7 +21,6 @@ use plume_models::{ | ||||
|     instance::*, | ||||
|     posts::Post, | ||||
|     safe_string::SafeString, | ||||
|     search::Searcher, | ||||
|     timeline::Timeline, | ||||
|     users::{Role, User}, | ||||
|     Connection, Error, PlumeRocket, CONFIG, | ||||
| @ -331,7 +330,6 @@ pub fn edit_users( | ||||
|     } | ||||
| 
 | ||||
|     let conn = &rockets.conn; | ||||
|     let searcher = &*rockets.searcher; | ||||
|     let worker = &*rockets.worker; | ||||
|     match form.action { | ||||
|         UserActions::Admin => { | ||||
| @ -351,7 +349,7 @@ pub fn edit_users( | ||||
|         } | ||||
|         UserActions::Ban => { | ||||
|             for u in form.ids.clone() { | ||||
|                 ban(u, conn, searcher, worker)?; | ||||
|                 ban(u, conn, worker)?; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @ -362,14 +360,9 @@ pub fn edit_users( | ||||
|     )) | ||||
| } | ||||
| 
 | ||||
| fn ban( | ||||
|     id: i32, | ||||
|     conn: &Connection, | ||||
|     searcher: &Searcher, | ||||
|     worker: &ScheduledThreadPool, | ||||
| ) -> Result<(), ErrorPage> { | ||||
| fn ban(id: i32, conn: &Connection, worker: &ScheduledThreadPool) -> Result<(), ErrorPage> { | ||||
|     let u = User::get(&*conn, id)?; | ||||
|     u.delete(&*conn, searcher)?; | ||||
|     u.delete(&*conn)?; | ||||
|     if Instance::get_local() | ||||
|         .map(|i| u.instance_id == i.id) | ||||
|         .unwrap_or(false) | ||||
|  | ||||
| @ -298,8 +298,7 @@ pub fn update( | ||||
|             post.source = form.content.clone(); | ||||
|             post.license = form.license.clone(); | ||||
|             post.cover_id = form.cover; | ||||
|             post.update(&*conn, &rockets.searcher) | ||||
|                 .expect("post::update: update error"); | ||||
|             post.update(&*conn).expect("post::update: update error"); | ||||
| 
 | ||||
|             if post.published { | ||||
|                 post.update_mentions( | ||||
| @ -481,7 +480,6 @@ pub fn create( | ||||
|                 source: form.content.clone(), | ||||
|                 cover_id: form.cover, | ||||
|             }, | ||||
|             &rockets.searcher, | ||||
|         ) | ||||
|         .expect("post::create: post save error"); | ||||
| 
 | ||||
|  | ||||
| @ -421,7 +421,7 @@ pub fn delete( | ||||
| ) -> Result<Flash<Redirect>, ErrorPage> { | ||||
|     let account = User::find_by_fqn(&rockets, &name)?; | ||||
|     if user.id == account.id { | ||||
|         account.delete(&*rockets.conn, &rockets.searcher)?; | ||||
|         account.delete(&*rockets.conn)?; | ||||
| 
 | ||||
|         let target = User::one_by_instance(&*rockets.conn)?; | ||||
|         let delete_act = account.delete_activity(&*rockets.conn)?; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user