Change template lib to tera

newstuff
Manos Pitsidianakis 2022-11-20 18:26:51 +02:00
parent ddb6d225aa
commit 2af8fe1b5e
22 changed files with 595 additions and 354 deletions

522
Cargo.lock generated
View File

@ -10,7 +10,16 @@ checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [ dependencies = [
"getrandom", "getrandom",
"once_cell", "once_cell",
"version_check 0.9.4", "version_check",
]
[[package]]
name = "aho-corasick"
version = "0.7.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
dependencies = [
"memchr",
] ]
[[package]] [[package]]
@ -28,50 +37,6 @@ version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704" checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704"
[[package]]
name = "askama"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dc2a4b6d7f812d2b13d251ae792caecebd635d6401761162d4b71d5ebe1a010"
dependencies = [
"askama_derive",
"askama_escape",
"askama_shared",
]
[[package]]
name = "askama_derive"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23ee2fff0f22ad5d215cace1227cd036c28e81e26206763bb837b6d0e766c87d"
dependencies = [
"askama_shared",
"nom 4.2.3",
"proc-macro2 0.4.30",
"quote 0.6.13",
"syn 0.15.44",
]
[[package]]
name = "askama_escape"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0de942230b5beedaa9e1d64df5b76fa1c97002e4c7982897be899cccf40621d"
[[package]]
name = "askama_shared"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6dfa6b6d254fd066a8bbed9a8f913123e3f701db89216ad4f0aff04ad87718c"
dependencies = [
"askama_escape",
"humansize",
"num-traits",
"serde",
"serde_derive",
"toml 0.4.10",
]
[[package]] [[package]]
name = "async-channel" name = "async-channel"
version = "1.6.1" version = "1.6.1"
@ -180,9 +145,9 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27"
dependencies = [ dependencies = [
"proc-macro2 1.0.40", "proc-macro2",
"quote 1.0.20", "quote",
"syn 1.0.98", "syn",
] ]
[[package]] [[package]]
@ -267,6 +232,15 @@ dependencies = [
"once_cell", "once_cell",
] ]
[[package]]
name = "bstr"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "buf_redux" name = "buf_redux"
version = "0.8.4" version = "0.8.4"
@ -339,6 +313,28 @@ dependencies = [
"winapi 0.3.9", "winapi 0.3.9",
] ]
[[package]]
name = "chrono-tz"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29c39203181991a7dd4343b8005bd804e7a9a37afb8ac070e43771e8c820bbde"
dependencies = [
"chrono",
"chrono-tz-build",
"phf",
]
[[package]]
name = "chrono-tz-build"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f509c3a87b33437b05e2458750a0700e5bdd6956176773e6c7d6dd15a283a0c"
dependencies = [
"parse-zoneinfo",
"phf",
"phf_codegen",
]
[[package]] [[package]]
name = "clap" name = "clap"
version = "2.34.0" version = "2.34.0"
@ -388,6 +384,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "crossbeam-utils"
version = "0.8.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "422f23e724af1240ec469ea1e834d87a4b59ce2efe2c6a96256b0c47e2fd86aa"
dependencies = [
"cfg-if 1.0.0",
]
[[package]] [[package]]
name = "crypto-common" name = "crypto-common"
version = "0.1.6" version = "0.1.6"
@ -404,6 +409,12 @@ version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57"
[[package]]
name = "deunicode"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690"
[[package]] [[package]]
name = "digest" name = "digest"
version = "0.9.0" version = "0.9.0"
@ -519,7 +530,7 @@ version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc"
dependencies = [ dependencies = [
"version_check 0.9.4", "version_check",
] ]
[[package]] [[package]]
@ -696,9 +707,9 @@ version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
dependencies = [ dependencies = [
"proc-macro2 1.0.40", "proc-macro2",
"quote 1.0.20", "quote",
"syn 1.0.98", "syn",
] ]
[[package]] [[package]]
@ -738,7 +749,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803"
dependencies = [ dependencies = [
"typenum", "typenum",
"version_check 0.9.4", "version_check",
] ]
[[package]] [[package]]
@ -752,6 +763,30 @@ dependencies = [
"wasi 0.11.0+wasi-snapshot-preview1", "wasi 0.11.0+wasi-snapshot-preview1",
] ]
[[package]]
name = "globset"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a"
dependencies = [
"aho-corasick",
"bstr",
"fnv",
"log",
"regex",
]
[[package]]
name = "globwalk"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc"
dependencies = [
"bitflags",
"ignore",
"walkdir",
]
[[package]] [[package]]
name = "h2" name = "h2"
version = "0.3.13" version = "0.3.13"
@ -910,6 +945,24 @@ dependencies = [
"unicode-normalization", "unicode-normalization",
] ]
[[package]]
name = "ignore"
version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d"
dependencies = [
"crossbeam-utils",
"globset",
"lazy_static",
"log",
"memchr",
"regex",
"same-file",
"thread_local",
"walkdir",
"winapi-util",
]
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.9.1" version = "1.9.1"
@ -1051,7 +1104,7 @@ dependencies = [
"base64", "base64",
"either", "either",
"log", "log",
"nom 7.1.1", "nom",
"ternop", "ternop",
] ]
@ -1085,7 +1138,7 @@ dependencies = [
"serde_json", "serde_json",
"stderrlog", "stderrlog",
"tempfile", "tempfile",
"toml 0.5.9", "toml",
"xdg", "xdg",
] ]
@ -1131,7 +1184,7 @@ dependencies = [
"libloading", "libloading",
"native-tls", "native-tls",
"nix", "nix",
"nom 7.1.1", "nom",
"notify", "notify",
"serde", "serde",
"serde_derive", "serde_derive",
@ -1239,9 +1292,10 @@ dependencies = [
name = "mpot-archives" name = "mpot-archives"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"askama", "lazy_static",
"mailpot", "mailpot",
"percent-encoding", "percent-encoding",
"tera",
"tokio", "tokio",
"warp", "warp",
] ]
@ -1305,16 +1359,6 @@ dependencies = [
"memoffset", "memoffset",
] ]
[[package]]
name = "nom"
version = "4.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
dependencies = [
"memchr",
"version_check 0.1.5",
]
[[package]] [[package]]
name = "nom" name = "nom"
version = "7.1.1" version = "7.1.1"
@ -1405,9 +1449,9 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
dependencies = [ dependencies = [
"proc-macro2 1.0.40", "proc-macro2",
"quote 1.0.20", "quote",
"syn 1.0.98", "syn",
] ]
[[package]] [[package]]
@ -1458,12 +1502,104 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "parse-zoneinfo"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41"
dependencies = [
"regex",
]
[[package]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.1.0" version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "pest"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbc7bc69c062e492337d74d59b120c274fd3d261b6bf6d3207d499b4b379c41a"
dependencies = [
"thiserror",
"ucd-trie",
]
[[package]]
name = "pest_derive"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b75706b9642ebcb34dab3bc7750f811609a0eb1dd8b88c2d15bf628c1c65b2"
dependencies = [
"pest",
"pest_generator",
]
[[package]]
name = "pest_generator"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4f9272122f5979a6511a749af9db9bfc810393f63119970d7085fed1c4ea0db"
dependencies = [
"pest",
"pest_meta",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "pest_meta"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8717927f9b79515e565a64fe46c38b8cd0427e64c40680b14a7365ab09ac8d"
dependencies = [
"once_cell",
"pest",
"sha1",
]
[[package]]
name = "phf"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c"
dependencies = [
"phf_shared",
]
[[package]]
name = "phf_codegen"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a56ac890c5e3ca598bbdeaa99964edb5b0258a583a9eb6ef4e89fc85d9224770"
dependencies = [
"phf_generator",
"phf_shared",
]
[[package]]
name = "phf_generator"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf"
dependencies = [
"phf_shared",
"rand",
]
[[package]]
name = "phf_shared"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676"
dependencies = [
"siphasher",
"uncased",
]
[[package]] [[package]]
name = "pin-project" name = "pin-project"
version = "1.0.11" version = "1.0.11"
@ -1479,9 +1615,9 @@ version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74" checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74"
dependencies = [ dependencies = [
"proc-macro2 1.0.40", "proc-macro2",
"quote 1.0.20", "quote",
"syn 1.0.98", "syn",
] ]
[[package]] [[package]]
@ -1528,10 +1664,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [ dependencies = [
"proc-macro-error-attr", "proc-macro-error-attr",
"proc-macro2 1.0.40", "proc-macro2",
"quote 1.0.20", "quote",
"syn 1.0.98", "syn",
"version_check 0.9.4", "version_check",
] ]
[[package]] [[package]]
@ -1540,18 +1676,9 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [ dependencies = [
"proc-macro2 1.0.40", "proc-macro2",
"quote 1.0.20", "quote",
"version_check 0.9.4", "version_check",
]
[[package]]
name = "proc-macro2"
version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
dependencies = [
"unicode-xid",
] ]
[[package]] [[package]]
@ -1569,22 +1696,13 @@ version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quote"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
dependencies = [
"proc-macro2 0.4.30",
]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.20" version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
dependencies = [ dependencies = [
"proc-macro2 1.0.40", "proc-macro2",
] ]
[[package]] [[package]]
@ -1637,6 +1755,23 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "regex"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]] [[package]]
name = "remove_dir_all" name = "remove_dir_all"
version = "0.5.3" version = "0.5.3"
@ -1794,9 +1929,9 @@ version = "1.0.139"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc1d3230c1de7932af58ad8ffbe1d784bd55efd5a9d84ac24f69c72d83543dfb" checksum = "dc1d3230c1de7932af58ad8ffbe1d784bd55efd5a9d84ac24f69c72d83543dfb"
dependencies = [ dependencies = [
"proc-macro2 1.0.40", "proc-macro2",
"quote 1.0.20", "quote",
"syn 1.0.98", "syn",
] ]
[[package]] [[package]]
@ -1846,6 +1981,17 @@ dependencies = [
"digest 0.10.3", "digest 0.10.3",
] ]
[[package]]
name = "sha1"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "006769ba83e921b3085caa8334186b00cf92b4cb1a6cf4632fbccc8eff5c7549"
dependencies = [
"cfg-if 1.0.0",
"cpufeatures",
"digest 0.10.3",
]
[[package]] [[package]]
name = "sha1_smol" name = "sha1_smol"
version = "1.0.0" version = "1.0.0"
@ -1871,12 +2017,27 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "siphasher"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.6" version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
[[package]]
name = "slug"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373"
dependencies = [
"deunicode",
]
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.9.0" version = "1.9.0"
@ -1957,20 +2118,9 @@ source = "git+https://github.com/epilys/structopt-derive-manpage#2861b6318cfe9fc
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro-error", "proc-macro-error",
"proc-macro2 1.0.40", "proc-macro2",
"quote 1.0.20", "quote",
"syn 1.0.98", "syn",
]
[[package]]
name = "syn"
version = "0.15.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
dependencies = [
"proc-macro2 0.4.30",
"quote 0.6.13",
"unicode-xid",
] ]
[[package]] [[package]]
@ -1979,8 +2129,8 @@ version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
dependencies = [ dependencies = [
"proc-macro2 1.0.40", "proc-macro2",
"quote 1.0.20", "quote",
"unicode-ident", "unicode-ident",
] ]
@ -1998,6 +2148,28 @@ dependencies = [
"winapi 0.3.9", "winapi 0.3.9",
] ]
[[package]]
name = "tera"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c9783d6ff395ae80cf17ed9a25360e7ba37742a79fa8fddabb073c5c7c8856d"
dependencies = [
"chrono",
"chrono-tz",
"globwalk",
"humansize",
"lazy_static",
"percent-encoding",
"pest",
"pest_derive",
"rand",
"regex",
"serde",
"serde_json",
"slug",
"unic-segment",
]
[[package]] [[package]]
name = "termcolor" name = "termcolor"
version = "1.1.3" version = "1.1.3"
@ -2037,9 +2209,9 @@ version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
dependencies = [ dependencies = [
"proc-macro2 1.0.40", "proc-macro2",
"quote 1.0.20", "quote",
"syn 1.0.98", "syn",
] ]
[[package]] [[package]]
@ -2104,9 +2276,9 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
dependencies = [ dependencies = [
"proc-macro2 1.0.40", "proc-macro2",
"quote 1.0.20", "quote",
"syn 1.0.98", "syn",
] ]
[[package]] [[package]]
@ -2161,15 +2333,6 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "toml"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.5.9" version = "0.5.9"
@ -2246,13 +2409,78 @@ version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
[[package]]
name = "ucd-trie"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81"
[[package]]
name = "uncased"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622"
dependencies = [
"version_check",
]
[[package]]
name = "unic-char-property"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221"
dependencies = [
"unic-char-range",
]
[[package]]
name = "unic-char-range"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc"
[[package]]
name = "unic-common"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc"
[[package]]
name = "unic-segment"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23"
dependencies = [
"unic-ucd-segment",
]
[[package]]
name = "unic-ucd-segment"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700"
dependencies = [
"unic-char-property",
"unic-char-range",
"unic-ucd-version",
]
[[package]]
name = "unic-ucd-version"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4"
dependencies = [
"unic-common",
]
[[package]] [[package]]
name = "unicase" name = "unicase"
version = "2.6.0" version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
dependencies = [ dependencies = [
"version_check 0.9.4", "version_check",
] ]
[[package]] [[package]]
@ -2288,12 +2516,6 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
[[package]] [[package]]
name = "untrusted" name = "untrusted"
version = "0.7.1" version = "0.7.1"
@ -2341,12 +2563,6 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.4" version = "0.9.4"
@ -2441,9 +2657,9 @@ dependencies = [
"bumpalo", "bumpalo",
"lazy_static", "lazy_static",
"log", "log",
"proc-macro2 1.0.40", "proc-macro2",
"quote 1.0.20", "quote",
"syn 1.0.98", "syn",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -2453,7 +2669,7 @@ version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa"
dependencies = [ dependencies = [
"quote 1.0.20", "quote",
"wasm-bindgen-macro-support", "wasm-bindgen-macro-support",
] ]
@ -2463,9 +2679,9 @@ version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048"
dependencies = [ dependencies = [
"proc-macro2 1.0.40", "proc-macro2",
"quote 1.0.20", "quote",
"syn 1.0.98", "syn",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]

View File

@ -16,8 +16,9 @@ name = "mpot-archives"
path = "src/main.rs" path = "src/main.rs"
[dependencies] [dependencies]
askama = "0.8" tera = "1"
mailpot = { version = "0.1.0", path = "../core" } mailpot = { version = "0.1.0", path = "../core" }
percent-encoding = "2.1" percent-encoding = "2.1"
tokio = { version = "1", features = ["full"] } tokio = { version = "1", features = ["full"] }
warp = "0.3" warp = "0.3"
lazy_static = "*"

View File

@ -25,9 +25,30 @@ pub use mailpot::errors::*;
pub use mailpot::models::*; pub use mailpot::models::*;
pub use mailpot::*; pub use mailpot::*;
use askama::Template; use std::sync::Arc;
use percent_encoding::percent_decode_str;
use percent_encoding::percent_decode_str;
use tera::{Context, Tera};
use warp::Filter;
lazy_static::lazy_static! {
pub static ref TEMPLATES: Tera = {
let mut tera = match Tera::new("src/templates/*") {
Ok(t) => t,
Err(e) => {
println!("Parsing error(s): {}", e);
::std::process::exit(1);
}
};
let names: Vec<_> = tera.get_template_names().collect();
println!("names: {:?}", names);
assert!(!names.is_empty());
tera.autoescape_on(vec![".html", ".sql"]);
tera
};
}
/*
#[derive(Template)] #[derive(Template)]
#[template(path = "lists.html")] #[template(path = "lists.html")]
struct ListsTemplate<'a> { struct ListsTemplate<'a> {
@ -75,72 +96,99 @@ struct PostTemplate<'a> {
_in_reply_to: Option<String>, _in_reply_to: Option<String>,
_references: Vec<String>, _references: Vec<String>,
} }
*/
use warp::Filter;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let list_handler = warp::path!("lists" / i64).map(|list_pk: i64| { let config_path = std::env::args()
let db = Database::open_or_create_db().unwrap(); .skip(1)
.next()
.expect("Expected configuration file path as first argument.");
let conf = Arc::new(Configuration::from_file(config_path).unwrap());
let conf1 = conf.clone();
let list_handler = warp::path!("lists" / i64).map(move |list_pk: i64| {
let db = Database::open_db(&conf1).unwrap();
let list = db.get_list(list_pk).unwrap().unwrap(); let list = db.get_list(list_pk).unwrap().unwrap();
let months = db.months(list_pk).unwrap(); let months = db.months(list_pk).unwrap();
let posts = db.list_posts(list_pk, None).unwrap(); let posts = db.list_posts(list_pk, None).unwrap();
let template = ListTemplate { let mut context = Context::new();
title: &list.name, context.insert("title", &list.name);
list: &list, context.insert("list", &list);
months, context.insert("months", &months);
posts, context.insert("posts", &posts);
body: &list.description.clone().unwrap_or_default(), context.insert("body", &list.description.clone().unwrap_or_default());
}; Ok(warp::reply::html(
let res = template.render().unwrap(); TEMPLATES.render("list.html", &context).unwrap(),
Ok(warp::reply::html(res)) ))
}); });
let conf2 = conf.clone();
let post_handler = let post_handler =
warp::path!("list" / i64 / String).map(|list_pk: i64, message_id: String| { warp::path!("list" / i64 / String).map(move |list_pk: i64, message_id: String| {
let message_id = percent_decode_str(&message_id).decode_utf8().unwrap(); let message_id = percent_decode_str(&message_id).decode_utf8().unwrap();
let db = Database::open_or_create_db().unwrap(); let db = Database::open_db(&conf2).unwrap();
let list = db.get_list(list_pk).unwrap().unwrap(); let list = db.get_list(list_pk).unwrap().unwrap();
let posts = db.list_posts(list_pk, None).unwrap(); let posts = db.list_posts(list_pk, None).unwrap();
let post = posts let post = posts
.into_iter() .iter()
.find(|p| message_id.contains(&p.message_id)) .find(|p| message_id.contains(&p.message_id))
.unwrap(); .unwrap();
let envelope = melib::Envelope::from_bytes(post.message.as_slice(), None) let envelope = melib::Envelope::from_bytes(post.message.as_slice(), None)
.expect("Could not parse mail"); .expect("Could not parse mail");
let body = envelope.body_bytes(post.message.as_slice()); let body = envelope.body_bytes(post.message.as_slice());
let body_text = body.text(); let body_text = body.text();
let template = PostTemplate { let mut context = Context::new();
title: &list.name, context.insert("title", &list.name);
_list: &list, context.insert("list", &list);
_post: post, context.insert("post", &post);
body: &body_text, context.insert("posts", &posts);
_from: &envelope.field_from_to_string(), context.insert("body", &body_text);
_to: &envelope.field_to_to_string(), context.insert("from", &envelope.field_from_to_string());
subject: &envelope.subject(), context.insert("date", &envelope.date_as_str());
_in_reply_to: envelope.in_reply_to_display().map(|r| r.to_string()), context.insert("to", &envelope.field_to_to_string());
_references: envelope context.insert("subject", &envelope.subject());
context.insert(
"in_reply_to",
&envelope.in_reply_to_display().map(|r| r.to_string()),
);
context.insert(
"references",
&envelope
.references() .references()
.into_iter() .into_iter()
.map(|m| m.to_string()) .map(|m| m.to_string())
.collect::<Vec<String>>(), .collect::<Vec<String>>(),
}; );
let res = template.render().unwrap(); Ok(warp::reply::html(
Ok(warp::reply::html(res)) TEMPLATES.render("post.html", &context).unwrap(),
))
}); });
let index_handler = warp::path::end().map(|| { let conf3 = conf.clone();
let db = Database::open_or_create_db().unwrap(); let index_handler = warp::path::end().map(move || {
let db = Database::open_db(&conf3).unwrap();
let lists_values = db.list_lists().unwrap(); let lists_values = db.list_lists().unwrap();
dbg!(&lists_values);
let lists = lists_values let lists = lists_values
.iter() .iter()
.map(|list| (list, &db).into()) .map(|list| {
.collect::<Vec<ListTemplate<'_>>>(); let mut context = Context::new();
let template = ListsTemplate { let months = db.months(list.pk).unwrap();
title: "mailing list archive", let posts = db.list_posts(list.pk, None).unwrap();
description: "", context.insert("title", &list.name);
lists_len: lists.len(), context.insert("list", &list);
lists, context.insert("posts", &posts);
}; context.insert("months", &months);
let res = template.render().unwrap(); context.insert("body", &list.description.as_deref().unwrap_or_default());
Ok(warp::reply::html(res)) context.into_json()
})
.collect::<Vec<_>>();
let mut context = Context::new();
context.insert("title", "mailing list archive");
context.insert("description", "");
context.insert("lists", &lists);
Ok(warp::reply::html(
TEMPLATES.render("lists.html", &context).unwrap(),
))
}); });
let routes = warp::get() let routes = warp::get()
.and(index_handler) .and(index_handler)

View File

@ -1,9 +1,9 @@
{% include "header.html" %} {% include "header.html" %}
<div class="entry"> <div class="entry">
<p>{{lists_len}} lists</p> <p>{{lists|length}} lists</p>
<div class="body"> <div class="body">
{% for list in lists %} {% for list in lists %}
{{ list }} {{ list.title }}
{% endfor %} {% endfor %}
</div> </div>
</div> </div>

View File

@ -0,0 +1,36 @@
{% include "header.html" %}
<div class="entry">
<h1>{{subject}}</h1>
<table class="headers">
<tr>
<th scope="row">List</th>
<td>{{ list.id }}</td>
</tr>
<tr>
<th scope="row">From</th>
<td>{{ from }}</td>
</tr>
<tr>
<th scope="row">Date</th>
<td>{{ date }}</td>
</tr>
<tr>
<th scope="row">To</th>
<td>{{ to }}</td>
</tr>
<tr>
<th scope="row">Subject</th>
<td>{{ subject }}</td>
</tr>
{% if in_reply_to %}
<tr>
<th scope="row">In-Reply-To</th>
<td>{{ in_reply_to }}</td>
</tr>
{% endif %}
</table>
<div class="body">
<pre>{{body}}</pre>
</div>
</div>
{% include "footer.html" %}

View File

@ -1,10 +0,0 @@
{% include "header.html" %}
<div class="entry">
<h1>{{subject}}</h1>
<div class="body">
<pre>
{{body}}
</pre>
</div>
</div>
{% include "footer.html" %}

View File

@ -48,7 +48,7 @@ struct Opt {
/// Set config file /// Set config file
#[structopt(short, long, parse(from_os_str))] #[structopt(short, long, parse(from_os_str))]
#[allow(dead_code)] #[allow(dead_code)]
config: Option<PathBuf>, config: PathBuf,
#[structopt(flatten)] #[structopt(flatten)]
cmd: Command, cmd: Command,
/// Silence all output /// Silence all output
@ -65,10 +65,6 @@ struct Opt {
#[derive(Debug, StructOpt)] #[derive(Debug, StructOpt)]
#[structopt(manpage = "docs/command.mdoc")] #[structopt(manpage = "docs/command.mdoc")]
enum Command { enum Command {
///Prints database filesystem location
DbLocation,
///Prints default configuration file filesystem location
ConfigLocation,
///Dumps database data to STDOUT ///Dumps database data to STDOUT
DumpDatabase, DumpDatabase,
///Lists all registered mailing lists ///Lists all registered mailing lists
@ -238,22 +234,11 @@ fn run_app(opt: Opt) -> Result<()> {
if opt.debug { if opt.debug {
println!("DEBUG: {:?}", &opt); println!("DEBUG: {:?}", &opt);
} }
if let Some(config_path) = opt.config.as_ref() { let config = Configuration::from_file(opt.config.as_path())?;
let config = Configuration::from_file(&config_path)?;
config.init_with()?;
} else {
Configuration::init()?;
}
use Command::*; use Command::*;
let mut db = Database::open_or_create_db(&config)?;
match opt.cmd { match opt.cmd {
DbLocation => {
println!("{}", Database::db_path()?.display());
}
ConfigLocation => {
println!("{}", Configuration::default_path()?.display());
}
DumpDatabase => { DumpDatabase => {
let db = Database::open_or_create_db()?;
let lists = db.list_lists()?; let lists = db.list_lists()?;
let mut stdout = std::io::stdout(); let mut stdout = std::io::stdout();
serde_json::to_writer_pretty(&mut stdout, &lists)?; serde_json::to_writer_pretty(&mut stdout, &lists)?;
@ -262,7 +247,6 @@ fn run_app(opt: Opt) -> Result<()> {
} }
} }
ListLists => { ListLists => {
let db = Database::open_or_create_db()?;
let lists = db.list_lists()?; let lists = db.list_lists()?;
if lists.is_empty() { if lists.is_empty() {
println!("No lists found."); println!("No lists found.");
@ -288,7 +272,6 @@ fn run_app(opt: Opt) -> Result<()> {
} }
} }
List { list_id, cmd } => { List { list_id, cmd } => {
let db = Database::open_or_create_db()?;
let list = match db.get_list_by_id(&list_id)? { let list = match db.get_list_by_id(&list_id)? {
Some(v) => v, Some(v) => v,
None => { None => {
@ -531,7 +514,6 @@ fn run_app(opt: Opt) -> Result<()> {
description, description,
archive_url, archive_url,
} => { } => {
let db = Database::open_or_create_db()?;
let new = db.create_list(MailingList { let new = db.create_list(MailingList {
pk: 0, pk: 0,
name, name,
@ -564,12 +546,15 @@ fn run_app(opt: Opt) -> Result<()> {
if opt.debug { if opt.debug {
std::dbg!(&env); std::dbg!(&env);
} }
let db = Database::open_or_create_db()?;
db.post(&env, input.as_bytes(), dry_run)?; db.post(&env, input.as_bytes(), dry_run)?;
} }
Err(err) if input.trim().is_empty() => {
eprintln!("Empty input, abort.");
return Err(err.into());
}
Err(err) => { Err(err) => {
eprintln!("Could not parse message: {}", err); eprintln!("Could not parse message: {}", err);
let p = Configuration::save_message(input)?; let p = config.save_message(input)?;
eprintln!("Message saved at {}", p.display()); eprintln!("Message saved at {}", p.display());
return Err(err.into()); return Err(err.into());
} }
@ -577,7 +562,6 @@ fn run_app(opt: Opt) -> Result<()> {
} }
ErrorQueue { cmd } => match cmd { ErrorQueue { cmd } => match cmd {
ErrorQueueCommand::List => { ErrorQueueCommand::List => {
let db = Database::open_or_create_db()?;
let errors = db.error_queue()?; let errors = db.error_queue()?;
if errors.is_empty() { if errors.is_empty() {
println!("Error queue is empty."); println!("Error queue is empty.");
@ -595,7 +579,6 @@ fn run_app(opt: Opt) -> Result<()> {
} }
} }
ErrorQueueCommand::Print { index, json } => { ErrorQueueCommand::Print { index, json } => {
let db = Database::open_or_create_db()?;
let mut errors = db.error_queue()?; let mut errors = db.error_queue()?;
if !index.is_empty() { if !index.is_empty() {
errors.retain(|el| index.contains(&el.pk())); errors.retain(|el| index.contains(&el.pk()));
@ -613,7 +596,6 @@ fn run_app(opt: Opt) -> Result<()> {
} }
} }
ErrorQueueCommand::Delete { index, quiet } => { ErrorQueueCommand::Delete { index, quiet } => {
let mut db = Database::open_or_create_db()?;
let mut errors = db.error_queue()?; let mut errors = db.error_queue()?;
if !index.is_empty() { if !index.is_empty() {
errors.retain(|el| index.contains(&el.pk())); errors.retain(|el| index.contains(&el.pk()));
@ -639,7 +621,6 @@ fn run_app(opt: Opt) -> Result<()> {
list_id, list_id,
mut maildir_path, mut maildir_path,
} => { } => {
let db = Database::open_or_create_db()?;
let list = match db.get_list_by_id(&list_id)? { let list = match db.get_list_by_id(&list_id)? {
Some(v) => v, Some(v) => v,
None => { None => {

View File

@ -24,9 +24,6 @@ use std::io::{Read, Write};
use std::os::unix::fs::PermissionsExt; use std::os::unix::fs::PermissionsExt;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
thread_local!(pub static CONFIG: RefCell<Configuration> = RefCell::new(Configuration::new()));
thread_local!(static CONFIG_INIT: Cell<bool> = Cell::new(false));
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(tag = "type", content = "value")] #[serde(tag = "type", content = "value")]
pub enum SendMail { pub enum SendMail {
@ -40,33 +37,24 @@ pub struct Configuration {
#[serde(default = "default_storage_fn")] #[serde(default = "default_storage_fn")]
pub storage: String, pub storage: String,
pub db_path: PathBuf, pub db_path: PathBuf,
} pub data_path: PathBuf,
impl Default for Configuration {
fn default() -> Self {
Self::new()
}
} }
impl Configuration { impl Configuration {
pub(crate) fn new() -> Self { /*
pub fn new(db_path: impl Into<PathBuf>) -> Self {
let db_path = db_path.into();
Configuration { Configuration {
send_mail: SendMail::ShellCommand("/usr/bin/false".to_string()), send_mail: SendMail::ShellCommand("/usr/bin/false".to_string()),
storage: "sqlite3".into(), storage: "sqlite3".into(),
db_path: ".".into(), data_path: db_path
.parent()
.map(Path::to_path_buf)
.unwrap_or_else(|| db_path.clone()),
db_path,
} }
} }
*/
pub fn init_with(self) -> Result<()> {
CONFIG.with(|f| {
*f.borrow_mut() = self;
});
CONFIG_INIT.with(|f| {
f.set(true);
});
Ok(())
}
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> { pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
let path = path.as_ref(); let path = path.as_ref();
@ -81,27 +69,12 @@ impl Configuration {
Ok(config) Ok(config)
} }
pub fn init() -> Result<()> { pub fn data_directory(&self) -> &Path {
if CONFIG_INIT.with(|f| f.get()) { self.data_path.as_path()
return Ok(());
}
let mut path =
xdg::BaseDirectories::with_prefix("mailpot")?.place_config_file("config.toml")?;
if !path.exists() {
return Err(format!("Configuration file {} doesn't exist", path.display()).into());
}
if path.starts_with("~") {
path = Path::new(&std::env::var("HOME").context("No $HOME set.")?)
.join(path.strip_prefix("~").context("Internal error while getting default database path: path starts with ~ but rust couldn't strip_refix(\"~\"")?);
}
let config: Configuration = Self::from_file(&path)?;
config.init_with()
} }
pub fn data_directory() -> Result<PathBuf> { pub fn db_path(&self) -> &Path {
Ok(xdg::BaseDirectories::with_prefix("mailpot")? self.db_path.as_path()
.get_data_home()
.canonicalize()?)
} }
pub fn default_path() -> Result<PathBuf> { pub fn default_path() -> Result<PathBuf> {
@ -114,10 +87,13 @@ impl Configuration {
Ok(result) Ok(result)
} }
pub fn save_message_to_path(msg: &str, mut path: PathBuf) -> Result<PathBuf> { pub fn save_message_to_path(&self, msg: &str, mut path: PathBuf) -> Result<PathBuf> {
let now = Local::now().timestamp(); if path.is_dir() {
path.push(format!("{}-failed.eml", now)); let now = Local::now().timestamp();
path.push(format!("{}-failed.eml", now));
}
debug_assert!(path != self.db_path());
let mut file = std::fs::File::create(&path)?; let mut file = std::fs::File::create(&path)?;
let metadata = file.metadata()?; let metadata = file.metadata()?;
let mut permissions = metadata.permissions(); let mut permissions = metadata.permissions();
@ -129,23 +105,8 @@ impl Configuration {
Ok(path) Ok(path)
} }
pub fn save_message(msg: String) -> Result<PathBuf> { pub fn save_message(&self, msg: String) -> Result<PathBuf> {
match Configuration::data_directory() self.save_message_to_path(&msg, self.data_directory().to_path_buf())
.and_then(|path| Self::save_message_to_path(&msg, path))
{
Ok(p) => return Ok(p),
Err(err) => {
eprintln!("{}", err);
}
};
match Self::save_message_to_path(&msg, PathBuf::from(".")) {
Ok(p) => return Ok(p),
Err(err) => {
eprintln!("{}", err);
}
}
let temp_path = std::env::temp_dir();
Self::save_message_to_path(&msg, temp_path)
} }
} }

View File

@ -17,6 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
use super::Configuration;
use super::*; use super::*;
use crate::ErrorKind::*; use crate::ErrorKind::*;
use melib::Envelope; use melib::Envelope;
@ -25,13 +26,14 @@ use rusqlite::Connection as DbConnection;
use rusqlite::OptionalExtension; use rusqlite::OptionalExtension;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::io::Write; use std::io::Write;
use std::path::PathBuf; use std::path::{Path, PathBuf};
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
const DB_NAME: &str = "current.db"; const DB_NAME: &str = "current.db";
pub struct Database { pub struct Database {
pub connection: DbConnection, pub connection: DbConnection,
conf: Configuration,
} }
mod error_queue; mod error_queue;
@ -42,22 +44,18 @@ mod members;
pub use members::*; pub use members::*;
impl Database { impl Database {
pub fn db_path() -> Result<PathBuf> { pub fn open_db(conf: &Configuration) -> Result<Self> {
Ok(crate::config::CONFIG.with(|c| c.borrow().db_path.clone())) if !conf.db_path.exists() {
}
pub fn open_db(db_path: PathBuf) -> Result<Self> {
if !db_path.exists() {
return Err("Database doesn't exist".into()); return Err("Database doesn't exist".into());
} }
Ok(Database { Ok(Database {
connection: DbConnection::open(&db_path.to_str().unwrap())?, conf: conf.clone(),
connection: DbConnection::open(&conf.db_path.to_str().unwrap())?,
}) })
} }
pub fn open_or_create_db() -> Result<Self> { pub fn open_or_create_db(conf: &Configuration) -> Result<Self> {
crate::config::Configuration::init()?; let mut db_path = conf.db_path.to_path_buf();
let mut db_path = Self::db_path()?;
if db_path.is_dir() { if db_path.is_dir() {
db_path.push(DB_NAME); db_path.push(DB_NAME);
} }
@ -100,11 +98,14 @@ impl Database {
let conn = DbConnection::open(&db_path.to_str().unwrap())?; let conn = DbConnection::open(&db_path.to_str().unwrap())?;
Ok(Database { connection: conn }) Ok(Database {
conf: conf.clone(),
connection: conn,
})
} }
pub fn load_archives(&mut self) -> Result<&mut Self> { pub fn load_archives(&mut self, conf: &Configuration) -> Result<&mut Self> {
let archives_path = crate::config::CONFIG.with(|c| c.borrow().db_path.clone()); let archives_path = conf.data_path.clone();
let mut stmt = self.connection.prepare("ATTACH ? AS ?;")?; let mut stmt = self.connection.prepare("ATTACH ? AS ?;")?;
for archive in std::fs::read_dir(&archives_path)? { for archive in std::fs::read_dir(&archives_path)? {
let archive = archive?; let archive = archive?;
@ -232,7 +233,7 @@ impl Database {
pub fn remove_list_policy(&self, list_pk: i64, policy_pk: i64) -> Result<()> { pub fn remove_list_policy(&self, list_pk: i64, policy_pk: i64) -> Result<()> {
let mut stmt = self let mut stmt = self
.connection .connection
.prepare("DELETE FROM post_policy WHERE pk = ? AND list_pk = ?;")?; .prepare("DELETE FROM post_policy WHERE pk = ? AND list = ?;")?;
stmt.execute(rusqlite::params![&policy_pk, &list_pk,])?; stmt.execute(rusqlite::params![&policy_pk, &list_pk,])?;
trace!("remove_list_policy {} {}.", list_pk, policy_pk); trace!("remove_list_policy {} {}.", list_pk, policy_pk);
@ -240,6 +241,13 @@ impl Database {
} }
pub fn set_list_policy(&self, list_pk: i64, policy: PostPolicy) -> Result<DbVal<PostPolicy>> { pub fn set_list_policy(&self, list_pk: i64, policy: PostPolicy) -> Result<DbVal<PostPolicy>> {
if !(policy.announce_only || policy.subscriber_only || policy.approval_needed) {
return Err(
"Cannot add empty policy. Having no policies is probably what you want to do."
.into(),
);
}
let mut stmt = self.connection.prepare("INSERT OR REPLACE INTO post_policy(list, announce_only, subscriber_only, approval_needed) VALUES (?, ?, ?, ?) RETURNING *;")?; let mut stmt = self.connection.prepare("INSERT OR REPLACE INTO post_policy(list, announce_only, subscriber_only, approval_needed) VALUES (?, ?, ?, ?) RETURNING *;")?;
let ret = stmt.query_row( let ret = stmt.query_row(
rusqlite::params![ rusqlite::params![

View File

@ -119,11 +119,7 @@ impl Database {
return Ok(()); return Ok(());
} }
let mut configuration = crate::config::Configuration::new(); trace!("Configuration is {:#?}", &self.conf);
crate::config::CONFIG.with(|f| {
configuration = f.borrow().clone();
});
trace!("Configuration is {:#?}", &configuration);
use crate::mail::{ListContext, Post, PostAction}; use crate::mail::{ListContext, Post, PostAction};
for mut list in lists { for mut list in lists {
trace!("Examining list {}", list.list_id()); trace!("Examining list {}", list.list_id());
@ -161,7 +157,7 @@ impl Database {
trace!("recipients: {:?}", &recipients); trace!("recipients: {:?}", &recipients);
if let crate::config::SendMail::Smtp(ref smtp_conf) = if let crate::config::SendMail::Smtp(ref smtp_conf) =
&configuration.send_mail &self.conf.send_mail
{ {
let smtp_conf = smtp_conf.clone(); let smtp_conf = smtp_conf.clone();
use melib::futures; use melib::futures;

View File

@ -1,4 +1,4 @@
use mailpot::{models::*, Configuration, Database}; use mailpot::{models::*, Configuration, Database, SendMail};
use tempfile::TempDir; use tempfile::TempDir;
#[test] #[test]
@ -6,13 +6,17 @@ fn test_init_empty() {
let tmp_dir = TempDir::new().unwrap(); let tmp_dir = TempDir::new().unwrap();
let db_path = tmp_dir.path().join("mpot.db"); let db_path = tmp_dir.path().join("mpot.db");
let mut config = Configuration::default(); let config = Configuration {
config.db_path = db_path.clone(); send_mail: SendMail::ShellCommand("/usr/bin/false".to_string()),
db_path: db_path.clone(),
storage: "sqlite3".to_string(),
data_path: tmp_dir.path().to_path_buf(),
};
config.init_with().unwrap(); config.init_with().unwrap();
assert_eq!(Database::db_path().unwrap(), db_path); assert_eq!(Database::db_path().unwrap(), db_path);
let db = Database::open_or_create_db().unwrap(); let db = Database::open_or_create_db(&db_path).unwrap();
assert!(db.list_lists().unwrap().is_empty()); assert!(db.list_lists().unwrap().is_empty());
} }
@ -21,13 +25,17 @@ fn test_list_creation() {
let tmp_dir = TempDir::new().unwrap(); let tmp_dir = TempDir::new().unwrap();
let db_path = tmp_dir.path().join("mpot.db"); let db_path = tmp_dir.path().join("mpot.db");
let mut config = Configuration::default(); let config = Configuration {
config.db_path = db_path.clone(); send_mail: SendMail::ShellCommand("/usr/bin/false".to_string()),
db_path: db_path.clone(),
storage: "sqlite3".to_string(),
data_path: tmp_dir.path().to_path_buf(),
};
config.init_with().unwrap(); config.init_with().unwrap();
assert_eq!(Database::db_path().unwrap(), db_path); assert_eq!(Database::db_path().unwrap(), db_path);
let db = Database::open_or_create_db().unwrap(); let db = Database::open_or_create_db(&db_path).unwrap();
assert!(db.list_lists().unwrap().is_empty()); assert!(db.list_lists().unwrap().is_empty());
let foo_chat = db let foo_chat = db
.create_list(MailingList { .create_list(MailingList {

View File

@ -25,14 +25,17 @@ fn test_error_queue() {
let tmp_dir = TempDir::new().unwrap(); let tmp_dir = TempDir::new().unwrap();
let db_path = tmp_dir.path().join("mpot.db"); let db_path = tmp_dir.path().join("mpot.db");
let mut config = Configuration::default(); let config = Configuration {
config.send_mail = SendMail::Smtp(get_smtp_conf()); send_mail: SendMail::Smtp(get_smtp_conf()),
config.db_path = db_path.clone(); db_path: db_path.clone(),
storage: "sqlite3".to_string(),
data_path: tmp_dir.path().to_path_buf(),
};
config.init_with().unwrap(); config.init_with().unwrap();
assert_eq!(Database::db_path().unwrap(), db_path); assert_eq!(Database::db_path().unwrap(), db_path);
let db = Database::open_or_create_db().unwrap(); let db = Database::open_or_create_db(&db_path).unwrap();
assert!(db.list_lists().unwrap().is_empty()); assert!(db.list_lists().unwrap().is_empty());
let foo_chat = db let foo_chat = db
.create_list(MailingList { .create_list(MailingList {

View File

@ -192,14 +192,17 @@ fn test_smtp() {
}); });
let db_path = tmp_dir.path().join("mpot.db"); let db_path = tmp_dir.path().join("mpot.db");
let mut config = Configuration::default(); let config = Configuration {
config.send_mail = SendMail::Smtp(get_smtp_conf()); send_mail: SendMail::Smtp(get_smtp_conf()),
config.db_path = db_path.clone(); db_path: db_path.clone(),
config.init_with().unwrap(); storage: "sqlite3".to_string(),
data_path: tmp_dir.path().to_path_buf(),
};
config.clone().init_with().unwrap();
assert_eq!(Database::db_path().unwrap(), db_path); assert_eq!(Database::db_path().unwrap(), db_path);
let db = Database::open_or_create_db().unwrap(); let db = Database::open_or_create_db(&config.db_path).unwrap();
assert!(db.list_lists().unwrap().is_empty()); assert!(db.list_lists().unwrap().is_empty());
let foo_chat = db let foo_chat = db
.create_list(MailingList { .create_list(MailingList {

View File

@ -1,9 +1,5 @@
.Bl -tag -width Ds -compact -offset indent .Bl -tag -width Ds -compact -offset indent
.It Ic db-location
Prints database filesystem location.
.It Ic config-location
Prints default configuration file filesystem location.
.It Ic dump-database .It Ic dump-database
Dumps database data to STDOUT. Dumps database data to STDOUT.
.It Ic list-lists .It Ic list-lists
@ -39,10 +35,6 @@ Mail that has not been handled properly end up in the error queue.
. .
Import a maildir folder into an existing list. Import a maildir folder into an existing list.
.It Ic db-location
Prints database filesystem location.
.It Ic config-location
Prints default configuration file filesystem location.
.It Ic dump-database .It Ic dump-database
Dumps database data to STDOUT. Dumps database data to STDOUT.
.It Ic list-lists .It Ic list-lists

View File

@ -31,10 +31,6 @@ This command-line tool allows you to control databases of the mailing list manag
.Sh COMMANDS .Sh COMMANDS
.Bl -tag -width Ds -compact -offset indent .Bl -tag -width Ds -compact -offset indent
.It Ic db-location
Prints database filesystem location.
.It Ic config-location
Prints default configuration file filesystem location.
.It Ic dump-database .It Ic dump-database
Dumps database data to STDOUT. Dumps database data to STDOUT.
.It Ic list-lists .It Ic list-lists
@ -70,10 +66,6 @@ Mail that has not been handled properly end up in the error queue.
. .
Import a maildir folder into an existing list. Import a maildir folder into an existing list.
.It Ic db-location
Prints database filesystem location.
.It Ic config-location
Prints default configuration file filesystem location.
.It Ic dump-database .It Ic dump-database
Dumps database data to STDOUT. Dumps database data to STDOUT.
.It Ic list-lists .It Ic list-lists

View File

@ -37,9 +37,15 @@ fn json_body() -> impl Filter<Extract = (String,), Error = warp::Rejection> + Cl
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let config_path = std::env::args()
.skip(1)
.next()
.expect("Expected configuration file path as first argument.");
Configuration::init(config_path).unwrap();
// GET /lists/:i64/policy // GET /lists/:i64/policy
let policy = warp::path!("lists" / i64 / "policy").map(|list_pk| { let policy = warp::path!("lists" / i64 / "policy").map(|list_pk| {
let db = Database::open_or_create_db().unwrap(); let db = Database::open_or_create_db(&Configuration::db_path().unwrap()).unwrap();
db.get_list_policy(list_pk) db.get_list_policy(list_pk)
.ok() .ok()
.map(|l| warp::reply::json(&l.unwrap())) .map(|l| warp::reply::json(&l.unwrap()))
@ -48,21 +54,21 @@ async fn main() {
//get("/lists")] //get("/lists")]
let lists = warp::path!("lists").map(|| { let lists = warp::path!("lists").map(|| {
let db = Database::open_or_create_db().unwrap(); let db = Database::open_or_create_db(&Configuration::db_path().unwrap()).unwrap();
let lists = db.list_lists().unwrap(); let lists = db.list_lists().unwrap();
warp::reply::json(&lists) warp::reply::json(&lists)
}); });
//get("/lists/<num>")] //get("/lists/<num>")]
let lists_num = warp::path!("lists" / i64).map(|list_pk| { let lists_num = warp::path!("lists" / i64).map(|list_pk| {
let db = Database::open_or_create_db().unwrap(); let db = Database::open_or_create_db(&Configuration::db_path().unwrap()).unwrap();
let list = db.get_list(list_pk).unwrap(); let list = db.get_list(list_pk).unwrap();
warp::reply::json(&list) warp::reply::json(&list)
}); });
//get("/lists/<num>/members")] //get("/lists/<num>/members")]
let lists_members = warp::path!("lists" / i64 / "members").map(|list_pk| { let lists_members = warp::path!("lists" / i64 / "members").map(|list_pk| {
let db = Database::open_or_create_db().unwrap(); let db = Database::open_or_create_db(&Configuration::db_path().unwrap()).unwrap();
db.list_members(list_pk) db.list_members(list_pk)
.ok() .ok()
.map(|l| warp::reply::json(&l)) .map(|l| warp::reply::json(&l))
@ -71,7 +77,7 @@ async fn main() {
//get("/lists/<num>/owners")] //get("/lists/<num>/owners")]
let lists_owners = warp::path!("lists" / i64 / "owners").map(|list_pk| { let lists_owners = warp::path!("lists" / i64 / "owners").map(|list_pk| {
let db = Database::open_or_create_db().unwrap(); let db = Database::open_or_create_db(&Configuration::db_path().unwrap()).unwrap();
db.get_list_owners(list_pk) db.get_list_owners(list_pk)
.ok() .ok()
.map(|l| warp::reply::json(&l)) .map(|l| warp::reply::json(&l))