Compare commits
23 commits
3d6a006f19
...
b80c1adc33
Author | SHA1 | Date | |
---|---|---|---|
b80c1adc33 | |||
097bd9b965 | |||
3c84378910 | |||
456830fc3a | |||
20e5d27974 | |||
86b98d33ba | |||
a1e1a0df5f | |||
4980c9e24c | |||
9fcbb5ad67 | |||
2c26ab95de | |||
af769100e7 | |||
e7b0925a64 | |||
66ca846ebb | |||
db6f753d6e | |||
620b901bc3 | |||
a8ddf20098 | |||
5cd35e2e8e | |||
500d87d65b | |||
8ab294277b | |||
c47b511e04 | |||
78d5bafae3 | |||
716584841e | |||
d5353fb019 |
5 changed files with 450 additions and 75 deletions
274
Cargo.lock
generated
274
Cargo.lock
generated
|
@ -1,17 +1,35 @@
|
||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ascii_utils"
|
name = "ascii_utils"
|
||||||
version = "0.9.3"
|
version = "0.9.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a"
|
checksum = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"safemem",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
|
@ -57,6 +75,28 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chrono"
|
||||||
|
version = "0.4.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
"time",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cloudabi"
|
||||||
|
version = "0.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation"
|
name = "core-foundation"
|
||||||
version = "0.9.1"
|
version = "0.9.1"
|
||||||
|
@ -73,6 +113,21 @@ 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 = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
|
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "email"
|
||||||
|
version = "0.0.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "91549a51bb0241165f13d57fc4c72cef063b4088fb078b019ecbf464a45f22e4"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.9.3",
|
||||||
|
"chrono",
|
||||||
|
"encoding",
|
||||||
|
"lazy_static",
|
||||||
|
"rand 0.4.6",
|
||||||
|
"time",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding"
|
name = "encoding"
|
||||||
version = "0.2.33"
|
version = "0.2.33"
|
||||||
|
@ -161,6 +216,12 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fuchsia-cprng"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.14"
|
version = "0.3.14"
|
||||||
|
@ -313,7 +374,7 @@ version = "0.9.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "86ed8677138975b573ab4949c35613931a4addeadd0a8a6aa0327e2a979660de"
|
checksum = "86ed8677138975b573ab4949c35613931a4addeadd0a8a6aa0327e2a979660de"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64 0.10.1",
|
||||||
"bufstream",
|
"bufstream",
|
||||||
"fast_chemail",
|
"fast_chemail",
|
||||||
"hostname",
|
"hostname",
|
||||||
|
@ -325,6 +386,20 @@ dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lettre_email"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fd02480f8dcf48798e62113974d6ccca2129a51d241fa20f1ea349c8a42559d5"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.10.1",
|
||||||
|
"email",
|
||||||
|
"lettre",
|
||||||
|
"mime",
|
||||||
|
"time",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.93"
|
version = "0.2.93"
|
||||||
|
@ -348,15 +423,22 @@ checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mention_2_mail"
|
name = "mention_2_mail"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"irc-proto",
|
"irc-proto",
|
||||||
"irc_stream",
|
"irc_stream",
|
||||||
"lettre",
|
"lettre",
|
||||||
|
"lettre_email",
|
||||||
"native-tls",
|
"native-tls",
|
||||||
"toml",
|
"toml",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mime"
|
||||||
|
version = "0.3.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "native-tls"
|
name = "native-tls"
|
||||||
version = "0.2.7"
|
version = "0.2.7"
|
||||||
|
@ -385,6 +467,25 @@ dependencies = [
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 1.0.1",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 1.0.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.7.2"
|
version = "1.7.2"
|
||||||
|
@ -417,7 +518,7 @@ version = "0.9.61"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "313752393519e876837e09e1fa183ddef0be7735868dced3196f4472d536277f"
|
checksum = "313752393519e876837e09e1fa183ddef0be7735868dced3196f4472d536277f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg 1.0.1",
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
|
@ -478,6 +579,38 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
|
||||||
|
dependencies = [
|
||||||
|
"fuchsia-cprng",
|
||||||
|
"libc",
|
||||||
|
"rand_core 0.3.1",
|
||||||
|
"rdrand",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 0.1.7",
|
||||||
|
"libc",
|
||||||
|
"rand_chacha 0.1.1",
|
||||||
|
"rand_core 0.4.2",
|
||||||
|
"rand_hc 0.1.0",
|
||||||
|
"rand_isaac",
|
||||||
|
"rand_jitter",
|
||||||
|
"rand_os",
|
||||||
|
"rand_pcg",
|
||||||
|
"rand_xorshift",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.8.3"
|
version = "0.8.3"
|
||||||
|
@ -485,9 +618,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
|
checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"rand_chacha",
|
"rand_chacha 0.3.0",
|
||||||
"rand_core",
|
"rand_core 0.6.2",
|
||||||
"rand_hc",
|
"rand_hc 0.3.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 0.1.7",
|
||||||
|
"rand_core 0.3.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -497,9 +640,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
|
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ppv-lite86",
|
"ppv-lite86",
|
||||||
"rand_core",
|
"rand_core 0.6.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.4.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_core"
|
name = "rand_core"
|
||||||
version = "0.6.2"
|
version = "0.6.2"
|
||||||
|
@ -509,13 +667,84 @@ dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_hc"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.3.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_hc"
|
name = "rand_hc"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
|
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rand_core",
|
"rand_core 0.6.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_isaac"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.3.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_jitter"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_core 0.4.2",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_os"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
|
||||||
|
dependencies = [
|
||||||
|
"cloudabi",
|
||||||
|
"fuchsia-cprng",
|
||||||
|
"libc",
|
||||||
|
"rand_core 0.4.2",
|
||||||
|
"rdrand",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_pcg"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 0.1.7",
|
||||||
|
"rand_core 0.4.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_xorshift"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.3.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rdrand"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.3.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -542,6 +771,12 @@ version = "1.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "safemem"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "schannel"
|
name = "schannel"
|
||||||
version = "0.1.19"
|
version = "0.1.19"
|
||||||
|
@ -628,7 +863,7 @@ checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"rand",
|
"rand 0.8.3",
|
||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
"remove_dir_all",
|
"remove_dir_all",
|
||||||
"winapi",
|
"winapi",
|
||||||
|
@ -654,13 +889,23 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time"
|
||||||
|
version = "0.1.43"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "83f0c8e7c0addab50b663055baf787d0af7f413a46e6e7fb9559a4e4db7137a5"
|
checksum = "83f0c8e7c0addab50b663055baf787d0af7f413a46e6e7fb9559a4e4db7137a5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg 1.0.1",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -693,6 +938,15 @@ version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uuid"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a"
|
||||||
|
dependencies = [
|
||||||
|
"rand 0.6.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vcpkg"
|
name = "vcpkg"
|
||||||
version = "0.2.12"
|
version = "0.2.12"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "mention_2_mail"
|
name = "mention_2_mail"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
authors = ["Thelie <git.daniel@mowitz.rocks>"]
|
authors = ["Thelie <git.daniel@mowitz.rocks>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ edition = "2018"
|
||||||
irc-proto = "0.15"
|
irc-proto = "0.15"
|
||||||
irc_stream = { path = "irc-stream", version = "0.1" }
|
irc_stream = { path = "irc-stream", version = "0.1" }
|
||||||
lettre = "0.9"
|
lettre = "0.9"
|
||||||
|
lettre_email = "0.9"
|
||||||
native-tls = "0.2"
|
native-tls = "0.2"
|
||||||
toml = "0.5"
|
toml = "0.5"
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,9 @@ fn parse_server_dir(mut config: Value, server_config_path: PathBuf)
|
||||||
} else {
|
} else {
|
||||||
config.insert("channels".to_owned(), channels);
|
config.insert("channels".to_owned(), channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let channel_config = parse_toml_to_table(entry.path())?;
|
||||||
|
config = merge_config_maps(config, channel_config)?;
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
92
src/main.rs
92
src/main.rs
|
@ -27,9 +27,15 @@ use std::{
|
||||||
thread,
|
thread,
|
||||||
};
|
};
|
||||||
use lettre::{
|
use lettre::{
|
||||||
SendmailTransport,
|
Transport,
|
||||||
Transport
|
SmtpClient,
|
||||||
|
smtp::authentication::{
|
||||||
|
Credentials,
|
||||||
|
Mechanism,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
use lettre_email::EmailBuilder;
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut server_conf_flag = false;
|
let mut server_conf_flag = false;
|
||||||
|
@ -57,53 +63,81 @@ fn main() {
|
||||||
None => config = config::get_main_config(PathBuf::from("/etc/Mention2Mail/config.toml"))
|
None => config = config::get_main_config(PathBuf::from("/etc/Mention2Mail/config.toml"))
|
||||||
.expect("Could not get default config in /etc/Mention2Mail/default.toml"),
|
.expect("Could not get default config in /etc/Mention2Mail/default.toml"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mail_config = &config.get("email").expect("No email config found.");
|
||||||
|
|
||||||
let server_configs;
|
let server_configs;
|
||||||
|
|
||||||
match server_conf_path {
|
match server_conf_path {
|
||||||
Some(p) => server_configs = config::get_server_configs(config, PathBuf::from(p))
|
Some(p) => server_configs = config::get_server_configs(config.clone(), PathBuf::from(p))
|
||||||
.expect("Could not get server config."),
|
.expect("Could not get server config."),
|
||||||
None => server_configs = vec![config],
|
None => server_configs = vec![config.clone()],
|
||||||
}
|
}
|
||||||
|
|
||||||
let (tx,rx) = channel();
|
// TODO: This line has many problems…
|
||||||
|
let (tx,rx): (std::sync::mpsc::Sender<(String, String, String, Vec<Option<[String; 2]>>)>, std::sync::mpsc::Receiver<(String, String, String, Vec<Option<[String; 2]>>)>)= channel();
|
||||||
|
|
||||||
let mut server_threads = vec![];
|
let mut server_threads = vec![];
|
||||||
|
|
||||||
for s_conf in server_configs {
|
for s_conf in server_configs {
|
||||||
let t = tx.clone();
|
let t = tx.clone();
|
||||||
|
|
||||||
|
let addr = s_conf.get("server").unwrap().as_str()
|
||||||
|
.ok_or("Could not get server adress from config").unwrap();
|
||||||
server_threads.push(thread::Builder::new()
|
server_threads.push(thread::Builder::new()
|
||||||
.name("server name here".to_string())
|
.name(addr.to_string())
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
servers::handle_server(s_conf, t).unwrap();
|
servers::handle_server(s_conf, t, 5).unwrap();
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut mailer = SendmailTransport::new();
|
let smtp_address = mail_config.get("address")
|
||||||
|
.expect("No SMTP server address found.")
|
||||||
|
.as_str()
|
||||||
|
.unwrap();
|
||||||
|
let smpt_user = mail_config.get("user")
|
||||||
|
.expect("No SMTP user name found.")
|
||||||
|
.as_str()
|
||||||
|
.unwrap();
|
||||||
|
let smtp_pass = mail_config.get("pass")
|
||||||
|
.expect("No SMTP password found.")
|
||||||
|
.as_str()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mail_client = SmtpClient::new_simple(smtp_address).unwrap();
|
||||||
|
let mail_client = mail_client.credentials(
|
||||||
|
Credentials::new(smpt_user.to_owned(), smtp_pass.to_owned())
|
||||||
|
);
|
||||||
|
let mail_client = mail_client.authentication_mechanism(Mechanism::Plain);
|
||||||
|
let mut mailer = mail_client.transport();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match rx.recv() {
|
match rx.recv() {
|
||||||
Ok(data) => {
|
Ok((email_address, server, channel, context)) => {
|
||||||
println!("Sending mail to: {}", data[0]);
|
println!("Sending mail to: {}", email_address);
|
||||||
let id = "notarealiid@mention2mail".to_owned();
|
|
||||||
let body = format!("Subject: You were mentioned in {} on {}\n{} wrote: {}",
|
|
||||||
data[2], data[1], data[3], data[4]).into_bytes();
|
|
||||||
let mail = lettre::SendableEmail::new(
|
|
||||||
lettre::Envelope::new(
|
|
||||||
Some(
|
|
||||||
lettre::EmailAddress::new("m2m@chaostreff-alzey.de".to_owned())
|
|
||||||
.unwrap()
|
|
||||||
),
|
|
||||||
vec![
|
|
||||||
lettre::EmailAddress::new(data[0].clone()).unwrap()]
|
|
||||||
).unwrap(),
|
|
||||||
id,
|
|
||||||
body
|
|
||||||
);
|
|
||||||
|
|
||||||
match mailer.send(mail) {
|
let mut body = "".to_owned();
|
||||||
|
for opt in context.iter() {
|
||||||
|
match opt{
|
||||||
|
Some([sender, msg]) => {
|
||||||
|
body.push_str(&format!("{} wrote: {}\n", sender, msg))
|
||||||
|
},
|
||||||
|
None => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mail = EmailBuilder::new()
|
||||||
|
.to((email_address.clone(), "Someone"))
|
||||||
|
.from("m2m@chaostreff-alzey.de")
|
||||||
|
.subject(format!("You were mentioned in {} on {}", channel, server))
|
||||||
|
.text(body)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
match mailer.send(mail.into()) {
|
||||||
Ok(_) => println!("Email sent successfully!"),
|
Ok(_) => println!("Email sent successfully!"),
|
||||||
Err(e) => panic!("Could not send email: {:?}", e),
|
Err(e) => println!("Could not send email: {:?}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_e) => (),
|
Err(_e) => (),
|
||||||
|
|
153
src/servers.rs
153
src/servers.rs
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::VecDeque,
|
collections::VecDeque,
|
||||||
|
collections::HashMap,
|
||||||
sync::mpsc::Sender,
|
sync::mpsc::Sender,
|
||||||
};
|
};
|
||||||
use irc_proto::command::{
|
use irc_proto::command::{
|
||||||
|
@ -30,6 +31,55 @@ use toml::map::{
|
||||||
use irc_proto::message::Message;
|
use irc_proto::message::Message;
|
||||||
use toml::value::Value;
|
use toml::value::Value;
|
||||||
|
|
||||||
|
/// A static implementation of a ringbuffer.
|
||||||
|
/// It holds arrays of three strings each,
|
||||||
|
/// which are meant to represent the author and message respectively.
|
||||||
|
pub struct MessageRingBuf<T> {
|
||||||
|
buf: Vec<Option<T>>,
|
||||||
|
ptr: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <T: Clone> MessageRingBuf<T> {
|
||||||
|
pub fn new(size: usize) -> Self {
|
||||||
|
|
||||||
|
Self{
|
||||||
|
buf: vec!(None; size),
|
||||||
|
ptr: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a message to the end of the buffer,
|
||||||
|
/// overwriting the first value if the buffer is full.
|
||||||
|
pub fn push(&mut self, val: T) {
|
||||||
|
self.ptr = (self.ptr + 1) % self.buf.len();
|
||||||
|
self.buf[self.ptr] = Some(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the last element of the buffer,
|
||||||
|
/// replacing it with none.
|
||||||
|
pub fn pop(&mut self) -> Option<T> {
|
||||||
|
let l = self.buf.len();
|
||||||
|
self.ptr = (self.ptr + l - 1) % l;
|
||||||
|
self.buf[self.ptr].take()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the contained buffer in the correct order.
|
||||||
|
pub fn get_queue(& self) -> Vec<Option<T>> {
|
||||||
|
let l = self.buf.len();
|
||||||
|
let mut queue = self.buf.clone();
|
||||||
|
|
||||||
|
for i in self.ptr + 1 .. l {
|
||||||
|
queue[i - self.ptr - 1] = self.buf[i].clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0 .. self.ptr + 1{
|
||||||
|
queue[l - self.ptr - 1 + i] = self.buf[i].clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
return queue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Constructs a VecDeque with the messages
|
/// Constructs a VecDeque with the messages
|
||||||
/// required to identify with an IRC server.
|
/// required to identify with an IRC server.
|
||||||
/// Uses the credentials set in -`config.toml`.
|
/// Uses the credentials set in -`config.toml`.
|
||||||
|
@ -82,30 +132,32 @@ fn get_irc_identify_messages (config: &Value)
|
||||||
|
|
||||||
/// Appends a given VecDeque to include the messages
|
/// Appends a given VecDeque to include the messages
|
||||||
/// used to join the channels defined in `config.toml`.
|
/// used to join the channels defined in `config.toml`.
|
||||||
fn get_irc_join_messages(config: &Value, queue: VecDeque<Message>)
|
fn get_irc_join_messages(channels: &Vec<Value>, queue: VecDeque<Message>)
|
||||||
-> Result<VecDeque<Message>, Box<dyn std::error::Error>> {
|
-> Result<VecDeque<Message>, Box<dyn std::error::Error>> {
|
||||||
let mut queue = queue;
|
let mut queue = queue;
|
||||||
|
|
||||||
match config.get("channels") {
|
for channel in channels {
|
||||||
Some(c) => {
|
queue.push_back(Message::from(
|
||||||
for channel in c.as_array().ok_or("Could not parse channels.")? {
|
Command::JOIN(
|
||||||
queue.push_back(Message::from(
|
String::from(channel.as_str().ok_or("Could not parse one of the channels")?),
|
||||||
Command::JOIN(
|
None,
|
||||||
String::from(channel.as_str().ok_or("Could not parse one of the channels")?),
|
None
|
||||||
None,
|
)
|
||||||
None
|
))
|
||||||
)
|
|
||||||
))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => ()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(queue)
|
Ok(queue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_message(message: Message, nick: &String, client_names: Keys)
|
/// Checks messages for mentions of users or commands in private messages.
|
||||||
-> (Option<Message>, Option<[String; 4]>) {
|
/// Returns either one of:
|
||||||
|
/// - None and None in the case no mention or command is recognized
|
||||||
|
/// - The appropriate answer as Message and None for a command
|
||||||
|
/// - None and the mentioned user and channel as String and the context as a MessageRingBuf for mentions.
|
||||||
|
fn handle_message (message: Message, nick: &String,
|
||||||
|
client_names: Keys, contexts: &mut HashMap<String, MessageRingBuf<[String; 2]>>)
|
||||||
|
-> (Option<Message>, Option<(String, String, Vec<Option<[String; 2]>>)>) {
|
||||||
|
|
||||||
let sender = match message.clone().source_nickname() {
|
let sender = match message.clone().source_nickname() {
|
||||||
Some(s) => String::from(s),
|
Some(s) => String::from(s),
|
||||||
None => String::from("anonymous")
|
None => String::from("anonymous")
|
||||||
|
@ -132,14 +184,23 @@ fn handle_message(message: Message, nick: &String, client_names: Keys)
|
||||||
),
|
),
|
||||||
None
|
None
|
||||||
)
|
)
|
||||||
}
|
} else {
|
||||||
for c_name in client_names {
|
match contexts.get_mut(&rec.clone()) {
|
||||||
if msg.contains(c_name) {
|
Some(ref mut buf) => {
|
||||||
return (None, Some([c_name.clone(),
|
buf.push([sender.clone(), msg.clone()]);
|
||||||
rec.clone(),
|
for c_name in client_names {
|
||||||
sender.clone(),
|
if msg.contains(c_name) {
|
||||||
msg.clone()
|
return (None, Some((
|
||||||
]))
|
c_name.clone(),
|
||||||
|
rec.clone(),
|
||||||
|
buf.get_queue(),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
println!("Channel not recognized: {}", rec.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -148,18 +209,36 @@ fn handle_message(message: Message, nick: &String, client_names: Keys)
|
||||||
return (None, None)
|
return (None, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_server(config: Value, tx: Sender<[String; 5]>)
|
/// Connects to a server and indefinitely iterates the messages received.
|
||||||
|
/// Calls handle_message on each one and pushes
|
||||||
|
/// email, server, channel as Strings
|
||||||
|
/// and the context as MessageRingBuf to the given stream.
|
||||||
|
pub fn handle_server
|
||||||
|
(config: Value, tx: Sender<(String, String, String, Vec<Option<[String; 2]>>)>,context_size: usize)
|
||||||
-> Result<(), Box<dyn std::error::Error>> {
|
-> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
let server_name = config.get("server").unwrap().as_str()
|
let server_name = config.get("server").unwrap().as_str()
|
||||||
.ok_or("Could not get server adress from config")?;
|
.ok_or("Could not get server adress from config")?;
|
||||||
let nick = config.get("nickname").unwrap().as_str()
|
let nick = config.get("nickname").unwrap().as_str()
|
||||||
.ok_or("Could not get nickname from config")?.to_owned();
|
.ok_or("Could not get nickname from config")?.to_owned();
|
||||||
|
let channels = config.get("channels").unwrap().as_array()
|
||||||
|
.ok_or("Could not get channels from config")?;
|
||||||
|
|
||||||
let clients;
|
let clients;
|
||||||
match config.get("clients").unwrap().as_table() {
|
match config.get("clients").unwrap().as_table() {
|
||||||
Some(t) => clients = t.clone(),
|
Some(t) => clients = t.clone(),
|
||||||
None => clients = Map::new(),
|
None => clients = Map::new(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut chat_contexts = HashMap::new();
|
||||||
|
for channel in channels {
|
||||||
|
chat_contexts.insert(
|
||||||
|
channel.as_str()
|
||||||
|
.ok_or("Could not parse one of the channels")?
|
||||||
|
.to_owned(),
|
||||||
|
MessageRingBuf::new(context_size),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let mut stream = super::connect::connect_irc(&config).unwrap();
|
let mut stream = super::connect::connect_irc(&config).unwrap();
|
||||||
let mut message_queue = get_irc_identify_messages(&config).unwrap();
|
let mut message_queue = get_irc_identify_messages(&config).unwrap();
|
||||||
|
@ -168,7 +247,7 @@ pub fn handle_server(config: Value, tx: Sender<[String; 5]>)
|
||||||
stream.write(message).unwrap();
|
stream.write(message).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
message_queue = get_irc_join_messages(&config, message_queue).unwrap();
|
message_queue = get_irc_join_messages(&channels, message_queue).unwrap();
|
||||||
|
|
||||||
// Wait for first ping and join channels after sending pong.
|
// Wait for first ping and join channels after sending pong.
|
||||||
loop {
|
loop {
|
||||||
|
@ -190,24 +269,28 @@ pub fn handle_server(config: Value, tx: Sender<[String; 5]>)
|
||||||
// Handle all incoming messages after joining the channels.
|
// Handle all incoming messages after joining the channels.
|
||||||
loop {
|
loop {
|
||||||
let message = stream.read()?;
|
let message = stream.read()?;
|
||||||
let (answer, data) = handle_message(message, &nick, clients.keys());
|
let (answer, data) = handle_message(
|
||||||
|
message,
|
||||||
|
&nick,
|
||||||
|
clients.keys(),
|
||||||
|
&mut chat_contexts
|
||||||
|
);
|
||||||
|
|
||||||
match answer {
|
match answer {
|
||||||
Some(a) => stream.write(a).unwrap(),
|
Some(a) => stream.write(a).unwrap(),
|
||||||
None => ()
|
None => ()
|
||||||
}
|
}
|
||||||
match data {
|
match data {
|
||||||
Some(d) => match clients.get(&d[0]) {
|
Some((client, channel, context)) => match clients.get(&client) {
|
||||||
Some(addr) => {
|
Some(addr) => {
|
||||||
// There must be a better way to do this…
|
let out = (
|
||||||
let out = [
|
|
||||||
addr.as_str()
|
addr.as_str()
|
||||||
.ok_or("Could not parse email address.")?
|
.ok_or("Could not parse email address.")?
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
server_name.to_owned(),
|
server_name.to_owned(),
|
||||||
d[1].clone(),
|
channel.clone(),
|
||||||
d[2].clone(),
|
context.clone(),
|
||||||
d[3].clone(),
|
);
|
||||||
];
|
|
||||||
tx.send(out)?
|
tx.send(out)?
|
||||||
},
|
},
|
||||||
None => (),
|
None => (),
|
||||||
|
|
Loading…
Reference in a new issue