mirror of
https://git.joinplu.me/Plume/Plume.git
synced 2024-11-25 21:11:01 +00:00
Merge branch 'master' of https://github.com/Plume-org/Plume into feature/reshare_to_boost
This commit is contained in:
commit
1fc89e8aeb
55 changed files with 1865 additions and 526 deletions
17
.editorconfig
Normal file
17
.editorconfig
Normal file
|
@ -0,0 +1,17 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{js,rs,css,tera}]
|
||||
charset = utf-8
|
||||
|
||||
[*.{rs,tera,css}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.js]
|
||||
indent_style = space
|
||||
indent_size = 2
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -6,3 +6,5 @@ rls
|
|||
translations
|
||||
po/*.po~
|
||||
.env
|
||||
Rocket.toml
|
||||
media
|
||||
|
|
459
Cargo.lock
generated
459
Cargo.lock
generated
|
@ -89,6 +89,35 @@ dependencies = [
|
|||
"nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ascii"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "atom_syndication"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"derive_builder 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quick-xml 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"debug-builders 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.6"
|
||||
|
@ -140,6 +169,11 @@ dependencies = [
|
|||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "0.9.1"
|
||||
|
@ -168,6 +202,16 @@ dependencies = [
|
|||
"opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "buf_redux"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"slice-deque 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build_const"
|
||||
version = "0.2.1"
|
||||
|
@ -202,6 +246,17 @@ name = "cfg-if"
|
|||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "chomp"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"debugtrace 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"either 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.2"
|
||||
|
@ -213,6 +268,11 @@ dependencies = [
|
|||
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chunked_transfer"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cloudabi"
|
||||
version = "0.0.3"
|
||||
|
@ -229,6 +289,14 @@ dependencies = [
|
|||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "conv"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
version = "0.11.0-dev"
|
||||
|
@ -316,11 +384,38 @@ dependencies = [
|
|||
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "custom_derive"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "dbghelp-sys"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "debug-builders"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "debugtrace"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive-error-chain"
|
||||
version = "0.11.1"
|
||||
|
@ -332,6 +427,25 @@ dependencies = [
|
|||
"syntex_fmt_macros 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"derive_builder_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder_core"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diesel"
|
||||
version = "1.2.2"
|
||||
|
@ -370,6 +484,68 @@ name = "dtoa"
|
|||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "encoding"
|
||||
version = "0.2.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-japanese"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-korean"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-simpchinese"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-singlebyte"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-tradchinese"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding_index_tests"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.7.2"
|
||||
|
@ -490,6 +666,59 @@ name = "glob"
|
|||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "groupable"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "guid"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"chomp 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"guid-macro-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"guid-parser 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "guid-create"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chomp 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"guid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"guid-parser 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "guid-macro-impl"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"chomp 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"guid-parser 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "guid-parser"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"chomp 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.0"
|
||||
|
@ -611,6 +840,21 @@ dependencies = [
|
|||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iron"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "isatty"
|
||||
version = "0.1.7"
|
||||
|
@ -708,6 +952,14 @@ name = "mac"
|
|||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "mach"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maplit"
|
||||
version = "1.0.1"
|
||||
|
@ -762,6 +1014,17 @@ dependencies = [
|
|||
"unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime_guess"
|
||||
version = "1.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime_guess"
|
||||
version = "2.0.0-alpha.4"
|
||||
|
@ -802,6 +1065,41 @@ dependencies = [
|
|||
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "modifier"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "multipart"
|
||||
version = "0.15.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"buf_redux 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"iron 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nickel 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tiny_http 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mustache"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.1.5"
|
||||
|
@ -834,6 +1132,25 @@ dependencies = [
|
|||
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nickel"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"groupable 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mustache 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nodrop"
|
||||
version = "0.1.12"
|
||||
|
@ -980,23 +1297,34 @@ name = "pkg-config"
|
|||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "plugin"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plume"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"activitypub 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atom_syndication 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"diesel 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dotenv 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gettext-rs 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"guid-create 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"multipart 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plume-common 0.1.0",
|
||||
"plume-models 0.1.0",
|
||||
"rocket 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)",
|
||||
"rocket_codegen 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)",
|
||||
"rocket_contrib 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)",
|
||||
"rocket_csrf 0.1.0 (git+https://github.com/fdb-hiroshima/rocket_csrf?branch=plume)",
|
||||
"rocket_csrf 0.1.0 (git+https://github.com/fdb-hiroshima/rocket_csrf?rev=0fbacab1bc6a32419a18edb600586c5c02fdac4d)",
|
||||
"rocket_i18n 0.1.1 (git+https://github.com/BaptisteGelez/rocket_i18n?rev=5b4225d5bed5769482dc926a7e6d6b79f1217be6)",
|
||||
"rpassword 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1068,6 +1396,19 @@ name = "precomputed-hash"
|
|||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack-impl"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.2.3"
|
||||
|
@ -1100,6 +1441,21 @@ dependencies = [
|
|||
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "1.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"encoding_rs 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.3.15"
|
||||
|
@ -1329,7 +1685,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "rocket_csrf"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/fdb-hiroshima/rocket_csrf?branch=plume#5309b7634a9cd204d003312cb70ce9d36b660e6b"
|
||||
source = "git+https://github.com/fdb-hiroshima/rocket_csrf?rev=0fbacab1bc6a32419a18edb600586c5c02fdac4d#0fbacab1bc6a32419a18edb600586c5c02fdac4d"
|
||||
dependencies = [
|
||||
"csrf 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"data-encoding 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1401,6 +1757,11 @@ name = "safemem"
|
|||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "safemem"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.12"
|
||||
|
@ -1509,6 +1870,16 @@ name = "slab"
|
|||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "slice-deque"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mach 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slug"
|
||||
version = "0.1.3"
|
||||
|
@ -1693,6 +2064,19 @@ dependencies = [
|
|||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny_http"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "0.1.5"
|
||||
|
@ -1855,11 +2239,27 @@ name = "traitobject"
|
|||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "twoway"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typeable"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "typemap"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unsafe-any 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.10.0"
|
||||
|
@ -1927,6 +2327,14 @@ dependencies = [
|
|||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unsafe-any"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.6.2"
|
||||
|
@ -2074,24 +2482,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5"
|
||||
"checksum array_tool 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8f8cb5d814eb646a863c4f24978cff2880c4be96ad8cde2c0f0678732902e271"
|
||||
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
|
||||
"checksum ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "97be891acc47ca214468e09425d02cef3af2c94d0d82081cd02061f996802f14"
|
||||
"checksum atom_syndication 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0a9a7ab83635ff7a3b04856f4ad95324dccc9b947ab1e790fc5c769ee6d6f60c"
|
||||
"checksum backtrace 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "150ae7828afa7afb6d474f909d64072d21de1f3365b6e8ad8029bf7b1c6350a0"
|
||||
"checksum backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe525f66f42d207968308ee86bc2dd60aa5fab535b22e616323a173d097d8e"
|
||||
"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"
|
||||
"checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9"
|
||||
"checksum base64 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9263aa6a38da271eec5c91a83ce1e800f093c8535788d403d626d8d5c3f8f007"
|
||||
"checksum bcrypt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a1512813db09170b44a00870b58421876d797b77b085c5205a24db90905f758"
|
||||
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
|
||||
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
|
||||
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
|
||||
"checksum block-cipher-trait 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6136d803280ae3532efa36114335255ea94f3d75d735ddedd66b0d7cd30bad3"
|
||||
"checksum blowfish 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "95ede07672d9f4144c578439aa352604ec5c67a80c940fe8d382ddbeeeb3c6d8"
|
||||
"checksum buf_redux 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20c6687a26c9ce967594b78038c06139a0d3a5b3005d16572284d543924a01aa"
|
||||
"checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39"
|
||||
"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
|
||||
"checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87"
|
||||
"checksum bytes 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "2f1d50c876fb7545f5f289cd8b2aee3f359d073ae819eed5d6373638e2c61e59"
|
||||
"checksum cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8b9d2900f78631a5876dc5d6c9033ede027253efcd33dd36b1309fc6cab97ee0"
|
||||
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||
"checksum chomp 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9f74ad218e66339b11fd23f693fb8f1d621e80ba6ac218297be26073365d163d"
|
||||
"checksum chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cce36c92cb605414e9b824f866f5babe0a0368e39ea07393b9b63cf3844c0e6"
|
||||
"checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87"
|
||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
"checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc"
|
||||
"checksum conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299"
|
||||
"checksum cookie 0.11.0-dev (git+https://github.com/alexcrichton/cookie-rs?rev=0365a18)" = "<none>"
|
||||
"checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67"
|
||||
"checksum core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d"
|
||||
|
@ -2101,12 +2517,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
|
||||
"checksum crossbeam-utils 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d636a8b3bcc1b409d7ffd3facef8f21dcb4009626adbd0c5e6c4305c07253c7b"
|
||||
"checksum csrf 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "38f2ee2a7e76740d81de006e61eff53206c56448a30d8017b4ac97b5486682bd"
|
||||
"checksum custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9"
|
||||
"checksum data-encoding 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "67df0571a74bf0d97fb8b2ed22abdd9a48475c96bd327db968b7d9cace99655e"
|
||||
"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
|
||||
"checksum debug-builders 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f5d8e3d14cabcb2a8a59d7147289173c6ada77a0bc526f6b85078f941c0cf12"
|
||||
"checksum debugtrace 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62e432bd83c5d70317f6ebd8a50ed4afb32907c64d6e2e1e65e339b06dc553f3"
|
||||
"checksum derive-error-chain 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4450afbe280461e78299b39182a085b70e3e71be049cf4a588ad72f1e44d33"
|
||||
"checksum derive_builder 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c998e6ab02a828dd9735c18f154e14100e674ed08cb4e1938f0e4177543f439"
|
||||
"checksum derive_builder_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "735e24ee9e5fa8e16b86da5007856e97d592e11867e45d76e0c0d0a164a0b757"
|
||||
"checksum diesel 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24815a0c2094f2c8dafe74ab3b9e975892f44acbb94b4d4b4898025a7615efa4"
|
||||
"checksum diesel_derives 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6471a2b637b414d3ee1504cf230409a550381c79204282f8fe06c527e4ae56be"
|
||||
"checksum dotenv 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a70de3c590ce18df70743cace1cf12565637a0b26fd8b04ef10c7d33fdc66cdc"
|
||||
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
|
||||
"checksum either 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a39bffec1e2015c5d8a6773cb0cf48d0d758c842398f624c34969071f5499ea7"
|
||||
"checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec"
|
||||
"checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91"
|
||||
"checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81"
|
||||
"checksum encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7"
|
||||
"checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a"
|
||||
"checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18"
|
||||
"checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
|
||||
"checksum encoding_rs 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98fd0f24d1fb71a4a6b9330c8ca04cbd4e7cc5d846b54ca74ff376bc7c9f798d"
|
||||
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
|
||||
"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82"
|
||||
|
@ -2123,6 +2553,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum gettext-rs 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b8c2412d5758f68a9eeba161f9ecb9a55f56bfdbf17857650b98f2b9b281a47"
|
||||
"checksum gettext-sys 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)" = "62c644c0b8b73706fb8c7420533fd30abf6f41c2703994bc6f0826fceb7fb3d6"
|
||||
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
|
||||
"checksum groupable 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32619942b8be646939eaf3db0602b39f5229b74575b67efc897811ded1db4e57"
|
||||
"checksum guid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e691c64d9b226c7597e29aeb46be753beb8c9eeef96d8c78dfd4d306338a38da"
|
||||
"checksum guid-create 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcea207bf7a6092166ab590f98fe5dde5a7deed1f1920d98dcac31f80814c40d"
|
||||
"checksum guid-macro-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08d50f7c496073b5a5dec0f6f1c149113a50960ce25dd2a559987a5a71190816"
|
||||
"checksum guid-parser 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "abc7adb441828023999e6cff9eb1ea63156f7ec37ab5bf690005e8fc6c1148ad"
|
||||
"checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82"
|
||||
"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
|
||||
"checksum html5ever 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b04478cf718862650a0bf66acaf8f2f8c906fbc703f35c916c1f4211b069a364"
|
||||
|
@ -2135,6 +2570,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "61bb90bdd39e3af69b0172dfc6130f6cd6332bf040fbb9bdd4401d37adbd48b8"
|
||||
"checksum indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08173ba1e906efb6538785a8844dd496f5d34f0a2d88038e95195172fc667220"
|
||||
"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
|
||||
"checksum iron 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d8e17268922834707e1c29e8badbf9c712c9c43378e1b6a3388946baff10be2"
|
||||
"checksum isatty 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a118a53ba42790ef25c82bb481ecf36e2da892646cccd361e69a6bb881e19398"
|
||||
"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
|
||||
"checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682"
|
||||
|
@ -2149,6 +2585,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
|
||||
"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2"
|
||||
"checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
||||
"checksum mach 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "977262a11cfd76b94da10b8898cea6e9ac391301ab74741e6da6bee13d7df46d"
|
||||
"checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43"
|
||||
"checksum markup5ever 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfedc97d5a503e96816d10fedcd5b42f760b2e525ce2f7ec71f6a41780548475"
|
||||
"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
|
||||
|
@ -2156,12 +2593,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
|
||||
"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0"
|
||||
"checksum mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e00e17be181010a91dbfefb01660b17311059dc8c7f48b9017677721e732bd"
|
||||
"checksum mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2d4c0961143b8efdcfa29c3ae63281601b446a4a668165454b6c90f8024954c5"
|
||||
"checksum mime_guess 2.0.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "130ea3c9c1b65dba905ab5a4d9ac59234a9585c24d135f264e187fe7336febbd"
|
||||
"checksum mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "6d771e3ef92d58a8da8df7d6976bfca9371ed1de6619d9d5a5ce5b1f29b85bfe"
|
||||
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
|
||||
"checksum modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41f5c9112cb662acd3b204077e0de5bc66305fa8df65c8019d5adb10e9ab6e58"
|
||||
"checksum multipart 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b3bd50d71866514b14d2ca09823d81390d92daa40bc835f83a908c52ab0a802e"
|
||||
"checksum mustache 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb004e419334fc9172d0a5ff91c0770bdd6239091b0b343eb5926101f0a7d13"
|
||||
"checksum native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f74dbadc8b43df7864539cedb7bc91345e532fdd913cfdc23ad94f4d2d40fbc0"
|
||||
"checksum net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "9044faf1413a1057267be51b5afba8eb1090bd2231c693664aa1db716fe1eae0"
|
||||
"checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"
|
||||
"checksum nickel 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "22b40e35b9f46a076dcbd8193125cea0e4130b1c015f68655038010f3e826e04"
|
||||
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
|
||||
"checksum num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f8d26da319fb45674985c78f1d1caf99aa4941f785d384a2ae36d0740bc3e2fe"
|
||||
"checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364"
|
||||
|
@ -2180,12 +2622,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "05a079dd052e7b674d21cb31cbb6c05efd56a2cd2827db7692e2f1a507ebd998"
|
||||
"checksum phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c2261d544c2bb6aa3b10022b0be371b9c7c64f762ef28c6f5d4f1ef6d97b5930"
|
||||
"checksum pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "110d5ee3593dbb73f56294327fe5668bcc997897097cbc76b51e7aed3f52452f"
|
||||
"checksum plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a6a0dc3910bc8db877ffed8e457763b317cf880df4ae19109b9f77d277cf6e0"
|
||||
"checksum pq-sys 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4dfb5e575ef93a1b7b2a381d47ba7c5d4e4f73bff37cee932195de769aad9a54"
|
||||
"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||
"checksum proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ba8d4f9257b85eb6cdf13f055cea3190520aab1409ca2ab43493ea4820c25f0"
|
||||
"checksum proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5cb6f960ad471404618e9817c0e5d10b1ae74cfdf01fab89ea0641fe7fb2892"
|
||||
"checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0"
|
||||
"checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118"
|
||||
"checksum proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "effdb53b25cdad54f8f48843d67398f7ef2e14f12c1b4cb4effc549a6462a4d6"
|
||||
"checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32"
|
||||
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
|
||||
"checksum quick-xml 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b14c27e04216596a49f2b82398a24f67ed9f131a5c0e0235496ea446bdacfb12"
|
||||
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
|
||||
"checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408"
|
||||
"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8"
|
||||
|
@ -2208,7 +2655,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum rocket_codegen 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)" = "<none>"
|
||||
"checksum rocket_codegen_next 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)" = "<none>"
|
||||
"checksum rocket_contrib 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)" = "<none>"
|
||||
"checksum rocket_csrf 0.1.0 (git+https://github.com/fdb-hiroshima/rocket_csrf?branch=plume)" = "<none>"
|
||||
"checksum rocket_csrf 0.1.0 (git+https://github.com/fdb-hiroshima/rocket_csrf?rev=0fbacab1bc6a32419a18edb600586c5c02fdac4d)" = "<none>"
|
||||
"checksum rocket_http 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)" = "<none>"
|
||||
"checksum rocket_i18n 0.1.1 (git+https://github.com/BaptisteGelez/rocket_i18n?rev=5b4225d5bed5769482dc926a7e6d6b79f1217be6)" = "<none>"
|
||||
"checksum rpassword 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d127299b02abda51634f14025aec43ae87a7aa7a95202b6a868ec852607d1451"
|
||||
|
@ -2216,6 +2663,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb"
|
||||
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
||||
"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f"
|
||||
"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9"
|
||||
"checksum schannel 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "85fd9df495640643ad2d00443b3d78aae69802ad488debab4f1dd52fc1806ade"
|
||||
"checksum scheduled-thread-pool 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a2ff3fc5223829be817806c6441279c676e454cc7da608faf03b0ccc09d3889"
|
||||
"checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4"
|
||||
|
@ -2230,6 +2678,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
|
||||
"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
|
||||
"checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d"
|
||||
"checksum slice-deque 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "79e5bb98247a0eb0cfdedb7e792962ec71ac1003033f70558bd9961f8912e487"
|
||||
"checksum slug 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "797bcb4d24e91239a8615415814f4afb2d8ca400c472de3c73f803a5a7689e11"
|
||||
"checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013"
|
||||
"checksum smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "26df3bb03ca5eac2e64192b723d51f56c1b1e0860e7c766281f4598f181acdc8"
|
||||
|
@ -2250,6 +2699,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum tera 0.11.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e815b67d44c26feb06630011fb58b5b243f4e9585aac1ed0592c5795de64cd75"
|
||||
"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
|
||||
"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
|
||||
"checksum tiny_http 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a442681f9f72e440be192700eeb2861e4174b9983f16f4877c93a134cb5e5f63"
|
||||
"checksum tokio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be15ef40f675c9fe66e354d74c73f3ed012ca1aa14d65846a33ee48f1ae8d922"
|
||||
"checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71"
|
||||
"checksum tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8cac2a7883ff3567e9d66bb09100d09b33d90311feca0206c7ca034bc0c55113"
|
||||
|
@ -2264,7 +2714,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum tokio-udp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "137bda266504893ac4774e0ec4c2108f7ccdbcb7ac8dced6305fe9e4e0b5041a"
|
||||
"checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9"
|
||||
"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
|
||||
"checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1"
|
||||
"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887"
|
||||
"checksum typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "653be63c80a3296da5551e1bfd2cca35227e13cdd08c6668903ae2f4f77aa1f6"
|
||||
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
|
||||
"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
|
||||
"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
|
||||
|
@ -2276,6 +2728,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
"checksum unidecode 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "402bb19d8e03f1d1a7450e2bd613980869438e0666331be3e073089124aa1adc"
|
||||
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
|
||||
"checksum unsafe-any 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f30360d7979f5e9c6e6cea48af192ea8fab4afb3cf72597154b8f08935bc9c7f"
|
||||
"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f"
|
||||
"checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7"
|
||||
"checksum utf-8 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1262dfab4c30d5cb7c07026be00ee343a6cf5027fdc0104a9160f354e5db75c"
|
||||
|
|
|
@ -4,11 +4,14 @@ name = "plume"
|
|||
version = "0.1.0"
|
||||
[dependencies]
|
||||
activitypub = "0.1.1"
|
||||
atom_syndication = "0.6"
|
||||
colored = "1.6"
|
||||
dotenv = "*"
|
||||
failure = "0.1"
|
||||
gettext-rs = "0.4"
|
||||
guid-create = "0.1"
|
||||
heck = "0.3.0"
|
||||
multipart = "0.15"
|
||||
rpassword = "2.0"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
|
@ -42,8 +45,8 @@ git = "https://github.com/SergioBenitez/Rocket"
|
|||
rev = "df7111143e466c18d1f56377a8d9530a5a306aba"
|
||||
|
||||
[dependencies.rocket_csrf]
|
||||
branch = "plume"
|
||||
git = "https://github.com/fdb-hiroshima/rocket_csrf"
|
||||
rev = "0fbacab1bc6a32419a18edb600586c5c02fdac4d"
|
||||
|
||||
[dependencies.rocket_i18n]
|
||||
git = "https://github.com/BaptisteGelez/rocket_i18n"
|
||||
|
|
72
INSTALL.md
72
INSTALL.md
|
@ -1,72 +0,0 @@
|
|||
# How to install Plume on a Debian stretch:
|
||||
|
||||
## Basic setup:
|
||||
|
||||
```bash
|
||||
apt update
|
||||
apt install gettext postgresql postgresql-contrib libpq-dev
|
||||
adduser plume
|
||||
su - plume
|
||||
cd /home/plume
|
||||
git clone https://github.com/Plume-org/Plume.git
|
||||
curl https://sh.rustup.rs -sSf | sh
|
||||
cd Plume
|
||||
rustup toolchain install nightly
|
||||
rustup toolchain default nightly
|
||||
rustup update
|
||||
cargo install diesel_cli --no-default-features --features postgres --version '=1.2.0' # we dont need to compile anything else than pgsql
|
||||
```
|
||||
|
||||
## Now, if you want to run postgresql on the same server:
|
||||
|
||||
```bash
|
||||
service postgresql start
|
||||
cargo run # this will configure and launch Plume on the server.
|
||||
```
|
||||
|
||||
## If you want to run Plume with a remote DB this time ( Postgresql is not installed on the same server/container):
|
||||
|
||||
* On the DB server:
|
||||
|
||||
```bash
|
||||
service postgresql start
|
||||
su - postgres
|
||||
createuser -d -P plume
|
||||
createdb -O plume plume
|
||||
```
|
||||
|
||||
* On the Plume server:
|
||||
|
||||
```bash
|
||||
cd /home/plume/Plume
|
||||
diesel migration run --database-url postgres://plume:PASSWORD@DBSERVERIP:DBPORT/plume
|
||||
DB_URL=postgres://plume:PASSWORD@DBSERVERIP:DBPORT/plume cargo run # the first launch will ask questions to configure the instance. A second launch will not need the DB_URL.
|
||||
```
|
||||
|
||||
## Plume is now accessible as seen on your console. You can have fun now, or configure an nginx proxy with the following excerpt:
|
||||
|
||||
location / {
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $http_host;
|
||||
|
||||
proxy_pass http://localhost:8000;
|
||||
|
||||
client_max_body_size 16m;
|
||||
}
|
||||
|
||||
# Caveats:
|
||||
|
||||
* Pgbouncer is not yet supported ( named transactions are used ).
|
||||
|
||||
* Rust nightly is a moving target, dependancies can break and sometimes you need to check a few versions to find the one working.
|
||||
|
||||
```bash
|
||||
cd /home/plume/Plume
|
||||
rustup override set nightly-2018-05-15 # this could be needed for compilation. If errors, try 2018-05-31.
|
||||
# rustup override unset # remove the override for this directory.
|
||||
```
|
||||
|
||||
* Rust nightly 2018-06-28 is known to be failing to compile diesel 1.3.2
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
# Installing Software Prerequisites
|
||||
|
||||
These instructions have been adapted from the Aardwolf documentation, and may not be accurate.
|
||||
As such, this notification should be updated once verified for Plume installs.
|
||||
|
||||
> NOTE: These instructions may help in installing a production version, but are
|
||||
intended for developers to be able to build and test their changes. If in doubt,
|
||||
seek out documentation from your distribution package or from [the `doc` folder](doc).
|
||||
|
||||
## Installing Requirements
|
||||
|
||||
### Installing PostgreSQL
|
||||
|
||||
In order to run the Plume backend, you will need to have access to a
|
||||
[PostgreSQL](https://www.postgresql.org/) database. There are a few options for doing this, but for
|
||||
this guide we’re going to assume you are running the database on your
|
||||
development machine.
|
||||
|
||||
#### Linux/OSX Instructions
|
||||
|
||||
If you're on an Ubuntu-like machine, you should be able to install
|
||||
PostgreSQL like this:
|
||||
|
||||
$ sudo apt-get update
|
||||
$ sudo apt-get install postgresql postgresql-contrib
|
||||
|
||||
If you see an error like:
|
||||
|
||||
= note: /usr/bin/ld: cannot find -lpq
|
||||
collect2: error: ld returned 1 exit statusb
|
||||
|
||||
Then you may need to install the libpq (PostgreSQL C-library) package as well :
|
||||
|
||||
$ sudo apt-get install libpq-dev
|
||||
|
||||
If you're on OSX and using `brew`, do
|
||||
|
||||
$ brew update
|
||||
$ brew install postgres
|
||||
|
||||
For Gentoo (eselect-postgresql is optional),
|
||||
|
||||
# emerge --sync
|
||||
# emerge -av postgresql eselect-postgresql
|
||||
|
||||
For Fedora/CentOS/RHEL, do
|
||||
|
||||
# dnf install postgresql-server postgresql-contrib mariadb-devel libsq3-devel libpqxx libpqxx-devel
|
||||
|
||||
|
||||
#### Windows Instructions
|
||||
|
||||
For Windows, just download the installer [here](https://www.enterprisedb.com/downloads/postgres-postgresql-downloads#windows) and run it. After installing, make sure to add the <POSTGRES INSTALL PATH>/lib directory to your PATH system variable.
|
||||
|
||||
### Installing rustup
|
||||
|
||||
> Note: Rustup managed installations do appear to co-exist with system
|
||||
installations on Gentoo, and should work on most other distributions.
|
||||
If not, please file an issue with the Rust and Rustup teams or your distribution’s
|
||||
managers.
|
||||
|
||||
Next, you’ll need to have the [Rust](https://rust-lang.org/) toolchain
|
||||
installed. The best way to do this is to install
|
||||
[rustup](https://rustup.rs), which is a Rust toolchain manager.
|
||||
|
||||
#### Linux/OSX Instructions
|
||||
|
||||
Open your terminal and run the following command:
|
||||
|
||||
$ curl https://sh.rustup.rs -sSf | sh
|
||||
|
||||
For those who are (understandably) uncomfortable with piping a shell
|
||||
script from the internet directly into `sh`, you can also
|
||||
[use an alternate installation method](https://github.com/rust-lang-nursery/rustup.rs/#other-installation-methods).
|
||||
|
||||
#### Windows Instructions
|
||||
|
||||
If you don't already have them, download and install the [Visual C++ 2015 Build Tools](http://landinghub.visualstudio.com/visual-cpp-build-tools).
|
||||
|
||||
Then, download the [rustup installer](https://www.rust-lang.org/en-US/install.html) and run it. That's it!
|
||||
|
||||
### Installing Rust Toolchain
|
||||
|
||||
Once you have `rustup` installed, make sure you have the `nightly` rust
|
||||
toolchain installed:
|
||||
|
||||
$ rustup toolchain install nightly
|
||||
|
||||
### Installing GetText
|
||||
|
||||
GetText is the tool we use to manage translations. It will be needed at runtime, since we only compile
|
||||
translation files when starting Plume.
|
||||
|
||||
#### Ubuntu-like Linux
|
||||
|
||||
$ sudo apt-get install gettext
|
|
@ -1,74 +1,10 @@
|
|||
# Development Guide
|
||||
|
||||
## Running Plume locally
|
||||
## Installing the development environment
|
||||
|
||||
### Mac OSX
|
||||
Please refer to the [installation guide](INSTALL.md).
|
||||
|
||||
All commands are run in the Mac Terminal or terminal emulator of your choice, such as iTerm2. First, you will need [Git](https://git-scm.com/download/mac), [Homebrew](https://brew.sh/), [Rust](https://www.rust-lang.org/en-US/), and [Postgres](https://www.postgresql.org/). Follow the instructions to install Homebrew before continuing if you don't already have it.
|
||||
|
||||
### Linux
|
||||
|
||||
Similar to Mac OSX all commands should be run from a terminal (a.k.a command line). First, you will need [Git](https://git-scm.com/download/mac), [Rust](https://www.rust-lang.org/en-US/), and [Postgres](https://www.postgresql.org/). Step-by-step instructions are also available here: [Installing Prerequisites](/doc/PREREQUISITES.md)
|
||||
|
||||
#### Download the Repository
|
||||
|
||||
Navigate to the directory on your machine where you would like to install the repository, such as in `~/dev` by running `cd dev`. Now, clone the remote repository by running `git clone https://github.com/Plume-org/Plume.git`. This will install the codebase to the `Plume` subdirectory. Navigate into that directory by running `cd Plume`.
|
||||
|
||||
#### Rust
|
||||
|
||||
If you think you might already have rust on your machine, you can check by running
|
||||
|
||||
```
|
||||
rustc --version
|
||||
# Should output something like
|
||||
# rustc 1.28.0-nightly (a805a2a5e 2018-06-10)
|
||||
```
|
||||
|
||||
If you don't already have Rust, install it by running
|
||||
|
||||
```
|
||||
curl https://sh.rustup.rs -sSf | sh
|
||||
```
|
||||
|
||||
In the interactive installation, choose the option of the nightly toolchain. Restart your console so that the `rustc` CLI tool is available.
|
||||
|
||||
#### Postgres
|
||||
|
||||
Now we will use Homebrew to install Postgres. If you think you might already have it, try running `brew info postgres`. If it is not available, continue to install Postgres by running the following:
|
||||
|
||||
```
|
||||
brew install postgres
|
||||
```
|
||||
|
||||
Now, you can use the following command to start Postgres on a one-time basis.
|
||||
|
||||
```
|
||||
pg_ctl -D /usr/local/var/postgres start
|
||||
```
|
||||
|
||||
When you will launch Plume for the first time, it will setup the database by itself.
|
||||
|
||||
#### Database Migration
|
||||
|
||||
To run migrations and correctly setup the database, Plume use the `diesel` CLI tool under the hood. Therefore you should install it before running Plume. If this was your time installing Rust, you will probably need to run that using `cargo`. `cargo` is installed with `rustc` so if you followed the earlier instructions it will already be available.
|
||||
|
||||
```
|
||||
cargo install diesel_cli --version '=1.2.0'
|
||||
```
|
||||
|
||||
#### Running Plume
|
||||
|
||||
To run Plume locally, make sure you are once again in the Plume directory, such as `~/dev/Plume`. Now you will be able to run the application using the command
|
||||
|
||||
```
|
||||
cargo run
|
||||
```
|
||||
|
||||
#### Configuration
|
||||
|
||||
The first time you'll run Plume, it will help you setup your instance through an interactive tool. Once you'll have answered all its question, your instance will start.
|
||||
|
||||
#### Testing the federation
|
||||
## Testing the federation
|
||||
|
||||
To test the federation, you'll need to setup another database (see "Setup the database"),
|
||||
also owned by the "plume" user, but with a different name. Then, you'll need to run the
|
||||
|
@ -93,7 +29,7 @@ If you don't want to setup HTTPS locally, you can also disable it by running you
|
|||
USE_HTTPS=0 cargo run
|
||||
```
|
||||
|
||||
#### Making a Pull Request
|
||||
## Making a Pull Request
|
||||
To create an upstream fork of the repository in GitHub, click "Fork" in the top right button on the main page of the [Plume repository](https://github.com/Plume-org/Plume). Now, in the command line, set another remote for the repository by running the following command, replacing `myname` with the name under which you forked the repo. You can use another name besides `upstream` if you prefer. Using [SSH](https://help.github.com/articles/connecting-to-github-with-ssh/) is recommended.
|
||||
|
||||
```
|
||||
|
@ -105,7 +41,7 @@ Now, make any changes to the code you want. After committing your changes, push
|
|||
|
||||
The project maintainers may suggest further changes to improve the pull request even more. After implementing this locally, you can push to your upstream fork again and the changes will immediately show up in the pull request after pushing. Once all the suggested changes are made, the pull request may be accepted. Thanks for contributing.
|
||||
|
||||
#### When working with Tera templates
|
||||
## When working with Tera templates
|
||||
|
||||
When working with the interface, or any message that will be displayed to the final user, keep in mind that Plume is an internationalized software. To make sure that the parts of the interface you are changing are translatable, you should:
|
||||
|
||||
|
@ -139,3 +75,13 @@ msgstr[1] ""
|
|||
```
|
||||
|
||||
And that's it! Once these new messages will have been translated, they will correctly be displayed in the requested locale!
|
||||
|
||||
## Code Style
|
||||
|
||||
For Rust, use the standard style. `rustfmt` can help you keeping your code clean.
|
||||
|
||||
For CSS, the only rule is to use One True Brace Style.
|
||||
|
||||
For JavaScript, we use [the JavaScript Standard Style](https://standardjs.com/).
|
||||
|
||||
For HTML/Tera templates, we use HTML5 syntax.
|
383
docs/INSTALL.md
Normal file
383
docs/INSTALL.md
Normal file
|
@ -0,0 +1,383 @@
|
|||
# Installing Plume (for development or production)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
In order to be installed and to work correctly, Plume needs:
|
||||
|
||||
- *Git* (to get the code)
|
||||
- *Curl* (for RustUp, the Rust installer)
|
||||
- *GCC* and *make* (to compile C dependencies)
|
||||
- *PostgreSQL* (for the database)
|
||||
- *GetText* (to manage translations)
|
||||
- *Rust* and *Cargo* (to build the code)
|
||||
- *OpenSSL* and *OpenSSL librairies* (for security)
|
||||
|
||||
All the following instructions will need a terminal.
|
||||
|
||||
Here are the commands to install PostgreSQL and GetText on various operating systems.
|
||||
Some of them may need root permissions.
|
||||
|
||||
On **Debian**:
|
||||
|
||||
```bash
|
||||
apt update
|
||||
apt install gettext postgresql postgresql-contrib libpq-dev git curl gcc make openssl libssl-dev
|
||||
```
|
||||
|
||||
On **Fedora**, **CentOS** or **RHEL**:
|
||||
|
||||
```bash
|
||||
dnf install postgresql-server postgresql-contrib mariadb-devel libsq3-devel libpqxx libpqxx-devel git curl gcc make openssl openssl-devel gettext
|
||||
```
|
||||
|
||||
On **Gentoo**:
|
||||
|
||||
```bash
|
||||
emerge --sync
|
||||
emerge -av postgresql eselect-postgresql gettext && emerge --ask dev-vcs/git
|
||||
```
|
||||
|
||||
On **Mac OS X**, with [Homebrew](https://brew.sh/):
|
||||
|
||||
```bash
|
||||
brew update
|
||||
brew install postgres gettext git
|
||||
```
|
||||
|
||||
## Creating a new user (optional)
|
||||
|
||||
This step is recommended if you are in a **production environment**, but it is not necessary.
|
||||
|
||||
```bash
|
||||
adduser plume
|
||||
su - plume
|
||||
cd ~
|
||||
```
|
||||
|
||||
Creating a new user will let you use systemd to manage Plume if you want (see the dedicated section below).
|
||||
|
||||
## Installing Rust and Cargo
|
||||
|
||||
We said that Plume needed Rust and Cargo to work, but we didn't installed them at the same time as PostgreSQL and GetText, because there is an universal installation method called RustUp.
|
||||
|
||||
You can install it on **GNU/Linux** and **Mac OS X** with:
|
||||
|
||||
```bash
|
||||
curl https://sh.rustup.rs -sSf | sh
|
||||
```
|
||||
|
||||
When asked, choose the *"1) Proceed with installation (default)"* option.
|
||||
|
||||
Then run this command to be able to run cargo in the current session:
|
||||
|
||||
```bash
|
||||
export PATH="$PATH:/home/plume/.cargo/bin:/home/plume/.local/bin:/usr/local/sbin"
|
||||
```
|
||||
|
||||
On **Windows**, you'll need, if you don't already have them, to download and install the [Visual C++ 2015 Build Tools](https://www.microsoft.com/en-us/download/details.aspx?id=48159). Then, download the [rustup installer](https://www.rust-lang.org/en-US/install.html) and run it.
|
||||
|
||||
## Getting and compiling the Plume source code
|
||||
|
||||
Plume needs to be compiled from source.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Plume-org/Plume.git
|
||||
cd Plume
|
||||
|
||||
# This may take some time as RustUp will download all
|
||||
# the required Rust components, and Cargo will download
|
||||
# and compile all dependencies.
|
||||
cargo build
|
||||
```
|
||||
|
||||
We may provide precompiled packages and Docker images in the future (if you have experience in these fields and want to help, you're welcome).
|
||||
|
||||
## Configuring PostgreSQL
|
||||
|
||||
You can either run PostgreSQL from the machine that runs Plume, or from another server. We recommend you to use the first setup for development environments, or in production for small instances.
|
||||
|
||||
In the first case, just run this command after the PostgreSQL installation, to start it:
|
||||
|
||||
```
|
||||
service postgresql start
|
||||
```
|
||||
|
||||
If you want to have two separate machines, run these commands on the database server after you installed the dependencies mentionned above on both servers:
|
||||
|
||||
```bash
|
||||
service postgresql start
|
||||
su - postgres
|
||||
createuser -d -P plume
|
||||
createdb -O plume plume
|
||||
```
|
||||
|
||||
|
||||
## Running migrations
|
||||
|
||||
Migrations are scripts to update the database. They are run by a tool called Diesel, which can be installed with:
|
||||
|
||||
```bash
|
||||
cargo install diesel_cli --no-default-features --features postgres --version '=1.2.0'
|
||||
```
|
||||
|
||||
Plume should normally run migrations for you when needed, but if you want to run them manually, the command is:
|
||||
|
||||
```bash
|
||||
diesel migration run --database-url postgres://USER:PASSWORD@IP:PORT/plume
|
||||
```
|
||||
|
||||
This command may be useful if you decided to use a separate database server.
|
||||
|
||||
## Starting Plume
|
||||
|
||||
When you launch Plume for the first time, it will ask you a few questions to setup your instance before it actually launches. To start it, run these commands.
|
||||
|
||||
```
|
||||
# Optional, only do it if the database URL is not
|
||||
# postgres://plume:plume@localhost/plume
|
||||
export DB_URL=postgres://plume:PASSWORD@DBSERVERIP:DBPORT/plume
|
||||
|
||||
cargo run
|
||||
```
|
||||
|
||||
## Configuring Nginx
|
||||
|
||||
Here is a sample Nginx configuration for a Plume instance (replace `blog.example.com` with your domain name):
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name blog.example.com;
|
||||
|
||||
location /.well-known/acme-challenge {}
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
server_name blog.example.org;
|
||||
access_log /var/log/nginx/access.log;
|
||||
|
||||
listen [::]:443 ssl; # managed by Certbot
|
||||
SSLCertificateFile /etc/letsencrypt/live/blog.example.com/cert.pem
|
||||
SSLCertificateKeyFile /etc/letsencrypt/live/blog.example.com/privkey.pem
|
||||
SSLCertificateChainFile /etc/letsencrypt/live/blog.example.com/chain.pem
|
||||
|
||||
# for ssl conf: https://cipherli.st/
|
||||
ssl_protocols TLSv1.2 TLSv1.3;# Requires nginx >= 1.13.0 else use TLSv1.2
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;# openssl dhparam -out /etc/letsencrypt/ssl-dhparam.pem 4096
|
||||
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
|
||||
ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0
|
||||
ssl_session_timeout 10m;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_tickets off; # Requires nginx >= 1.5.9
|
||||
ssl_stapling on; # Requires nginx >= 1.3.7
|
||||
ssl_stapling_verify on; # Requires nginx => 1.3.7
|
||||
resolver 9.9.9.9 80.67.169.12 valid=300s;
|
||||
resolver_timeout 5s;
|
||||
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
|
||||
add_header X-Frame-Options DENY;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header Content-Security-Policy "default-src 'self';";
|
||||
add_header Content-Security-Policy "frame-ancestors 'self'";
|
||||
|
||||
location ~* \.(jpg|jpeg|png|gif|ico|js|pdf)$ {
|
||||
add_header Cache-Control "public";
|
||||
expires 7d;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:7878/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
client_max_body_size 10m;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Configuring Apache
|
||||
|
||||
If you prefer Apache, you can use this configuration (here too replace `blog.example.com` with your domain):
|
||||
|
||||
```apache
|
||||
<VirtualHost *:80>
|
||||
ServerName blog.example.com
|
||||
Redirect / https://blog.example.com/
|
||||
</VirtualHost>
|
||||
|
||||
<VirtualHost *:443>
|
||||
ServerAdmin admin@example.com
|
||||
ServerName blog.example.com
|
||||
|
||||
Header always set Referrer-Policy "strict-origin-when-cross-origin"
|
||||
Header always set Strict-Transport-Security "max-age=31536000"
|
||||
SSLEngine on
|
||||
|
||||
# for cipher conf: https://cipherli.st/
|
||||
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
|
||||
SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
|
||||
SSLHonorCipherOrder On
|
||||
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
|
||||
Header always set X-Frame-Options DENY
|
||||
Header always set X-Content-Type-Options nosniff
|
||||
SSLCompression off
|
||||
SSLUseStapling on
|
||||
SSLStaplingCache "shmcb:logs/stapling-cache(150000)"
|
||||
|
||||
# Requires Apache >= 2.4.11
|
||||
SSLSessionTickets Off
|
||||
|
||||
SSLCertificateFile /etc/letsencrypt/live/blog.example.com/cert.pem
|
||||
SSLCertificateKeyFile /etc/letsencrypt/live/blog.example.com/privkey.pem
|
||||
SSLCertificateChainFile /etc/letsencrypt/live/blog.example.com/chain.pem
|
||||
|
||||
ProxyPreserveHost On
|
||||
RequestHeader set X-Forwarded-Proto "https"
|
||||
|
||||
ProxyPass / http://127.0.0.1:7878/
|
||||
ProxyPassReverse / http://127.0.0.1:7878/
|
||||
</VirtualHost>
|
||||
```
|
||||
|
||||
## Systemd integration
|
||||
|
||||
If you want to manage your Plume instance with systemd, you can use the following unit file (to be saved in `/etc/systemd/system/plume.service`):
|
||||
|
||||
```toml
|
||||
[Unit]
|
||||
Description=plume
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=plume
|
||||
WorkingDirectory=/home/plume/Plume
|
||||
ExecStart=/home/plume/.cargo/bin/cargo run
|
||||
TimeoutSec=30
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
## SysVinit integration
|
||||
|
||||
This script can also be useful if you are using SysVinit.
|
||||
|
||||
```bash
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides:
|
||||
# Required-Start: $remote_fs $syslog
|
||||
# Required-Stop: $remote_fs $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Start daemon at boot time
|
||||
# Description: Federated blogging
|
||||
# Based on https://raw.githubusercontent.com/fhd/init-script-template/master/template
|
||||
### END INIT INFO
|
||||
|
||||
dir="/home/plume/Plume"
|
||||
cmd="/home/plume/.cargo/bin/cargo run"
|
||||
user="plume"
|
||||
|
||||
name=`basename $0`
|
||||
pid_file="/var/run/$name.pid"
|
||||
stdout_log="/home/plume/Plume/plume.log"
|
||||
stderr_log="/home/plume/Plume/plume.err"
|
||||
|
||||
get_pid() {
|
||||
cat "$pid_file"
|
||||
}
|
||||
|
||||
is_running() {
|
||||
[ -f "$pid_file" ] && ps -p `get_pid` > /dev/null 2>&1
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
if is_running; then
|
||||
echo "Already started"
|
||||
else
|
||||
echo "Starting $name"
|
||||
cd "$dir"
|
||||
if [ -z "$user" ]; then
|
||||
sudo $cmd >> "$stdout_log" 2>> "$stderr_log" &
|
||||
else
|
||||
sudo -u "$user" $cmd >> "$stdout_log" 2>> "$stderr_log" &
|
||||
fi
|
||||
echo $! > "$pid_file"
|
||||
if ! is_running; then
|
||||
echo "Unable to start, see $stdout_log and $stderr_log"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
stop)
|
||||
if is_running; then
|
||||
echo -n "Stopping $name.."
|
||||
kill `get_pid`
|
||||
for i in 1 2 3 4 5 6 7 8 9 10
|
||||
# for i in `seq 10`
|
||||
do
|
||||
if ! is_running; then
|
||||
break
|
||||
fi
|
||||
|
||||
echo -n "."
|
||||
sleep 1
|
||||
done
|
||||
echo
|
||||
|
||||
if is_running; then
|
||||
echo "Not stopped; may still be shutting down or shutdown may have failed"
|
||||
exit 1
|
||||
else
|
||||
echo "Stopped"
|
||||
if [ -f "$pid_file" ]; then
|
||||
rm "$pid_file"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "Not running"
|
||||
fi
|
||||
;;
|
||||
restart)
|
||||
$0 stop
|
||||
if is_running; then
|
||||
echo "Unable to stop, will not attempt to start"
|
||||
exit 1
|
||||
fi
|
||||
$0 start
|
||||
;;
|
||||
status)
|
||||
if is_running; then
|
||||
echo "Running"
|
||||
else
|
||||
echo "Stopped"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|status}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
```
|
||||
|
||||
## Caveats:
|
||||
|
||||
- Pgbouncer is not yet supported (named transactions are used).
|
||||
- Rust nightly is a moving target, dependancies can break and sometimes you need to check a few versions to find the one working (run `rustup override set nightly-2018-05-15` or `rustup override set nightly-2018-05-31` in the Plume directory if you have issues during the compilation)
|
||||
- Rust nightly 2018-06-28 is known to be failing to compile diesel 1.3.2
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
Most of this documentation have been written by *gled-rs*. The systemd unit file, Nginx and Apache configurations have been written by *nonbinaryanargeek*. Some parts (especially the instructions to install native dependencies) are from the [Aardwolf project](https://github.com/Aardwolf-Social/aardwolf).
|
6
docs/README.md
Normal file
6
docs/README.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Plume documentation
|
||||
|
||||
- [Installing Plume (for development or production)](INSTALL.md)
|
||||
- [Updating your instance](UPDATE.md)
|
||||
- [Development Guide](DEVELOPMENT.md)
|
||||
- [Making Plume available in your language](INTERNATIONALIZATION.md)
|
15
docs/UPDATE.md
Normal file
15
docs/UPDATE.md
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Updating your instance
|
||||
|
||||
To update your instance, run these commands with `plume` user if you created it, or with your default user, in the Plume directory.
|
||||
|
||||
```
|
||||
git pull origin master
|
||||
|
||||
# If you are not using systemd
|
||||
cargo run
|
||||
|
||||
# If you are using systemd
|
||||
service plume restart
|
||||
```
|
||||
|
||||
That's it!
|
1
docs/_config.yml
Normal file
1
docs/_config.yml
Normal file
|
@ -0,0 +1 @@
|
|||
theme: jekyll-theme-cayman
|
2
migrations/2018-09-02-111458_create_medias/down.sql
Normal file
2
migrations/2018-09-02-111458_create_medias/down.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
-- This file should undo anything in `up.sql`
|
||||
DROP TABLE medias;
|
10
migrations/2018-09-02-111458_create_medias/up.sql
Normal file
10
migrations/2018-09-02-111458_create_medias/up.sql
Normal file
|
@ -0,0 +1,10 @@
|
|||
-- Your SQL goes here
|
||||
CREATE TABLE medias (
|
||||
id SERIAL PRIMARY KEY,
|
||||
file_path TEXT NOT NULL DEFAULT '',
|
||||
alt_text TEXT NOT NULL DEFAULT '',
|
||||
is_remote BOOLEAN NOT NULL DEFAULT 'f',
|
||||
remote_url TEXT,
|
||||
sensitive BOOLEAN NOT NULL DEFAULT 'f',
|
||||
content_warning TEXT
|
||||
)
|
2
migrations/2018-09-02-123623_medias_owner_id/down.sql
Normal file
2
migrations/2018-09-02-123623_medias_owner_id/down.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
-- This file should undo anything in `up.sql`
|
||||
ALTER TABLE medias DROP COLUMN owner_id;
|
2
migrations/2018-09-02-123623_medias_owner_id/up.sql
Normal file
2
migrations/2018-09-02-123623_medias_owner_id/up.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
-- Your SQL goes here
|
||||
ALTER TABLE medias ADD COLUMN owner_id INTEGER REFERENCES users(id) ON DELETE CASCADE NOT NULL;
|
|
@ -29,9 +29,10 @@ pub trait Notify<C> {
|
|||
fn notify(&self, conn: &C);
|
||||
}
|
||||
|
||||
pub trait Deletable<C> {
|
||||
/// true if success
|
||||
fn delete_activity(conn: &C, id: Id) -> bool;
|
||||
pub trait Deletable<C, A> {
|
||||
fn delete(&self, conn: &C) -> A;
|
||||
fn delete_id(id: String, conn: &C);
|
||||
|
||||
}
|
||||
|
||||
pub trait WithInbox {
|
||||
|
|
|
@ -105,7 +105,7 @@ impl FromActivity<Note, PgConnection> for Comment {
|
|||
sensitive: false // "sensitive" is not a standard property, we need to think about how to support it with the activitypub crate
|
||||
});
|
||||
|
||||
// save mentions
|
||||
// save mentionsd
|
||||
if let Some(serde_json::Value::Array(tags)) = note.object_props.tag.clone() {
|
||||
for tag in tags.into_iter() {
|
||||
serde_json::from_value::<link::Mention>(tag)
|
||||
|
|
|
@ -72,6 +72,14 @@ impl Instance {
|
|||
.len() > 0
|
||||
}
|
||||
|
||||
pub fn main_admin(&self, conn: &PgConnection) -> User {
|
||||
users::table.filter(users::instance_id.eq(self.id))
|
||||
.filter(users::is_admin.eq(true))
|
||||
.limit(1)
|
||||
.get_result::<User>(conn)
|
||||
.expect("Couldn't load admins")
|
||||
}
|
||||
|
||||
pub fn compute_box(&self, prefix: &'static str, name: String, box_name: &'static str) -> String {
|
||||
ap_url(format!(
|
||||
"{instance}/{prefix}/{name}/{box_name}",
|
||||
|
@ -96,4 +104,8 @@ impl Instance {
|
|||
)).get_result::<Instance>(conn)
|
||||
.expect("Couldn't update instance")
|
||||
}
|
||||
|
||||
pub fn count(conn: &PgConnection) -> i64 {
|
||||
instances::table.count().get_result(conn).expect("Couldn't count instances")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ fn get_next_id(conn: &PgConnection, seq: &str) -> i32 {
|
|||
// We cant' use currval because it may fail if nextval have never been called before
|
||||
let next = select(nextval(seq)).get_result::<i64>(conn).expect("Next ID fail");
|
||||
if next > 1 {
|
||||
select(setval(seq, next - 1)).get_result::<i64>(conn).expect("Reset ID fail");
|
||||
select(setval(seq, next - 1)).get_result::<i64>(conn).expect("Reset ID fail");
|
||||
}
|
||||
next as i32
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ fn get_next_id(conn: &PgConnection, seq: &str) -> i32 {
|
|||
lazy_static! {
|
||||
pub static ref BASE_URL: String = env::var("BASE_URL")
|
||||
.unwrap_or(format!("127.0.0.1:{}", env::var("ROCKET_PORT").unwrap_or(String::from("8000"))));
|
||||
|
||||
|
||||
pub static ref DB_URL: String = env::var("DB_URL")
|
||||
.unwrap_or(format!("postgres://plume:plume@localhost/{}", env::var("DB_NAME").unwrap_or(String::from("plume"))));
|
||||
|
||||
|
@ -111,6 +111,7 @@ pub mod db_conn;
|
|||
pub mod follows;
|
||||
pub mod instance;
|
||||
pub mod likes;
|
||||
pub mod medias;
|
||||
pub mod mentions;
|
||||
pub mod notifications;
|
||||
pub mod post_authors;
|
||||
|
|
|
@ -48,19 +48,6 @@ impl Like {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn delete(&self, conn: &PgConnection) -> activity::Undo {
|
||||
diesel::delete(self).execute(conn).unwrap();
|
||||
|
||||
let mut act = activity::Undo::default();
|
||||
act.undo_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).expect("Like::delete: actor error");
|
||||
act.undo_props.set_object_object(self.into_activity(conn)).expect("Like::delete: object error");
|
||||
act.object_props.set_id_string(format!("{}#delete", self.ap_url)).expect("Like::delete: id error");
|
||||
act.object_props.set_to_link(Id::new(PUBLIC_VISIBILTY.to_string())).expect("Like::delete: to error");
|
||||
act.object_props.set_cc_link_vec::<Id>(vec![]).expect("Like::delete: cc error");
|
||||
|
||||
act
|
||||
}
|
||||
|
||||
pub fn into_activity(&self, conn: &PgConnection) -> activity::Like {
|
||||
let mut act = activity::Like::default();
|
||||
act.like_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).expect("Like::into_activity: actor error");
|
||||
|
@ -100,13 +87,23 @@ impl Notify<PgConnection> for Like {
|
|||
}
|
||||
}
|
||||
|
||||
impl Deletable<PgConnection> for Like {
|
||||
fn delete_activity(conn: &PgConnection, id: Id) -> bool {
|
||||
impl Deletable<PgConnection, activity::Undo> for Like {
|
||||
fn delete(&self, conn: &PgConnection) -> activity::Undo {
|
||||
diesel::delete(self).execute(conn).unwrap();
|
||||
|
||||
let mut act = activity::Undo::default();
|
||||
act.undo_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).expect("Like::delete: actor error");
|
||||
act.undo_props.set_object_object(self.into_activity(conn)).expect("Like::delete: object error");
|
||||
act.object_props.set_id_string(format!("{}#delete", self.ap_url)).expect("Like::delete: id error");
|
||||
act.object_props.set_to_link(Id::new(PUBLIC_VISIBILTY.to_string())).expect("Like::delete: to error");
|
||||
act.object_props.set_cc_link_vec::<Id>(vec![]).expect("Like::delete: cc error");
|
||||
|
||||
act
|
||||
}
|
||||
|
||||
fn delete_id(id: String, conn: &PgConnection) {
|
||||
if let Some(like) = Like::find_by_ap_url(conn, id.into()) {
|
||||
like.delete(conn);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
68
plume-models/src/medias.rs
Normal file
68
plume-models/src/medias.rs
Normal file
|
@ -0,0 +1,68 @@
|
|||
use diesel::{self, PgConnection, QueryDsl, ExpressionMethods, RunQueryDsl};
|
||||
use serde_json;
|
||||
use std::fs;
|
||||
|
||||
use ap_url;
|
||||
use instance::Instance;
|
||||
use schema::medias;
|
||||
|
||||
#[derive(Identifiable, Queryable, Serialize)]
|
||||
pub struct Media {
|
||||
pub id: i32,
|
||||
pub file_path: String,
|
||||
pub alt_text: String,
|
||||
pub is_remote: bool,
|
||||
pub remote_url: Option<String>,
|
||||
pub sensitive: bool,
|
||||
pub content_warning: Option<String>,
|
||||
pub owner_id: i32
|
||||
}
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[table_name = "medias"]
|
||||
pub struct NewMedia {
|
||||
pub file_path: String,
|
||||
pub alt_text: String,
|
||||
pub is_remote: bool,
|
||||
pub remote_url: Option<String>,
|
||||
pub sensitive: bool,
|
||||
pub content_warning: Option<String>,
|
||||
pub owner_id: i32
|
||||
}
|
||||
|
||||
impl Media {
|
||||
insert!(medias, NewMedia);
|
||||
get!(medias);
|
||||
list_by!(medias, for_user, owner_id as i32);
|
||||
|
||||
pub fn to_json(&self, conn: &PgConnection) -> serde_json::Value {
|
||||
let mut json = serde_json::to_value(self).unwrap();
|
||||
let (preview, html) = match self.file_path.rsplitn(2, '.').next().unwrap() {
|
||||
"png" | "jpg" | "jpeg" | "gif" => (
|
||||
format!("<img src=\"{}\" alt=\"{}\" title=\"{}\" class=\"preview\">", self.url(conn), self.alt_text, self.alt_text),
|
||||
format!("<img src=\"{}\" alt=\"{}\" title=\"{}\">", self.url(conn), self.alt_text, self.alt_text)
|
||||
),
|
||||
"mp3" | "wav" | "flac" => (
|
||||
format!("<audio src=\"{}\" title=\"{}\" class=\"preview\"></audio>", self.url(conn), self.alt_text),
|
||||
format!("<audio src=\"{}\" title=\"{}\"></audio>", self.url(conn), self.alt_text)
|
||||
),
|
||||
"mp4" | "avi" | "webm" | "mov" => (
|
||||
format!("<video src=\"{}\" title=\"{}\" class=\"preview\"></video>", self.url(conn), self.alt_text),
|
||||
format!("<video src=\"{}\" title=\"{}\"></video>", self.url(conn), self.alt_text)
|
||||
),
|
||||
_ => (String::new(), String::new())
|
||||
};
|
||||
json["html_preview"] = json!(preview);
|
||||
json["html"] = json!(html);
|
||||
json
|
||||
}
|
||||
|
||||
pub fn url(&self, conn: &PgConnection) -> String {
|
||||
ap_url(format!("{}/static/{}", Instance::get_local(conn).unwrap().public_domain, self.file_path))
|
||||
}
|
||||
|
||||
pub fn delete(&self, conn: &PgConnection) {
|
||||
fs::remove_file(self.file_path.as_str()).expect("Couldn't delete media from disk");
|
||||
diesel::delete(self).execute(conn).expect("Couldn't remove media from DB");
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
use activitypub::{
|
||||
activity::Create,
|
||||
activity::{Create, Delete},
|
||||
link,
|
||||
object::Article
|
||||
object::{Article, Tombstone}
|
||||
};
|
||||
use chrono::{NaiveDateTime, TimeZone, Utc};
|
||||
use diesel::{self, PgConnection, RunQueryDsl, QueryDsl, ExpressionMethods, BelongingToDsl, dsl::any};
|
||||
|
@ -10,7 +10,7 @@ use serde_json;
|
|||
|
||||
use plume_common::activity_pub::{
|
||||
PUBLIC_VISIBILTY, Id, IntoId,
|
||||
inbox::FromActivity
|
||||
inbox::{Deletable, FromActivity}
|
||||
};
|
||||
use {BASE_URL, ap_url};
|
||||
use blogs::Blog;
|
||||
|
@ -273,6 +273,27 @@ impl FromActivity<Article, PgConnection> for Post {
|
|||
}
|
||||
}
|
||||
|
||||
impl Deletable<PgConnection, Delete> for Post {
|
||||
fn delete(&self, conn: &PgConnection) -> Delete {
|
||||
let mut act = Delete::default();
|
||||
act.delete_props.set_actor_link(self.get_authors(conn)[0].clone().into_id()).expect("Post::delete: actor error");
|
||||
|
||||
let mut tombstone = Tombstone::default();
|
||||
tombstone.object_props.set_id_string(self.ap_url.clone()).expect("Post::delete: object.id error");
|
||||
act.delete_props.set_object_object(tombstone).expect("Post::delete: object error");
|
||||
|
||||
act.object_props.set_id_string(format!("{}#delete", self.ap_url)).expect("Post::delete: id error");
|
||||
act.object_props.set_to_link_vec(vec![Id::new(PUBLIC_VISIBILTY)]).expect("Post::delete: to error");
|
||||
|
||||
diesel::delete(self).execute(conn).expect("Post::delete: DB error");
|
||||
act
|
||||
}
|
||||
|
||||
fn delete_id(id: String, conn: &PgConnection) {
|
||||
Post::find_by_ap_url(conn, id).map(|p| p.delete(conn));
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoId for Post {
|
||||
fn into_id(self) -> Id {
|
||||
Id::new(self.ap_url.clone())
|
||||
|
|
|
@ -59,19 +59,6 @@ impl Reshare {
|
|||
User::get(conn, self.user_id)
|
||||
}
|
||||
|
||||
pub fn delete(&self, conn: &PgConnection) -> Undo {
|
||||
diesel::delete(self).execute(conn).unwrap();
|
||||
|
||||
let mut act = Undo::default();
|
||||
act.undo_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap();
|
||||
act.undo_props.set_object_object(self.into_activity(conn)).unwrap();
|
||||
act.object_props.set_id_string(format!("{}#delete", self.ap_url)).expect("Reshare::delete: id error");
|
||||
act.object_props.set_to_link(Id::new(PUBLIC_VISIBILTY.to_string())).expect("Reshare::delete: to error");
|
||||
act.object_props.set_cc_link_vec::<Id>(vec![]).expect("Reshare::delete: cc error");
|
||||
|
||||
act
|
||||
}
|
||||
|
||||
pub fn into_activity(&self, conn: &PgConnection) -> Announce {
|
||||
let mut act = Announce::default();
|
||||
act.announce_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap();
|
||||
|
@ -86,8 +73,8 @@ impl Reshare {
|
|||
|
||||
impl FromActivity<Announce, PgConnection> for Reshare {
|
||||
fn from_activity(conn: &PgConnection, announce: Announce, _actor: Id) -> Reshare {
|
||||
let user = User::from_url(conn, announce.announce_props.actor.as_str().unwrap().to_string());
|
||||
let post = Post::find_by_ap_url(conn, announce.announce_props.object.as_str().unwrap().to_string());
|
||||
let user = User::from_url(conn, announce.announce_props.actor_link::<Id>().expect("Reshare::from_activity: actor error").into());
|
||||
let post = Post::find_by_ap_url(conn, announce.announce_props.object_link::<Id>().expect("Reshare::from_activity: object error").into());
|
||||
let reshare = Reshare::insert(conn, NewReshare {
|
||||
post_id: post.unwrap().id,
|
||||
user_id: user.unwrap().id,
|
||||
|
@ -111,13 +98,23 @@ impl Notify<PgConnection> for Reshare {
|
|||
}
|
||||
}
|
||||
|
||||
impl Deletable<PgConnection> for Reshare {
|
||||
fn delete_activity(conn: &PgConnection, id: Id) -> bool {
|
||||
if let Some(reshare) = Reshare::find_by_ap_url(conn, id.into()) {
|
||||
impl Deletable<PgConnection, Undo> for Reshare {
|
||||
fn delete(&self, conn: &PgConnection) -> Undo {
|
||||
diesel::delete(self).execute(conn).unwrap();
|
||||
|
||||
let mut act = Undo::default();
|
||||
act.undo_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap();
|
||||
act.undo_props.set_object_object(self.into_activity(conn)).unwrap();
|
||||
act.object_props.set_id_string(format!("{}#delete", self.ap_url)).expect("Reshare::delete: id error");
|
||||
act.object_props.set_to_link(Id::new(PUBLIC_VISIBILTY.to_string())).expect("Reshare::delete: to error");
|
||||
act.object_props.set_cc_link_vec::<Id>(vec![]).expect("Reshare::delete: cc error");
|
||||
|
||||
act
|
||||
}
|
||||
|
||||
fn delete_id(id: String, conn: &PgConnection) {
|
||||
if let Some(reshare) = Reshare::find_by_ap_url(conn, id) {
|
||||
reshare.delete(conn);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,6 +72,19 @@ table! {
|
|||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
medias (id) {
|
||||
id -> Int4,
|
||||
file_path -> Text,
|
||||
alt_text -> Text,
|
||||
is_remote -> Bool,
|
||||
remote_url -> Nullable<Text>,
|
||||
sensitive -> Bool,
|
||||
content_warning -> Nullable<Text>,
|
||||
owner_id -> Int4,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
mentions (id) {
|
||||
id -> Int4,
|
||||
|
@ -152,6 +165,7 @@ joinable!(comments -> posts (post_id));
|
|||
joinable!(comments -> users (author_id));
|
||||
joinable!(likes -> posts (post_id));
|
||||
joinable!(likes -> users (user_id));
|
||||
joinable!(medias -> users (owner_id));
|
||||
joinable!(mentions -> comments (comment_id));
|
||||
joinable!(mentions -> posts (post_id));
|
||||
joinable!(mentions -> users (mentioned_id));
|
||||
|
@ -170,6 +184,7 @@ allow_tables_to_appear_in_same_query!(
|
|||
follows,
|
||||
instances,
|
||||
likes,
|
||||
medias,
|
||||
mentions,
|
||||
notifications,
|
||||
post_authors,
|
||||
|
|
24
po/de.po
24
po/de.po
|
@ -98,7 +98,7 @@ msgid "I don't want to boost this anymore"
|
|||
msgstr "Nicht mehr boosten"
|
||||
|
||||
msgid "Boost"
|
||||
msgstr "Boost"
|
||||
msgstr "Boosten"
|
||||
|
||||
msgid "Comments"
|
||||
msgstr "Kommentare"
|
||||
|
@ -437,22 +437,20 @@ msgstr "Artikel geschrieben haben"
|
|||
msgid "Read the detailed rules"
|
||||
msgstr "Lies die detailierten Regeln"
|
||||
|
||||
#~ msgid "One reshare"
|
||||
#~ msgid_plural "{{ count }} reshares"
|
||||
#~ msgstr[0] "Ein Reshare"
|
||||
#~ msgstr[1] "{{ count }} Reshares"
|
||||
msgid "Delete this article"
|
||||
msgstr "Artikel löschen"
|
||||
|
||||
#~ msgid "Reshare"
|
||||
#~ msgstr "Resharen"
|
||||
msgid "And connected to"
|
||||
msgstr "Verbunden mit"
|
||||
|
||||
#~ msgid "You need to be logged in order to reshare a post"
|
||||
#~ msgstr "Du musst eingeloggt sein, um einen Beitrag zu resharen"
|
||||
msgid "other instances"
|
||||
msgstr "anderen Instanzen"
|
||||
|
||||
#~ msgid "{{ data }} reshared your article"
|
||||
#~ msgstr "{{ data }} hat deinen Artikel reshared"
|
||||
msgid "Administred by"
|
||||
msgstr "Administriert von"
|
||||
|
||||
#~ msgid "{{ user }} reshared your article."
|
||||
#~ msgstr "{{ user }} hat deinen Artikel reshared."
|
||||
msgid "Runs Plume {{ version }}"
|
||||
msgstr "Verwendet Plume {{ version }}"
|
||||
|
||||
#~ msgid "Your password should be at least 8 characters long"
|
||||
#~ msgstr "Das Passwort sollte mindestens 8 Zeichen lang sein"
|
||||
|
|
15
po/en.po
15
po/en.po
|
@ -430,3 +430,18 @@ msgstr ""
|
|||
|
||||
msgid "Read the detailed rules"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete this article"
|
||||
msgstr ""
|
||||
|
||||
msgid "And connected to"
|
||||
msgstr ""
|
||||
|
||||
msgid "other instances"
|
||||
msgstr ""
|
||||
|
||||
msgid "Administred by"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runs Plume {{ version }}"
|
||||
msgstr ""
|
||||
|
|
83
po/fr.po
83
po/fr.po
|
@ -43,18 +43,18 @@ msgid "Submit comment"
|
|||
msgstr "Envoyer le commentaire"
|
||||
|
||||
msgid "Something broke on our side."
|
||||
msgstr "Nous avons cassé quelque chose"
|
||||
msgstr "Nous avons cassé quelque chose."
|
||||
|
||||
msgid "Sorry about that. If you think this is a bug, please report it."
|
||||
msgstr ""
|
||||
"Nous sommes désolé⋅e⋅s. Si vous pensez que c'est un bogue, merci de le "
|
||||
"rapporter."
|
||||
"signaler."
|
||||
|
||||
msgid "Configuration"
|
||||
msgstr "Configuration"
|
||||
|
||||
msgid "Configure your instance"
|
||||
msgstr "Configurez votre instance"
|
||||
msgstr "Configurer votre instance"
|
||||
|
||||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
|
@ -92,9 +92,8 @@ msgid_plural "{{ count }} Boosts"
|
|||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "I don't want to boost this anymore"
|
||||
msgstr "Je ne veux plus repartager"
|
||||
msgstr "Je ne veux plus repartager ceci"
|
||||
|
||||
msgid "Boost"
|
||||
msgstr ""
|
||||
|
@ -106,7 +105,7 @@ msgid "Respond"
|
|||
msgstr "Répondre"
|
||||
|
||||
msgid "Comment"
|
||||
msgstr "Commentez"
|
||||
msgstr "Commenter"
|
||||
|
||||
msgid "New post"
|
||||
msgstr "Nouvel article"
|
||||
|
@ -141,7 +140,7 @@ msgstr ""
|
|||
"un."
|
||||
|
||||
msgid "Start a new blog"
|
||||
msgstr "Commencez un nouveau blog"
|
||||
msgstr "Commencer un nouveau blog"
|
||||
|
||||
msgid "Admin"
|
||||
msgstr "Administrateur"
|
||||
|
@ -150,7 +149,7 @@ msgid "It is you"
|
|||
msgstr "C'est vous"
|
||||
|
||||
msgid "Edit your profile"
|
||||
msgstr "Éditez votre profil"
|
||||
msgstr "Éditer votre profil"
|
||||
|
||||
msgid "Open on {{ instance_url }}"
|
||||
msgstr "Ouvrir sur {{ instance_url }}"
|
||||
|
@ -259,7 +258,8 @@ msgid "You need to be logged in order to edit your profile"
|
|||
msgstr "Vous devez vous connecter pour modifier votre profil"
|
||||
|
||||
msgid "By {{ link_1 }}{{ link_2 }}{{ link_3 }}{{ name | escape }}{{ link_4 }}"
|
||||
msgstr "De {{ link_1 }}{{ link_2 }}{{ link_3 }}{{ name | escape }}{{ link_4 }}"
|
||||
msgstr ""
|
||||
"Par {{ link_1 }}{{ link_2 }}{{ link_3 }}{{ name | escape }}{{ link_4 }}"
|
||||
|
||||
#, fuzzy
|
||||
msgid "{{ data }} boosted your article"
|
||||
|
@ -278,13 +278,13 @@ msgid "We couldn't find this page."
|
|||
msgstr "Page introuvable."
|
||||
|
||||
msgid "The link that led you here may be broken."
|
||||
msgstr "Le lien que vous avez suivi est cassé."
|
||||
msgstr "Vous avez probablement suivi un lien cassé."
|
||||
|
||||
msgid "You are not authorized."
|
||||
msgstr "Vous n'avez pas les droits."
|
||||
|
||||
msgid "You are not author in this blog."
|
||||
msgstr "Vous n'êtes pas auteur dans ce blog."
|
||||
msgstr "Vous n'êtes pas auteur⋅ice dans ce blog."
|
||||
|
||||
msgid "{{ data }} mentioned you."
|
||||
msgstr "{{ data }} vous a mentionné."
|
||||
|
@ -302,7 +302,7 @@ msgid "A blog with the same name already exists."
|
|||
msgstr "Un blog avec le même nom existe déjà."
|
||||
|
||||
msgid "Your comment can't be empty"
|
||||
msgstr "Votre commentaire ne peux pas être vide"
|
||||
msgstr "Votre commentaire ne peut pas être vide."
|
||||
|
||||
msgid "A post with the same title already exists."
|
||||
msgstr "Un article avec le même titre existe déjà."
|
||||
|
@ -314,7 +314,7 @@ msgstr ""
|
|||
|
||||
#, fuzzy
|
||||
msgid "Your password can't be empty"
|
||||
msgstr "Votre commentaire ne peux pas être vide"
|
||||
msgstr "Votre mot de passe ne peut pas être vide."
|
||||
|
||||
msgid "Passwords are not matching"
|
||||
msgstr "Les mots de passe ne correspondent pas."
|
||||
|
@ -323,15 +323,15 @@ msgid "Username can't be empty"
|
|||
msgstr "Le nom d'utilisateur ne peut pas être vide."
|
||||
|
||||
msgid "Invalid email"
|
||||
msgstr "Adresse mail invalide"
|
||||
msgstr "Adresse mail invalide."
|
||||
|
||||
msgid "Password should be at least 8 characters long"
|
||||
msgstr "Le mot de passe doit faire au moins 8 caractères."
|
||||
|
||||
msgid "One author in this blog: "
|
||||
msgid_plural "{{ count }} authors in this blog: "
|
||||
msgstr[0] "{{ count }} aut⋅eur⋅rice dans ce blog : "
|
||||
msgstr[1] "{{ count }} aut⋅eur⋅rice⋅s dans ce blog : "
|
||||
msgstr[0] "{{ count }} auteur⋅ice dans ce blog : "
|
||||
msgstr[1] "{{ count }} auteur⋅ice⋅s dans ce blog : "
|
||||
|
||||
msgid "Login or use your Fediverse account to interact with this article"
|
||||
msgstr ""
|
||||
|
@ -344,14 +344,14 @@ msgstr "Optionnel"
|
|||
#, fuzzy
|
||||
msgid "One article in this blog"
|
||||
msgid_plural "{{ count }} articles in this blog"
|
||||
msgstr[0] "{{ count }} aut⋅eur⋅rice dans ce blog : "
|
||||
msgstr[1] "{{ count }} aut⋅eur⋅rice⋅s dans ce blog : "
|
||||
msgstr[0] "{{ count }} article dans ce blog"
|
||||
msgstr[1] "{{ count }} articles dans ce blog"
|
||||
|
||||
msgid "Previous page"
|
||||
msgstr ""
|
||||
msgstr "Page précédente"
|
||||
|
||||
msgid "Next page"
|
||||
msgstr ""
|
||||
msgstr "Page suivante"
|
||||
|
||||
msgid "{{ user }} mentioned you."
|
||||
msgstr "{{ user }} vous a mentionné."
|
||||
|
@ -365,9 +365,8 @@ msgstr "{{ user }} vous suit"
|
|||
msgid "{{ user }} liked your article."
|
||||
msgstr "{{ user }} a aimé votre article"
|
||||
|
||||
#, fuzzy
|
||||
msgid "{{ user }} boosted your article."
|
||||
msgstr "{{ user }} a commenté votre article"
|
||||
msgstr ""
|
||||
|
||||
msgid "Source code"
|
||||
msgstr "Code source"
|
||||
|
@ -400,7 +399,7 @@ msgid "Save settings"
|
|||
msgstr "Enregistrer les paramètres"
|
||||
|
||||
msgid "No comments yet. Be the first to react!"
|
||||
msgstr "Pas encore de commentaires. Soyez læ premi⋅er⋅ère à réagir !"
|
||||
msgstr "Pas encore de commentaires. Soyez læ premier⋅ère à réagir !"
|
||||
|
||||
msgid "About this instance"
|
||||
msgstr "À propos de cette instance"
|
||||
|
@ -412,14 +411,15 @@ msgid "Plume is a decentralized blogging engine."
|
|||
msgstr "Plume est un moteur de blog décentralisé."
|
||||
|
||||
msgid "Authors can manage various blogs from an unique website."
|
||||
msgstr "Les auteurs peuvent gérer différents blogs au sein d'un même site."
|
||||
msgstr ""
|
||||
"Les auteur⋅ice⋅s peuvent gérer différents blogs au sein d'un même site."
|
||||
|
||||
msgid ""
|
||||
"Articles are also visible on other Plume websites, and you can interact with "
|
||||
"them directly from other platforms like Mastodon."
|
||||
msgstr ""
|
||||
"Les articles sont également visibles sur d'autres sites Plume et vous pouvez "
|
||||
"interagir avec eux directement depuis d'autres plateformes telles que "
|
||||
"Les articles sont également visibles sur d'autres sites Plume, et vous "
|
||||
"pouvez interagir avec directement depuis d'autres plateformes telles que "
|
||||
"Mastodon."
|
||||
|
||||
msgid "Create your account"
|
||||
|
@ -432,33 +432,34 @@ msgid "Home to"
|
|||
msgstr "Accueille"
|
||||
|
||||
msgid "people"
|
||||
msgstr "personnnes"
|
||||
msgstr "personnes"
|
||||
|
||||
msgid "Who wrote"
|
||||
msgstr "Qui ont écrit"
|
||||
msgstr "Ayant écrit"
|
||||
|
||||
msgid "articles"
|
||||
msgstr "articles"
|
||||
|
||||
msgid "Read the detailed rules"
|
||||
msgstr "Lisez le détail des règles"
|
||||
msgstr "Lire les règles détaillées"
|
||||
|
||||
#~ msgid "One reshare"
|
||||
#~ msgid_plural "{{ count }} reshares"
|
||||
#~ msgstr[0] "{{ count }} repartage"
|
||||
#~ msgstr[1] "{{ count }} repartages"
|
||||
#, fuzzy
|
||||
msgid "Delete this article"
|
||||
msgstr "Derniers articles"
|
||||
|
||||
#~ msgid "Reshare"
|
||||
#~ msgstr "Repartagez"
|
||||
msgid "And connected to"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "You need to be logged in order to reshare a post"
|
||||
#~ msgstr "Vous devez vous connecter pour repartager un article"
|
||||
#, fuzzy
|
||||
msgid "other instances"
|
||||
msgstr "À propos de cette instance"
|
||||
|
||||
#~ msgid "{{ data }} reshared your article"
|
||||
#~ msgstr "{{ data }} a repartagé votre article"
|
||||
#, fuzzy
|
||||
msgid "Administred by"
|
||||
msgstr "Administration"
|
||||
|
||||
#~ msgid "{{ user }} reshared your article."
|
||||
#~ msgstr "{{ user }} a repartagé votre article"
|
||||
msgid "Runs Plume {{ version }}"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Your password should be at least 8 characters long"
|
||||
#~ msgstr "Votre mot de passe doit faire au moins 8 caractères."
|
||||
|
|
276
po/gl.po
276
po/gl.po
|
@ -4,7 +4,7 @@ msgstr ""
|
|||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2018-06-15 16:33-0700\n"
|
||||
"PO-Revision-Date: 2018-06-15 16:33-0700\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Last-Translator: Xosé M. <correo@xmgz.eu>\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: gl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -13,76 +13,77 @@ msgstr ""
|
|||
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
|
||||
|
||||
msgid "Latest articles"
|
||||
msgstr ""
|
||||
msgstr "Últimos artigos"
|
||||
|
||||
msgid "No posts to see here yet."
|
||||
msgstr ""
|
||||
msgstr "Aínda non hai entradas publicadas"
|
||||
|
||||
msgid "New article"
|
||||
msgstr ""
|
||||
msgstr "Novo artigo"
|
||||
|
||||
msgid "New blog"
|
||||
msgstr ""
|
||||
msgstr "Novo blog"
|
||||
|
||||
msgid "Create a blog"
|
||||
msgstr ""
|
||||
msgstr "Crear un blog"
|
||||
|
||||
msgid "Title"
|
||||
msgstr ""
|
||||
msgstr "Título"
|
||||
|
||||
msgid "Create blog"
|
||||
msgstr ""
|
||||
msgstr "Crear blog"
|
||||
|
||||
msgid "Comment \"{{ post }}\""
|
||||
msgstr ""
|
||||
msgstr "Comentar \"{{ post }}\""
|
||||
|
||||
msgid "Content"
|
||||
msgstr ""
|
||||
msgstr "Contido"
|
||||
|
||||
msgid "Submit comment"
|
||||
msgstr ""
|
||||
msgstr "Enviar comentario"
|
||||
|
||||
msgid "Something broke on our side."
|
||||
msgstr ""
|
||||
msgstr "Algo fallou pola nosa parte"
|
||||
|
||||
msgid "Sorry about that. If you think this is a bug, please report it."
|
||||
msgstr ""
|
||||
msgstr "Lamentálmolo. Si cree que é un bug, infórmenos por favor."
|
||||
|
||||
msgid "Configuration"
|
||||
msgstr ""
|
||||
msgstr "Axustes"
|
||||
|
||||
msgid "Configure your instance"
|
||||
msgstr ""
|
||||
msgstr "Configure a súa instancia"
|
||||
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
msgstr "Nome"
|
||||
|
||||
msgid "Let's go!"
|
||||
msgstr ""
|
||||
msgstr "Imos!"
|
||||
|
||||
msgid "Welcome on {{ instance_name | escape }}"
|
||||
msgstr ""
|
||||
msgstr "Ben vida a {{ instance_name | escape }}"
|
||||
|
||||
msgid "Notifications"
|
||||
msgstr ""
|
||||
msgstr "Notificacións"
|
||||
|
||||
msgid ""
|
||||
"Written by {{ link_1 }}{{ url }}{{ link_2 }}{{ name | escape }}{{ link_3 }}"
|
||||
msgstr ""
|
||||
"Escrito por {{ link_1 }}{{ url }}{{ link_2 }}{{ name | escape }}{{ link_3 }}"
|
||||
|
||||
msgid "This article is under the {{ license }} license."
|
||||
msgstr ""
|
||||
msgstr "Este artigo ten licenza {{ license }}"
|
||||
|
||||
msgid "One like"
|
||||
msgid_plural "{{ count }} likes"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[0] "Un gústame"
|
||||
msgstr[1] "{{ count }} gústame"
|
||||
|
||||
msgid "I don't like this anymore"
|
||||
msgstr ""
|
||||
msgstr "Xa non me gusta"
|
||||
|
||||
msgid "Add yours"
|
||||
msgstr ""
|
||||
msgstr "Engada os seus"
|
||||
|
||||
msgid "One Boost"
|
||||
msgid_plural "{{ count }} Boosts"
|
||||
|
@ -96,330 +97,353 @@ msgid "Boost"
|
|||
msgstr ""
|
||||
|
||||
msgid "Comments"
|
||||
msgstr ""
|
||||
msgstr "Comentarios"
|
||||
|
||||
msgid "Respond"
|
||||
msgstr ""
|
||||
msgstr "Respostar"
|
||||
|
||||
msgid "Comment"
|
||||
msgstr ""
|
||||
msgstr "Comentar"
|
||||
|
||||
msgid "New post"
|
||||
msgstr ""
|
||||
msgstr "Nova entrada"
|
||||
|
||||
msgid "Create a post"
|
||||
msgstr ""
|
||||
msgstr "Crear unha entrada"
|
||||
|
||||
msgid "Publish"
|
||||
msgstr ""
|
||||
msgstr "Publicar"
|
||||
|
||||
msgid "Login"
|
||||
msgstr ""
|
||||
msgstr "Conectar"
|
||||
|
||||
msgid "Username or email"
|
||||
msgstr ""
|
||||
msgstr "Usuaria ou correo-e"
|
||||
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
msgstr "Contrasinal"
|
||||
|
||||
msgid "Dashboard"
|
||||
msgstr ""
|
||||
msgstr "Taboleiro"
|
||||
|
||||
msgid "Your Dashboard"
|
||||
msgstr ""
|
||||
msgstr "O seu taboleiro"
|
||||
|
||||
msgid "Your Blogs"
|
||||
msgstr ""
|
||||
msgstr "Os seus Blogs"
|
||||
|
||||
msgid "You don't have any blog yet. Create your own, or ask to join one."
|
||||
msgstr ""
|
||||
msgstr "Aínda non ten blogs. Publique un, ou solicita unirse a un."
|
||||
|
||||
msgid "Start a new blog"
|
||||
msgstr ""
|
||||
msgstr "Iniciar un blog"
|
||||
|
||||
msgid "Admin"
|
||||
msgstr ""
|
||||
msgstr "Admin"
|
||||
|
||||
msgid "It is you"
|
||||
msgstr ""
|
||||
msgstr "É vosted"
|
||||
|
||||
msgid "Edit your profile"
|
||||
msgstr ""
|
||||
msgstr "Edite o seu perfil"
|
||||
|
||||
msgid "Open on {{ instance_url }}"
|
||||
msgstr ""
|
||||
msgstr "Abrir en {{ instance_url }}"
|
||||
|
||||
msgid "Follow"
|
||||
msgstr ""
|
||||
msgstr "Seguir"
|
||||
|
||||
msgid "Unfollow"
|
||||
msgstr ""
|
||||
msgstr "Deixar de seguir"
|
||||
|
||||
msgid "Recently boosted"
|
||||
msgstr ""
|
||||
|
||||
msgid "One follower"
|
||||
msgid_plural "{{ count }} followers"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[0] "Unha seguidora"
|
||||
msgstr[1] "{{ count }} seguidoras"
|
||||
|
||||
msgid "Edit your account"
|
||||
msgstr ""
|
||||
msgstr "Edite a súa conta"
|
||||
|
||||
msgid "Your Profile"
|
||||
msgstr ""
|
||||
msgstr "O seu perfil"
|
||||
|
||||
msgid "Display Name"
|
||||
msgstr ""
|
||||
msgstr "Nome mostrado"
|
||||
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
msgstr "Correo-e"
|
||||
|
||||
msgid "Summary"
|
||||
msgstr ""
|
||||
msgstr "Resumen"
|
||||
|
||||
msgid "Update account"
|
||||
msgstr ""
|
||||
msgstr "Actualizar conta"
|
||||
|
||||
msgid "{{ name | escape }}'s followers"
|
||||
msgstr ""
|
||||
msgstr "Seguidoras de {{ name | escape }}"
|
||||
|
||||
msgid "Followers"
|
||||
msgstr ""
|
||||
msgstr "Seguidoras"
|
||||
|
||||
msgid "New Account"
|
||||
msgstr ""
|
||||
msgstr "Nova conta"
|
||||
|
||||
msgid "Create an account"
|
||||
msgstr ""
|
||||
msgstr "Crear unha conta"
|
||||
|
||||
msgid "Username"
|
||||
msgstr ""
|
||||
msgstr "Nome de usuaria"
|
||||
|
||||
msgid "Password confirmation"
|
||||
msgstr ""
|
||||
msgstr "Confirmación do contrasinal"
|
||||
|
||||
msgid "Create account"
|
||||
msgstr ""
|
||||
msgstr "Crear conta"
|
||||
|
||||
msgid "Plume"
|
||||
msgstr ""
|
||||
msgstr "Plume"
|
||||
|
||||
msgid "Menu"
|
||||
msgstr ""
|
||||
msgstr "Menú"
|
||||
|
||||
msgid "My account"
|
||||
msgstr ""
|
||||
msgstr "A miña conta"
|
||||
|
||||
msgid "Log Out"
|
||||
msgstr ""
|
||||
msgstr "Desconectar"
|
||||
|
||||
msgid "Log In"
|
||||
msgstr ""
|
||||
msgstr "Conectar"
|
||||
|
||||
msgid "Register"
|
||||
msgstr ""
|
||||
msgstr "Rexistrar"
|
||||
|
||||
msgid "You need to be logged in order to create a new blog"
|
||||
msgstr ""
|
||||
msgstr "Debe estar conectada para crear un novo blog"
|
||||
|
||||
msgid "You need to be logged in order to post a comment"
|
||||
msgstr ""
|
||||
msgstr "Debe estar conectada para publicar un comentario"
|
||||
|
||||
msgid "You need to be logged in order to like a post"
|
||||
msgstr ""
|
||||
msgstr "Debe estar conectada para gustar unha entrada"
|
||||
|
||||
msgid "You need to be logged in order to see your notifications"
|
||||
msgstr ""
|
||||
msgstr "Debe estar conectada para ver as súas notificacións"
|
||||
|
||||
msgid "You need to be logged in order to write a new post"
|
||||
msgstr ""
|
||||
msgstr "Debe estar conectada para escribir unha nova entrada"
|
||||
|
||||
msgid "You need to be logged in order to boost a post"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid username or password"
|
||||
msgstr ""
|
||||
msgstr "Usuaria ou Contrasinal incorrectos"
|
||||
|
||||
msgid "You need to be logged in order to access your dashboard"
|
||||
msgstr ""
|
||||
msgstr "Debe estar conectada para acceder ao seu taboleiro"
|
||||
|
||||
msgid "You need to be logged in order to follow someone"
|
||||
msgstr ""
|
||||
msgstr "Debe estar conectada para seguir a alguén"
|
||||
|
||||
msgid "You need to be logged in order to edit your profile"
|
||||
msgstr ""
|
||||
msgstr "Debe estar conectada para editar o seu perfil"
|
||||
|
||||
msgid "By {{ link_1 }}{{ link_2 }}{{ link_3 }}{{ name | escape }}{{ link_4 }}"
|
||||
msgstr ""
|
||||
"Por {{ link_1 }}{{ link_2 }}{{ link_3 }}{{ name | escape }}{{ link_4 }}"
|
||||
|
||||
msgid "{{ data }} boosted your article"
|
||||
msgstr ""
|
||||
|
||||
msgid "{{ data }} started following you"
|
||||
msgstr ""
|
||||
msgstr "{{ data }} comezou a seguila"
|
||||
|
||||
msgid "{{ data }} liked your article"
|
||||
msgstr ""
|
||||
msgstr "{{ data }} gustou do seu artigo"
|
||||
|
||||
msgid "{{ data }} commented your article"
|
||||
msgstr ""
|
||||
msgstr "{{ data }} comentou o seu artigo"
|
||||
|
||||
msgid "We couldn't find this page."
|
||||
msgstr ""
|
||||
msgstr "Non atopamos esta páxina"
|
||||
|
||||
msgid "The link that led you here may be broken."
|
||||
msgstr ""
|
||||
msgstr "A ligazón que a trouxo aquí podería estar quebrado"
|
||||
|
||||
msgid "You are not authorized."
|
||||
msgstr ""
|
||||
msgstr "Non ten permiso."
|
||||
|
||||
msgid "You are not author in this blog."
|
||||
msgstr ""
|
||||
msgstr "Vostede non é autora en este blog."
|
||||
|
||||
msgid "{{ data }} mentioned you."
|
||||
msgstr ""
|
||||
msgstr "{{ data }} mencionouna."
|
||||
|
||||
msgid "Your comment"
|
||||
msgstr ""
|
||||
msgstr "O seu comentario"
|
||||
|
||||
msgid "Unknown error"
|
||||
msgstr ""
|
||||
msgstr "Fallo descoñecido"
|
||||
|
||||
msgid "Invalid name"
|
||||
msgstr ""
|
||||
msgstr "Nome non válido"
|
||||
|
||||
msgid "A blog with the same name already exists."
|
||||
msgstr ""
|
||||
msgstr "Xa existe un blog co mismo nome."
|
||||
|
||||
msgid "Your comment can't be empty"
|
||||
msgstr ""
|
||||
msgstr "O seu comentario non pode estar baldeiro"
|
||||
|
||||
msgid "A post with the same title already exists."
|
||||
msgstr ""
|
||||
msgstr "Xa existe unha entrada co mismo nome."
|
||||
|
||||
msgid "We need an email or a username to identify you"
|
||||
msgstr ""
|
||||
msgstr "Precisamos un correo-e ou un nome de usuaria para identificala"
|
||||
|
||||
msgid "Your password can't be empty"
|
||||
msgstr ""
|
||||
msgstr "O contrasinal non pode estar baldeiro"
|
||||
|
||||
msgid "Passwords are not matching"
|
||||
msgstr ""
|
||||
msgstr "Con coinciden os contrasinais"
|
||||
|
||||
msgid "Username can't be empty"
|
||||
msgstr ""
|
||||
msgstr "O nome de usuaria non pode estar baldeiro"
|
||||
|
||||
msgid "Invalid email"
|
||||
msgstr ""
|
||||
msgstr "Correo-e non válido"
|
||||
|
||||
msgid "Password should be at least 8 characters long"
|
||||
msgstr ""
|
||||
msgstr "O contrasinal debe ter ao menos 8 caracteres"
|
||||
|
||||
msgid "One author in this blog: "
|
||||
msgid_plural "{{ count }} authors in this blog: "
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[0] "Unha autora en este blog: "
|
||||
msgstr[1] "{{ count }} autoras en este blog: "
|
||||
|
||||
msgid "Login or use your Fediverse account to interact with this article"
|
||||
msgstr ""
|
||||
"Conéctese ou utilice a súa conta no fediverso para interactuar con este "
|
||||
"artigo"
|
||||
|
||||
msgid "Optional"
|
||||
msgstr ""
|
||||
msgstr "Opcional"
|
||||
|
||||
msgid "One article in this blog"
|
||||
msgid_plural "{{ count }} articles in this blog"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[0] "Un artigo en este blog"
|
||||
msgstr[1] "{{ count }} artigos en este blog"
|
||||
|
||||
msgid "Previous page"
|
||||
msgstr ""
|
||||
msgstr "Páxina anterior"
|
||||
|
||||
msgid "Next page"
|
||||
msgstr ""
|
||||
msgstr "Páxina seguinte"
|
||||
|
||||
msgid "{{ user }} mentioned you."
|
||||
msgstr ""
|
||||
msgstr "{{ user }} mencionouna."
|
||||
|
||||
msgid "{{ user }} commented your article."
|
||||
msgstr ""
|
||||
msgstr "{{ user }} comentou o artigo."
|
||||
|
||||
msgid "{{ user }} is now following you."
|
||||
msgstr ""
|
||||
msgstr "{{ user }} está a seguila."
|
||||
|
||||
msgid "{{ user }} liked your article."
|
||||
msgstr ""
|
||||
msgstr "{{ user }} gustou do seu artigo."
|
||||
|
||||
msgid "{{ user }} boosted your article."
|
||||
msgstr ""
|
||||
|
||||
msgid "Source code"
|
||||
msgstr ""
|
||||
msgstr "Código fonte"
|
||||
|
||||
msgid "Matrix room"
|
||||
msgstr ""
|
||||
msgstr "Sala Matrix"
|
||||
|
||||
msgid "Administration"
|
||||
msgstr ""
|
||||
msgstr "Administración"
|
||||
|
||||
msgid "Instance settings"
|
||||
msgstr ""
|
||||
msgstr "Axustes da instancia"
|
||||
|
||||
msgid "Allow anyone to register"
|
||||
msgstr ""
|
||||
msgstr "Permitir o rexistro aberto"
|
||||
|
||||
msgid "Short description"
|
||||
msgstr ""
|
||||
msgstr "Descrición curta"
|
||||
|
||||
msgid "Markdown is supported"
|
||||
msgstr ""
|
||||
msgstr "Escritura Markdown activada"
|
||||
|
||||
msgid "Long description"
|
||||
msgstr ""
|
||||
msgstr "Descrición longa"
|
||||
|
||||
msgid "Default license"
|
||||
msgstr ""
|
||||
msgstr "Licenza por omisión"
|
||||
|
||||
msgid "Save settings"
|
||||
msgstr ""
|
||||
msgstr "Gardar axustes"
|
||||
|
||||
msgid "No comments yet. Be the first to react!"
|
||||
msgstr ""
|
||||
msgstr "Sin comentarios. Sexa a primeira e comentar!"
|
||||
|
||||
msgid "About this instance"
|
||||
msgstr ""
|
||||
msgstr "Sobre esta instancia"
|
||||
|
||||
msgid "What is Plume?"
|
||||
msgstr ""
|
||||
msgstr "Qué é Plume?"
|
||||
|
||||
msgid "Plume is a decentralized blogging engine."
|
||||
msgstr ""
|
||||
msgstr "Plume é un motor de publicación descentralizada."
|
||||
|
||||
msgid "Authors can manage various blogs from an unique website."
|
||||
msgstr ""
|
||||
msgstr "As autoras poden xestionar varios blogs desde un único sitio web."
|
||||
|
||||
msgid ""
|
||||
"Articles are also visible on other Plume websites, and you can interact with "
|
||||
"them directly from other platforms like Mastodon."
|
||||
msgstr ""
|
||||
"Os artigos son visibles tamén en outros sitios Plume, e pode interactuar "
|
||||
"coneles desde outras plataformas como Mastadon."
|
||||
|
||||
msgid "Create your account"
|
||||
msgstr ""
|
||||
msgstr "Cree a súa conta"
|
||||
|
||||
msgid "About {{ instance_name }}"
|
||||
msgstr ""
|
||||
msgstr "Acerca de {{ instance_name }}"
|
||||
|
||||
msgid "Home to"
|
||||
msgstr ""
|
||||
msgstr "Fogar de"
|
||||
|
||||
msgid "people"
|
||||
msgstr ""
|
||||
msgstr "persoas"
|
||||
|
||||
msgid "Who wrote"
|
||||
msgstr ""
|
||||
msgstr "Que escribiron"
|
||||
|
||||
msgid "articles"
|
||||
msgstr ""
|
||||
msgstr "artigos"
|
||||
|
||||
msgid "Read the detailed rules"
|
||||
msgstr "Lea o detalle das normas"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Delete this article"
|
||||
msgstr "Últimos artigos"
|
||||
|
||||
msgid "And connected to"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "other instances"
|
||||
msgstr "Sobre esta instancia"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Administred by"
|
||||
msgstr "Administración"
|
||||
|
||||
msgid "Runs Plume {{ version }}"
|
||||
msgstr ""
|
||||
|
|
19
po/nb.po
19
po/nb.po
|
@ -438,6 +438,24 @@ msgstr "artikler"
|
|||
msgid "Read the detailed rules"
|
||||
msgstr "Les reglene"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Delete this article"
|
||||
msgstr "Siste artikler"
|
||||
|
||||
msgid "And connected to"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "other instances"
|
||||
msgstr "Om denne instansen"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Administred by"
|
||||
msgstr "Administrasjon"
|
||||
|
||||
msgid "Runs Plume {{ version }}"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "One reshare"
|
||||
#~ msgid_plural "{{ count }} reshares"
|
||||
#~ msgstr[0] "Én deling"
|
||||
|
@ -455,5 +473,6 @@ msgstr "Les reglene"
|
|||
#~ msgid "{{ user }} reshared your article."
|
||||
#~ msgstr "{{ user }} delte artikkelen din med sine følgere."
|
||||
|
||||
|
||||
#~ msgid "Your password should be at least 8 characters long"
|
||||
#~ msgstr "Passordet ditt må bestå av minst åtte tegn"
|
||||
|
|
18
po/pl.po
18
po/pl.po
|
@ -449,6 +449,24 @@ msgstr "artykuły"
|
|||
msgid "Read the detailed rules"
|
||||
msgstr "Przeczytaj szczegółowe zasady"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Delete this article"
|
||||
msgstr "Najnowsze artykuły"
|
||||
|
||||
msgid "And connected to"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "other instances"
|
||||
msgstr "O tej instancji"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Administred by"
|
||||
msgstr "Administracja"
|
||||
|
||||
msgid "Runs Plume {{ version }}"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "One reshare"
|
||||
#~ msgid_plural "{{ count }} reshares"
|
||||
#~ msgstr[0] "Jedno udostępnienie"
|
||||
|
|
15
po/plume.pot
15
po/plume.pot
|
@ -420,3 +420,18 @@ msgstr ""
|
|||
|
||||
msgid "Read the detailed rules"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete this article"
|
||||
msgstr ""
|
||||
|
||||
msgid "And connected to"
|
||||
msgstr ""
|
||||
|
||||
msgid "other instances"
|
||||
msgstr ""
|
||||
|
||||
msgid "Administred by"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runs Plume {{ version }}"
|
||||
msgstr ""
|
||||
|
|
11
src/inbox.rs
11
src/inbox.rs
|
@ -1,4 +1,4 @@
|
|||
use activitypub::activity::{Announce, Create, Like, Undo};
|
||||
use activitypub::{activity::{Announce, Create, Delete, Like, Undo}, object::Tombstone};
|
||||
use diesel::PgConnection;
|
||||
use failure::Error;
|
||||
use serde_json;
|
||||
|
@ -32,6 +32,11 @@ pub trait Inbox {
|
|||
Err(InboxError::InvalidType)?
|
||||
}
|
||||
},
|
||||
"Delete" => {
|
||||
let act: Delete = serde_json::from_value(act.clone())?;
|
||||
Post::delete_id(act.delete_props.object_object::<Tombstone>()?.object_props.id_string()?, conn);
|
||||
Ok(())
|
||||
},
|
||||
"Follow" => {
|
||||
Follow::from_activity(conn, serde_json::from_value(act.clone())?, actor_id);
|
||||
Ok(())
|
||||
|
@ -44,11 +49,11 @@ pub trait Inbox {
|
|||
let act: Undo = serde_json::from_value(act.clone())?;
|
||||
match act.undo_props.object["type"].as_str().unwrap() {
|
||||
"Like" => {
|
||||
likes::Like::delete_activity(conn, Id::new(act.undo_props.object_object::<Like>()?.object_props.id_string()?));
|
||||
likes::Like::delete_id(act.undo_props.object_object::<Like>()?.object_props.id_string()?, conn);
|
||||
Ok(())
|
||||
},
|
||||
"Announce" => {
|
||||
Reshare::delete_activity(conn, Id::new(act.undo_props.object_object::<Announce>()?.object_props.id_string()?));
|
||||
Reshare::delete_id(act.undo_props.object_object::<Announce>()?.object_props.id_string()?, conn);
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(InboxError::CantUndo)?
|
||||
|
|
18
src/main.rs
18
src/main.rs
|
@ -1,13 +1,16 @@
|
|||
#![feature(custom_derive, decl_macro, plugin)]
|
||||
#![plugin(rocket_codegen)]
|
||||
|
||||
|
||||
extern crate activitypub;
|
||||
extern crate atom_syndication;
|
||||
extern crate colored;
|
||||
extern crate diesel;
|
||||
extern crate dotenv;
|
||||
extern crate failure;
|
||||
extern crate gettextrs;
|
||||
extern crate guid_create;
|
||||
extern crate heck;
|
||||
extern crate multipart;
|
||||
extern crate plume_common;
|
||||
extern crate plume_models;
|
||||
extern crate rocket;
|
||||
|
@ -45,6 +48,7 @@ fn main() {
|
|||
routes::blogs::new,
|
||||
routes::blogs::new_auth,
|
||||
routes::blogs::create,
|
||||
routes::blogs::atom_feed,
|
||||
|
||||
routes::comments::create,
|
||||
|
||||
|
@ -54,10 +58,18 @@ fn main() {
|
|||
routes::instance::update_settings,
|
||||
routes::instance::shared_inbox,
|
||||
routes::instance::nodeinfo,
|
||||
routes::instance::about,
|
||||
|
||||
routes::likes::create,
|
||||
routes::likes::create_auth,
|
||||
|
||||
routes::medias::list,
|
||||
routes::medias::new,
|
||||
routes::medias::upload,
|
||||
routes::medias::details,
|
||||
routes::medias::delete,
|
||||
routes::medias::static_files,
|
||||
|
||||
routes::notifications::paginated_notifications,
|
||||
routes::notifications::notifications,
|
||||
routes::notifications::notifications_auth,
|
||||
|
@ -68,6 +80,7 @@ fn main() {
|
|||
routes::posts::new,
|
||||
routes::posts::new_auth,
|
||||
routes::posts::create,
|
||||
routes::posts::delete,
|
||||
|
||||
routes::reshares::create,
|
||||
routes::reshares::create_auth,
|
||||
|
@ -96,6 +109,7 @@ fn main() {
|
|||
routes::user::ap_followers,
|
||||
routes::user::new,
|
||||
routes::user::create,
|
||||
routes::user::atom_feed,
|
||||
|
||||
routes::well_known::host_meta,
|
||||
routes::well_known::nodeinfo,
|
||||
|
@ -118,7 +132,7 @@ fn main() {
|
|||
.add_exceptions(vec![
|
||||
("/inbox".to_owned(), "/inbox".to_owned(), rocket::http::Method::Post),
|
||||
("/@/<name>/inbox".to_owned(), "/@/<name>/inbox".to_owned(), rocket::http::Method::Post),
|
||||
|
||||
("/medias/new".to_owned(), "/medias/new".to_owned(), rocket::http::Method::Post), // not compatible with multipart/form-data
|
||||
])
|
||||
.finalize().unwrap())
|
||||
.launch();
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use activitypub::collection::OrderedCollection;
|
||||
use atom_syndication::{Entry, FeedBuilder};
|
||||
use rocket::{
|
||||
request::LenientForm,
|
||||
response::{Redirect, Flash}
|
||||
response::{Redirect, Flash, content::Content},
|
||||
http::ContentType
|
||||
};
|
||||
use rocket_contrib::Template;
|
||||
use serde_json;
|
||||
|
@ -129,3 +131,18 @@ fn outbox(name: String, conn: DbConn) -> ActivityStream<OrderedCollection> {
|
|||
let blog = Blog::find_local(&*conn, name).unwrap();
|
||||
blog.outbox(&*conn)
|
||||
}
|
||||
|
||||
#[get("/~/<name>/atom.xml")]
|
||||
fn atom_feed(name: String, conn: DbConn) -> Content<String> {
|
||||
let blog = Blog::find_by_fqn(&*conn, name.clone()).expect("Unable to find blog");
|
||||
let feed = FeedBuilder::default()
|
||||
.title(blog.title.clone())
|
||||
.id(Instance::get_local(&*conn).unwrap().compute_box("~", name, "atom.xml"))
|
||||
.entries(Post::get_recents_for_blog(&*conn, &blog, 15)
|
||||
.into_iter()
|
||||
.map(|p| super::post_to_atom(p, &*conn))
|
||||
.collect::<Vec<Entry>>())
|
||||
.build()
|
||||
.expect("Error building Atom feed");
|
||||
Content(ContentType::new("application", "atom+xml"), feed.to_string())
|
||||
}
|
||||
|
|
|
@ -123,3 +123,16 @@ fn nodeinfo(conn: DbConn) -> Json<serde_json::Value> {
|
|||
"metadata": {}
|
||||
}))
|
||||
}
|
||||
|
||||
#[get("/about")]
|
||||
fn about(user: User, conn: DbConn) -> Template {
|
||||
Template::render("instance/about", json!({
|
||||
"account": user,
|
||||
"instance": Instance::get_local(&*conn),
|
||||
"admin": Instance::get_local(&*conn).map(|i| i.main_admin(&*conn).to_json(&*conn)),
|
||||
"version": "0.1.0",
|
||||
"n_users": User::count_local(&*conn),
|
||||
"n_articles": Post::count_local(&*conn),
|
||||
"n_instances": Instance::count(&*conn) - 1
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use rocket::{State, response::{Redirect, Flash}};
|
||||
use workerpool::{Pool, thunk::*};
|
||||
|
||||
use plume_common::activity_pub::{broadcast, inbox::Notify};
|
||||
use plume_common::activity_pub::{broadcast, inbox::{Notify, Deletable}};
|
||||
use plume_common::utils;
|
||||
use plume_models::{
|
||||
blogs::Blog,
|
||||
|
|
111
src/routes/medias.rs
Normal file
111
src/routes/medias.rs
Normal file
|
@ -0,0 +1,111 @@
|
|||
use guid_create::GUID;
|
||||
use multipart::server::{Multipart, save::{SavedData, SaveResult}};
|
||||
use rocket::{Data, http::ContentType, response::{NamedFile, Redirect}};
|
||||
use rocket_contrib::Template;
|
||||
use serde_json;
|
||||
use std::{fs, path::{Path, PathBuf}};
|
||||
use plume_models::{db_conn::DbConn, medias::*, users::User};
|
||||
|
||||
#[get("/medias")]
|
||||
fn list(user: User, conn: DbConn) -> Template {
|
||||
let medias = Media::for_user(&*conn, user.id);
|
||||
Template::render("medias/index", json!({
|
||||
"account": user,
|
||||
"medias": medias.into_iter().map(|m| m.to_json(&*conn)).collect::<Vec<serde_json::Value>>()
|
||||
}))
|
||||
}
|
||||
|
||||
#[get("/medias/new")]
|
||||
fn new(user: User) -> Template {
|
||||
Template::render("medias/new", json!({
|
||||
"account": user,
|
||||
"form": {},
|
||||
"errors": {}
|
||||
}))
|
||||
}
|
||||
|
||||
#[post("/medias/new", data = "<data>")]
|
||||
fn upload(user: User, data: Data, ct: &ContentType, conn: DbConn) -> Redirect {
|
||||
if ct.is_form_data() {
|
||||
let (_, boundary) = ct.params().find(|&(k, _)| k == "boundary").expect("No boundary");
|
||||
|
||||
match Multipart::with_body(data.open(), boundary).save().temp() {
|
||||
SaveResult::Full(entries) => {
|
||||
let fields = entries.fields;
|
||||
|
||||
let filename = fields.get(&"file".to_string()).unwrap().into_iter().next().unwrap().headers
|
||||
.filename.clone()
|
||||
.unwrap_or("x.png".to_string()); // PNG by default
|
||||
let ext = filename.rsplitn(2, ".")
|
||||
.next()
|
||||
.unwrap();
|
||||
let dest = format!("media/{}.{}", GUID::rand().to_string(), ext);
|
||||
|
||||
if let SavedData::Bytes(ref bytes) = fields[&"file".to_string()][0].data {
|
||||
fs::write(&dest, bytes).expect("Couldn't save upload");
|
||||
} else {
|
||||
if let SavedData::File(ref path, _) = fields[&"file".to_string()][0].data {
|
||||
fs::copy(path, &dest).expect("Couldn't copy temp upload");
|
||||
} else {
|
||||
println!("not file");
|
||||
return Redirect::to(uri!(new));
|
||||
}
|
||||
}
|
||||
|
||||
let has_cw = read(&fields[&"cw".to_string()][0].data).len() > 0;
|
||||
let media = Media::insert(&*conn, NewMedia {
|
||||
file_path: dest,
|
||||
alt_text: read(&fields[&"alt".to_string()][0].data),
|
||||
is_remote: false,
|
||||
remote_url: None,
|
||||
sensitive: has_cw,
|
||||
content_warning: if has_cw {
|
||||
Some(read(&fields[&"cw".to_string()][0].data))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
owner_id: user.id
|
||||
});
|
||||
println!("ok");
|
||||
Redirect::to(uri!(details: id = media.id))
|
||||
},
|
||||
SaveResult::Partial(_, _) | SaveResult::Error(_) => {
|
||||
println!("partial err");
|
||||
Redirect::to(uri!(new))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println!("not form data");
|
||||
Redirect::to(uri!(new))
|
||||
}
|
||||
}
|
||||
|
||||
fn read(data: &SavedData) -> String {
|
||||
if let SavedData::Text(s) = data {
|
||||
s.clone()
|
||||
} else {
|
||||
panic!("Field is not a string")
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/medias/<id>")]
|
||||
fn details(id: i32, user: User, conn: DbConn) -> Template {
|
||||
let media = Media::get(&*conn, id);
|
||||
Template::render("medias/details", json!({
|
||||
"account": user,
|
||||
"media": media.map(|m| m.to_json(&*conn))
|
||||
}))
|
||||
}
|
||||
|
||||
#[get("/medias/<id>/delete")]
|
||||
fn delete(id: i32, _user: User, conn: DbConn) -> Redirect {
|
||||
let media = Media::get(&*conn, id).expect("Media to delete not found");
|
||||
media.delete(&*conn);
|
||||
Redirect::to(uri!(list))
|
||||
}
|
||||
|
||||
#[get("/static/media/<file..>", rank = 1)]
|
||||
fn static_files(file: PathBuf) -> Option<NamedFile> {
|
||||
NamedFile::open(Path::new("media/").join(file)).ok()
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
use atom_syndication::{ContentBuilder, Entry, EntryBuilder, LinkBuilder, Person, PersonBuilder};
|
||||
use diesel::PgConnection;
|
||||
use rocket::{
|
||||
http::uri::{FromUriParam, UriDisplay},
|
||||
response::NamedFile
|
||||
|
@ -7,6 +9,8 @@ use std::{
|
|||
path::{Path, PathBuf}
|
||||
};
|
||||
|
||||
use plume_models::posts::Post;
|
||||
|
||||
macro_rules! may_fail {
|
||||
($account:expr, $expr:expr, $template:expr, $msg:expr, | $res:ident | $block:block) => {
|
||||
{
|
||||
|
@ -75,11 +79,31 @@ impl Page {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn post_to_atom(post: Post, conn: &PgConnection) -> Entry {
|
||||
EntryBuilder::default()
|
||||
.title(post.title.clone())
|
||||
.content(ContentBuilder::default()
|
||||
.value(format!("<![CDATA[{}]]>", *post.content.get()))
|
||||
.src(post.ap_url.clone())
|
||||
.content_type("html".to_string())
|
||||
.build().expect("Atom feed: content error"))
|
||||
.authors(post.get_authors(&*conn)
|
||||
.into_iter()
|
||||
.map(|a| PersonBuilder::default()
|
||||
.name(a.display_name)
|
||||
.uri(a.ap_url)
|
||||
.build().expect("Atom feed: author error"))
|
||||
.collect::<Vec<Person>>())
|
||||
.links(vec![LinkBuilder::default().href(post.ap_url).build().expect("Atom feed: link error")])
|
||||
.build().expect("Atom feed: entry error")
|
||||
}
|
||||
|
||||
pub mod blogs;
|
||||
pub mod comments;
|
||||
pub mod errors;
|
||||
pub mod instance;
|
||||
pub mod likes;
|
||||
pub mod medias;
|
||||
pub mod notifications;
|
||||
pub mod posts;
|
||||
pub mod reshares;
|
||||
|
@ -87,7 +111,7 @@ pub mod session;
|
|||
pub mod user;
|
||||
pub mod well_known;
|
||||
|
||||
#[get("/static/<file..>")]
|
||||
#[get("/static/<file..>", rank = 2)]
|
||||
fn static_files(file: PathBuf) -> Option<NamedFile> {
|
||||
NamedFile::open(Path::new("static/").join(file)).ok()
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::{collections::HashMap, borrow::Cow};
|
|||
use validator::{Validate, ValidationError, ValidationErrors};
|
||||
use workerpool::{Pool, thunk::*};
|
||||
|
||||
use plume_common::activity_pub::{broadcast, ActivityStream, ApRequest};
|
||||
use plume_common::activity_pub::{broadcast, ActivityStream, ApRequest, inbox::Deletable};
|
||||
use plume_common::utils;
|
||||
use plume_models::{
|
||||
blogs::*,
|
||||
|
@ -53,10 +53,11 @@ fn details_response(blog: String, slug: String, conn: DbConn, user: Option<User>
|
|||
"has_liked": user.clone().map(|u| u.has_liked(&*conn, &post)).unwrap_or(false),
|
||||
"n_reshares": post.get_reshares(&*conn).len(),
|
||||
"has_reshared": user.clone().map(|u| u.has_reshared(&*conn, &post)).unwrap_or(false),
|
||||
"account": user,
|
||||
"account": &user,
|
||||
"date": &post.creation_date.timestamp(),
|
||||
"previous": query.and_then(|q| q.responding_to.map(|r| Comment::get(&*conn, r).expect("Error retrieving previous comment").to_json(&*conn, &vec![]))),
|
||||
"user_fqn": user.map(|u| u.get_fqn(&*conn)).unwrap_or(String::new())
|
||||
"user_fqn": user.clone().map(|u| u.get_fqn(&*conn)).unwrap_or(String::new()),
|
||||
"is_author": user.map(|u| post.get_authors(&*conn).into_iter().any(|a| u.id == a.id)).unwrap_or(false)
|
||||
}))
|
||||
})
|
||||
})
|
||||
|
@ -176,3 +177,23 @@ fn create(blog_name: String, data: LenientForm<NewPostForm>, user: User, conn: D
|
|||
})))
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/~/<blog_name>/<slug>/delete")]
|
||||
fn delete(blog_name: String, slug: String, conn: DbConn, user: User, worker: State<Pool<ThunkWorker<()>>>) -> Redirect {
|
||||
let post = Blog::find_by_fqn(&*conn, blog_name.clone())
|
||||
.and_then(|blog| Post::find_by_slug(&*conn, slug.clone(), blog.id));
|
||||
|
||||
if let Some(post) = post {
|
||||
if !post.get_authors(&*conn).into_iter().any(|a| a.id == user.id) {
|
||||
Redirect::to(uri!(details: blog = blog_name.clone(), slug = slug.clone()))
|
||||
} else {
|
||||
let audience = user.get_followers(&*conn);
|
||||
let delete_activity = post.delete(&*conn);
|
||||
worker.execute(Thunk::of(move || broadcast(&user, delete_activity, audience)));
|
||||
|
||||
Redirect::to(uri!(super::blogs::details: name = blog_name))
|
||||
}
|
||||
} else {
|
||||
Redirect::to(uri!(super::blogs::details: name = blog_name))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use rocket::{State, response::{Redirect, Flash}};
|
||||
use workerpool::{Pool, thunk::*};
|
||||
|
||||
use plume_common::activity_pub::{broadcast, inbox::Notify};
|
||||
use plume_common::activity_pub::{broadcast, inbox::{Deletable, Notify}};
|
||||
use plume_common::utils;
|
||||
use plume_models::{
|
||||
blogs::Blog,
|
||||
|
|
|
@ -3,10 +3,12 @@ use activitypub::{
|
|||
collection::OrderedCollection,
|
||||
object::Article
|
||||
};
|
||||
use atom_syndication::{Entry, FeedBuilder};
|
||||
use rocket::{
|
||||
State,
|
||||
request::LenientForm,
|
||||
response::{Redirect, Flash}
|
||||
response::{Redirect, Flash, Content},
|
||||
http::ContentType
|
||||
};
|
||||
use rocket_contrib::Template;
|
||||
use serde_json;
|
||||
|
@ -276,3 +278,18 @@ fn ap_followers(name: String, conn: DbConn, _ap: ApRequest) -> ActivityStream<Or
|
|||
coll.collection_props.set_items_link_vec(followers).expect("Follower collection: items error");
|
||||
ActivityStream::new(coll)
|
||||
}
|
||||
|
||||
#[get("/@/<name>/atom.xml")]
|
||||
fn atom_feed(name: String, conn: DbConn) -> Content<String> {
|
||||
let author = User::find_by_fqn(&*conn, name.clone()).expect("Unable to find author");
|
||||
let feed = FeedBuilder::default()
|
||||
.title(author.display_name.clone())
|
||||
.id(Instance::get_local(&*conn).unwrap().compute_box("~", name, "atom.xml"))
|
||||
.entries(Post::get_recents_for_author(&*conn, &author, 15)
|
||||
.into_iter()
|
||||
.map(|p| super::post_to_atom(p, &*conn))
|
||||
.collect::<Vec<Entry>>())
|
||||
.build()
|
||||
.expect("Error building Atom feed");
|
||||
Content(ContentType::new("application", "atom+xml"), feed.to_string())
|
||||
}
|
||||
|
|
|
@ -215,7 +215,7 @@ fn create_admin(instance: Instance, conn: DbConn) {
|
|||
fn check_native_deps() {
|
||||
let mut not_found = Vec::new();
|
||||
if !try_run("psql") {
|
||||
not_found.push(("PostgreSQL", "sudo apt install postgres"));
|
||||
not_found.push(("PostgreSQL", "sudo apt install postgresql"));
|
||||
}
|
||||
if !try_run("gettext") {
|
||||
not_found.push(("GetText", "sudo apt install gettext"))
|
||||
|
|
1
static/images/boxicon-menu.svg
Normal file
1
static/images/boxicon-menu.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M3 6h18v2H3zM3 11h18v2H3zM3 16h18v2H3z" fill="#F4F4F4"/></svg>
|
After Width: | Height: | Size: 154 B |
9
static/js/autoExpand.js
Normal file
9
static/js/autoExpand.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
function autosize () {
|
||||
const el = this
|
||||
el.style.height = 'auto'
|
||||
el.style.height = `${el.scrollHeight}px`
|
||||
}
|
||||
|
||||
const articleContent = document.querySelector('#content')
|
||||
autosize.bind(articleContent)()
|
||||
articleContent.addEventListener('keyup', autosize)
|
148
static/main.css
148
static/main.css
|
@ -24,8 +24,7 @@ a, a:visited {
|
|||
|
||||
small {
|
||||
margin-left: 1em;
|
||||
color: #242424;
|
||||
opacity: 0.6;
|
||||
color: rgba(36, 36, 36, 0.6);
|
||||
font-size: 0.75em;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
|
@ -42,19 +41,43 @@ small {
|
|||
margin: 4rem 0;
|
||||
}
|
||||
|
||||
.banner {
|
||||
background: #DADADA;
|
||||
padding-top: 2em;
|
||||
padding-bottom: 1em;
|
||||
margin: 3em 0px;
|
||||
}
|
||||
|
||||
/*
|
||||
* == Header ==
|
||||
*/
|
||||
|
||||
header {
|
||||
background: #ECECEC;
|
||||
}
|
||||
header #content {
|
||||
display: flex;
|
||||
align-content: center;
|
||||
justify-content: space-between;
|
||||
background: #ECECEC;
|
||||
}
|
||||
|
||||
header #menu {
|
||||
header nav#menu {
|
||||
position: relative;
|
||||
display: none;
|
||||
transform: skewX(-15deg);
|
||||
left: -1em;
|
||||
padding: 1em 1em 1em 2em;
|
||||
background: #7765E3;
|
||||
align-self: flex-start;
|
||||
}
|
||||
header nav#menu a {
|
||||
transform: skewX(15deg);
|
||||
width: 1.75em;
|
||||
height: 1.75em;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: url("/static/images/boxicon-menu.svg") no-repeat center;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
header nav {
|
||||
|
@ -361,7 +384,7 @@ input:focus, textarea:focus {
|
|||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
|
||||
|
||||
font-family: "Lora", serif;
|
||||
font-size: 1.1em;
|
||||
line-height: 1.5em;
|
||||
|
@ -422,6 +445,9 @@ form.new-post .title {
|
|||
}
|
||||
form.new-post textarea {
|
||||
min-height: 20em;
|
||||
overflow-y: hidden;
|
||||
resize: none;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
form.new-post input[type="submit"] {
|
||||
background: #ECECEC;
|
||||
|
@ -442,6 +468,7 @@ form.new-post input[type="submit"]:hover { background: #DADADA; }
|
|||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-bottom: 0;
|
||||
z-index: -20;
|
||||
}
|
||||
.badge {
|
||||
margin-left: 1em;
|
||||
|
@ -545,45 +572,94 @@ form.new-post input[type="submit"]:hover { background: #DADADA; }
|
|||
* Small Screens *
|
||||
* ================= */
|
||||
|
||||
@media screen and (max-width: 500px) {
|
||||
header {
|
||||
padding: 1em;
|
||||
@media screen and (max-width: 900px) {
|
||||
header {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
header #menu {
|
||||
display: flex;
|
||||
header nav#menu {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
header > nav {
|
||||
header #content {
|
||||
display: none;
|
||||
text-align: center;
|
||||
}
|
||||
header nav a, header nav a.title { padding: 0.5em; }
|
||||
header nav a.title {
|
||||
width: 100vw;
|
||||
margin: 0;
|
||||
border: none;
|
||||
font-size: 1.75em;
|
||||
|
||||
@keyframes menuOpening {
|
||||
from {
|
||||
transform: scaleX(0);
|
||||
transform-origin: left;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
transform: scaleX(1);
|
||||
transform-origin: left;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
header:focus-within > nav {
|
||||
header:focus-within #content {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
animation: 0.2s menuOpening;
|
||||
}
|
||||
header:focus-within #content::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
transform: skewX(-10deg);
|
||||
top: 0;
|
||||
left: -20%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
z-index: -10;
|
||||
|
||||
background: #7765E3;
|
||||
}
|
||||
header:focus-within #content > nav {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
header:focus-within #content > nav a {
|
||||
margin: 0;
|
||||
padding: 1rem 1.5rem;
|
||||
color: #F4F4F4;
|
||||
font-size: 1.4em;
|
||||
font-weight: 300;
|
||||
}
|
||||
header:focus-within #content > nav a.title {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
header:focus-within #content > nav hr {
|
||||
display: block;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
border: solid #F4F4F4 0.1rem;
|
||||
}
|
||||
|
||||
body > main > * {
|
||||
body > main > * {
|
||||
padding: 0 5%;
|
||||
}
|
||||
main .article-meta > * { margin: 0 5%; }
|
||||
|
||||
main .article-meta > p {
|
||||
main .article-meta > p {
|
||||
margin: 2em 5%;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
main .article-meta .comments > * { margin-left: 5%; margin-right: 5%; }
|
||||
|
||||
.card {
|
||||
.card {
|
||||
min-width: 80%;
|
||||
min-height: 80%;
|
||||
}
|
||||
|
@ -602,7 +678,8 @@ form.new-post input[type="submit"]:hover { background: #DADADA; }
|
|||
/*== Flex boxes ==*/
|
||||
.flex {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.flex .grow {
|
||||
|
@ -631,3 +708,30 @@ body > footer {
|
|||
body > footer * {
|
||||
margin: 5em 0;
|
||||
}
|
||||
|
||||
/** Medias **/
|
||||
|
||||
figure {
|
||||
text-align: center;
|
||||
margin: 2em;
|
||||
max-width: 100%;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
figure > * {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
figcaption {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.preview {
|
||||
display: block;
|
||||
max-width: 100px;
|
||||
max-height: 100px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
|
|
@ -9,24 +9,28 @@
|
|||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav id="menu"><a href="#">{{ "Menu" | _ }}</a></nav>
|
||||
<nav>
|
||||
<a href="/" class="title">{{ "Plume" | _ }}</a>
|
||||
<hr/>
|
||||
{% block header %}
|
||||
{% endblock header %}
|
||||
</nav>
|
||||
<nav>
|
||||
{% if account %}
|
||||
<a href="/dashboard">{{ "Dashboard" | _ }}</a>
|
||||
<a href="/notifications">{{ "Notifications" | _ }}</a>
|
||||
<a href="/me">{{ "My account" | _ }}</a>
|
||||
<a href="/logout">{{ "Log Out" | _ }}</a>
|
||||
{% else %}
|
||||
<a href="/login">{{ "Log In" | _ }}</a>
|
||||
<a href="/users/new">{{ "Register" | _ }}</a>
|
||||
{% endif %}
|
||||
<nav id="menu">
|
||||
<a href="#" aria-label="{{ "Menu" | _ }}" title="{{ "Menu" | _ }}"></a>
|
||||
</nav>
|
||||
<div id="content">
|
||||
<nav>
|
||||
<a href="/" class="title">{{ "Plume" | _ }}</a>
|
||||
<hr/>
|
||||
{% block header %}
|
||||
{% endblock header %}
|
||||
</nav>
|
||||
<nav>
|
||||
{% if account %}
|
||||
<a href="/dashboard">{{ "Dashboard" | _ }}</a>
|
||||
<a href="/notifications">{{ "Notifications" | _ }}</a>
|
||||
<a href="/me">{{ "My account" | _ }}</a>
|
||||
<a href="/logout">{{ "Log Out" | _ }}</a>
|
||||
{% else %}
|
||||
<a href="/login">{{ "Log In" | _ }}</a>
|
||||
<a href="/users/new">{{ "Register" | _ }}</a>
|
||||
{% endif %}
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
{% block content %}
|
||||
|
|
|
@ -23,7 +23,10 @@
|
|||
</p>
|
||||
|
||||
<section>
|
||||
<h2>{{ "Latest articles" | _ }}</h2>
|
||||
<h2>
|
||||
{{ "Latest articles" | _ }}
|
||||
<small><a href="/@/{{ blog.fqn }}/atom.xml"><i title="Atom feed" class="fa fa-rss"></i></a></small>
|
||||
</h2>
|
||||
{% if posts | length < 1 %}
|
||||
<p>{{ "No posts to see here yet." | _ }}</p>
|
||||
{% endif %}
|
||||
|
|
40
templates/instance/about.html.tera
Normal file
40
templates/instance/about.html.tera
Normal file
|
@ -0,0 +1,40 @@
|
|||
{% extends "base" %}
|
||||
{% import "macros" as macros %}
|
||||
|
||||
{% block title %}
|
||||
About {{ instance.name }}
|
||||
{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{{ "About {{ instance_name }}" | _(instance_name=instance.name) }}</h1>
|
||||
<section>
|
||||
{{ instance.short_description_html | safe }}
|
||||
</section>
|
||||
<div class="banner">
|
||||
<section class="stats">
|
||||
<div>
|
||||
<p>{{ "Home to" | _ }}</p>
|
||||
<em>{{ n_users }}</em>
|
||||
<p>{{ "people" | _ }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>{{ "Who wrote" | _ }}</p>
|
||||
<em>{{ n_articles }}</em>
|
||||
<p>{{ "articles" | _ }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>{{ "And connected to" | _ }}</p>
|
||||
<em>{{ n_instances }}</em>
|
||||
<p>{{ "other instances" | _ }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>{{ "Administred by" | _ }}</p>
|
||||
<p><a href="/@/{{ admin.fqn }}">{{ admin.name }}</a><small>(@{{ admin.fqn }})</small></p>
|
||||
</div>
|
||||
</section>
|
||||
<p>{{ "Runs Plume {{ version }}" | _(version=version) }}
|
||||
</div>
|
||||
<section>
|
||||
{{ instance.long_description_html | safe }}
|
||||
</section>
|
||||
{% endblock content %}
|
24
templates/medias/details.html.tera
Normal file
24
templates/medias/details.html.tera
Normal file
|
@ -0,0 +1,24 @@
|
|||
{% extends "base" %}
|
||||
{% import "macros" as macros %}
|
||||
|
||||
{% block title %}
|
||||
Your medias
|
||||
{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{{ "Media details" }}</h1>
|
||||
<section>
|
||||
<a href="/medias">Go back to the gallery</a>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<figure class="media">
|
||||
{{ media.html | safe }}
|
||||
<figcaption>{{ media.alt_text }}</figcaption>
|
||||
</figure>
|
||||
<div>
|
||||
<a href="/medias/{{ media.id }}/avatar" class="button inline-block">Use as avatar</a>
|
||||
<a href="/medias/{{ media.id }}/delete" class="button inline-block">Delete</a>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock content %}
|
31
templates/medias/index.html.tera
Normal file
31
templates/medias/index.html.tera
Normal file
|
@ -0,0 +1,31 @@
|
|||
{% extends "base" %}
|
||||
{% import "macros" as macros %}
|
||||
|
||||
{% block title %}
|
||||
Your medias
|
||||
{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{{ "Your medias" }}</h1>
|
||||
<div>
|
||||
<a href="/medias/new" class="inline-block button">Upload</a>
|
||||
</div>
|
||||
|
||||
<section>
|
||||
{% if medias | length < 1 %}
|
||||
<p>{{ "You don't have any media yet." | _ }}</p>
|
||||
{% endif %}
|
||||
<div class="list">
|
||||
{% for media in medias %}
|
||||
<div class="card flex">
|
||||
{{ media.html_preview | safe }}
|
||||
<main class="grow">
|
||||
<p><a href="/medias/{{ media.id }}">{{ media.alt_text }}</a></p>
|
||||
</main>
|
||||
<a href="/medias/{{ media.id }}/delete">Delete</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{# macros::paginate(page=page, total=n_pages) #}
|
||||
</section>
|
||||
{% endblock content %}
|
17
templates/medias/new.html.tera
Normal file
17
templates/medias/new.html.tera
Normal file
|
@ -0,0 +1,17 @@
|
|||
{% extends "base" %}
|
||||
{% import "macros" as macros %}
|
||||
|
||||
{% block title %}
|
||||
{{ "Media upload" | _ }}
|
||||
{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{{ "Media upload" | _ }}</h1>
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{{ macros::input(name="alt", label="Description", errors=errors, form=form, props='required minlength="1"', details='Useful for visually impaired people and licensing') }}
|
||||
{{ macros::input(name="cw", label="Content warning", errors=errors, form=form, details='Let it empty if there is none') }}
|
||||
{{ macros::input(name="file", type='file', label="File", errors=errors, form=form, props='required') }}
|
||||
|
||||
<input type="submit" value="{{ "Send" | _ }}"/>
|
||||
</form>
|
||||
{% endblock content %}
|
|
@ -22,6 +22,10 @@
|
|||
}}</a></span>
|
||||
—
|
||||
<span class="date">{{ date | date(format="%B %e, %Y") }}</span>
|
||||
{% if is_author %}
|
||||
—
|
||||
<a href="{{ article.url}}delete">{{ "Delete this article" | _ }}</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
<article>
|
||||
{{ article.post.content | safe }}
|
||||
|
|
|
@ -17,11 +17,12 @@
|
|||
{% endif %}
|
||||
|
||||
<label for="content">{{ "Content" | _ }}<small>{{ "Markdown is supported" | _ }}</small></label>
|
||||
<textarea id="content" name="content" value="{{ form.content | default(value="") }}"></textarea>
|
||||
<textarea id="content" name="content" value="{{ form.content | default(value="") }}" rows="20"></textarea>
|
||||
|
||||
{% set license_infos = "Default license will be {{ instance.default_license }}" | _(instance=instance) %}
|
||||
{{ macros::input(name="license", label="License", errors=errors, form=form, optional=true, details=license_infos) }}
|
||||
|
||||
<input type="submit" value="{{ "Publish" | _ }}" />
|
||||
</form>
|
||||
<script src="/static/js/autoExpand.js"></script>
|
||||
{% endblock content %}
|
||||
|
|
|
@ -18,8 +18,11 @@
|
|||
{{ user.summary | safe }}
|
||||
</div>
|
||||
|
||||
{% if recents | length != 0 %}
|
||||
<h2>{{ "Latest articles" | _ }}</h2>
|
||||
{% if recents | length != 0 %}
|
||||
<h2>
|
||||
{{ "Latest articles" | _ }}
|
||||
<small><a href="/@/{{ user.fqn }}/atom.xml"><i title="Atom feed" class="fa fa-rss"></i></a></small>
|
||||
</h2>
|
||||
<div class="cards">
|
||||
{% for article in recents %}
|
||||
{{ macros::post_card(article=article) }}
|
||||
|
|
Loading…
Reference in a new issue