diff options
Diffstat (limited to 'fun/paroxysm')
-rw-r--r-- | fun/paroxysm/.gitignore | 5 | ||||
-rw-r--r-- | fun/paroxysm/Cargo.lock | 1579 | ||||
-rw-r--r-- | fun/paroxysm/Cargo.toml | 22 | ||||
-rw-r--r-- | fun/paroxysm/OWNERS | 3 | ||||
-rw-r--r-- | fun/paroxysm/README.md | 19 | ||||
-rw-r--r-- | fun/paroxysm/default.nix | 14 | ||||
-rw-r--r-- | fun/paroxysm/docker/default.nix | 7 | ||||
-rw-r--r-- | fun/paroxysm/migrations/20181209140247_initial/down.sql | 2 | ||||
-rw-r--r-- | fun/paroxysm/migrations/20181209140247_initial/up.sql | 15 | ||||
-rw-r--r-- | fun/paroxysm/migrations/20181218142013_fix_unique/down.sql | 1 | ||||
-rw-r--r-- | fun/paroxysm/migrations/20181218142013_fix_unique/up.sql | 1 | ||||
-rw-r--r-- | fun/paroxysm/src/cfg.rs | 12 | ||||
-rw-r--r-- | fun/paroxysm/src/keyword.rs | 219 | ||||
-rw-r--r-- | fun/paroxysm/src/main.rs | 395 | ||||
-rw-r--r-- | fun/paroxysm/src/models.rs | 36 | ||||
-rw-r--r-- | fun/paroxysm/src/schema.rs | 18 |
16 files changed, 2348 insertions, 0 deletions
diff --git a/fun/paroxysm/.gitignore b/fun/paroxysm/.gitignore new file mode 100644 index 000000000000..8cb01f2e3d35 --- /dev/null +++ b/fun/paroxysm/.gitignore @@ -0,0 +1,5 @@ +/target +irc.toml +paroxysm-irc.toml +paroxysm.toml +**/*.rs.bk diff --git a/fun/paroxysm/Cargo.lock b/fun/paroxysm/Cargo.lock new file mode 100644 index 000000000000..a3b2687c8dac --- /dev/null +++ b/fun/paroxysm/Cargo.lock @@ -0,0 +1,1579 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f" +dependencies = [ + "addr2line", + "cc", + "cfg-if 1.0.0", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bufstream" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder", + "iovec", +] + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +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 0.2.14", + "time", + "winapi 0.3.9", +] + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "config" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9107d78ed62b3fa5a86e7d18e647abed48cfd8f8fab6c72f4cdb982d196f7e6" +dependencies = [ + "lazy_static 1.4.0", + "nom", + "rust-ini", + "serde 1.0.136", + "serde-hjson", + "serde_json", + "toml", + "yaml-rust", +] + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "crimp" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe8f9a320ad9c1a2e3bacedaa281587bd297fb10a10179fd39f777049d04794" +dependencies = [ + "curl", + "serde 1.0.136", + "serde_json", +] + +[[package]] +name = "crossbeam-deque" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20ff29ded3204c5106278a81a38f4b482636ed4fa1e6cfbeef193291beb29ed" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", + "maybe-uninit", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +dependencies = [ + "autocfg", + "cfg-if 0.1.10", + "crossbeam-utils", + "lazy_static 1.4.0", + "maybe-uninit", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" +dependencies = [ + "cfg-if 0.1.10", + "crossbeam-utils", + "maybe-uninit", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +dependencies = [ + "autocfg", + "cfg-if 0.1.10", + "lazy_static 1.4.0", +] + +[[package]] +name = "curl" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d855aeef205b43f65a5001e0997d81f8efca7badad4fad7d897aa7f0d0651f" +dependencies = [ + "curl-sys", + "libc", + "openssl-probe", + "openssl-sys", + "schannel", + "socket2", + "winapi 0.3.9", +] + +[[package]] +name = "curl-sys" +version = "0.4.53+curl-7.82.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8092905a5a9502c312f223b2775f57ec5c5b715f9a15ee9d2a8591d1364a0352" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", + "winapi 0.3.9", +] + +[[package]] +name = "diesel" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b28135ecf6b7d446b43e27e225622a038cc4e2930a1022f51cdb97ada19b8e4d" +dependencies = [ + "bitflags", + "byteorder", + "chrono", + "diesel_derives", + "pq-sys", + "r2d2", +] + +[[package]] +name = "diesel_derives" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "encoding" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" +dependencies = [ + "encoding-index-japanese", + "encoding-index-korean", + "encoding-index-simpchinese", + "encoding-index-singlebyte", + "encoding-index-tradchinese", +] + +[[package]] +name = "encoding-index-japanese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-korean" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-simpchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-singlebyte" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-tradchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding_index_tests" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" + +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "failure" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +dependencies = [ + "backtrace", + "failure_derive", +] + +[[package]] +name = "failure_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + +[[package]] +name = "futures" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "gimli" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + +[[package]] +name = "irc" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eb7666c9ae95dc77b874467e347bde3789773b6f48887fb3384bfe29552b466" +dependencies = [ + "bufstream", + "bytes", + "chrono", + "encoding", + "failure", + "futures", + "log", + "native-tls", + "serde 1.0.136", + "serde_derive", + "tokio-codec", + "tokio-core", + "tokio-io", + "tokio-mockstream", + "tokio-timer 0.1.2", + "tokio-tls", + "toml", +] + +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "lazy_static" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.123" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb691a747a7ab48abc15c5b42066eaafde10dc427e3b6ee2a1cf43db04c763bd" + +[[package]] +name = "libz-sys" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f35facd4a5673cb5a48822be2be1d4236c1c99cb4113cab7061ac720d5bf859" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linked-hash-map" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd" +dependencies = [ + "serde 0.8.23", + "serde_test", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" + +[[package]] +name = "lock_api" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "lock_api" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "memoffset" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow", + "net2", + "slab 0.4.6", + "winapi 0.2.8", +] + +[[package]] +name = "mio-uds" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" +dependencies = [ + "iovec", + "libc", + "mio", +] + +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + +[[package]] +name = "native-tls" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +dependencies = [ + "lazy_static 1.4.0", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "net2" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "nom" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" +dependencies = [ + "memchr", + "version_check", +] + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits 0.2.14", +] + +[[package]] +name = "num-traits" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" +dependencies = [ + "num-traits 0.2.14", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" + +[[package]] +name = "openssl" +version = "0.10.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" +dependencies = [ + "bitflags", + "cfg-if 1.0.0", + "foreign-types", + "libc", + "once_cell", + "openssl-sys", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking_lot" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +dependencies = [ + "lock_api 0.3.4", + "parking_lot_core 0.6.2", + "rustc_version", +] + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api 0.4.7", + "parking_lot_core 0.8.5", +] + +[[package]] +name = "parking_lot_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" +dependencies = [ + "cfg-if 0.1.10", + "cloudabi", + "libc", + "redox_syscall 0.1.57", + "rustc_version", + "smallvec 0.6.14", + "winapi 0.3.9", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if 1.0.0", + "instant", + "libc", + "redox_syscall 0.2.13", + "smallvec 1.8.0", + "winapi 0.3.9", +] + +[[package]] +name = "paroxysm" +version = "0.1.0" +dependencies = [ + "chrono", + "config", + "crimp", + "diesel", + "env_logger", + "failure", + "irc", + "lazy_static 1.4.0", + "log", + "rand", + "regex", + "serde 1.0.136", +] + +[[package]] +name = "pkg-config" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "pq-sys" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac25eee5a0582f45a67e837e350d784e7003bd29a5f460796772061ca49ffda" +dependencies = [ + "vcpkg", +] + +[[package]] +name = "proc-macro2" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r2d2" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "545c5bc2b880973c9c10e4067418407a0ccaa3091781d1671d46eb35107cb26f" +dependencies = [ + "log", + "parking_lot 0.11.2", + "scheduled-thread-pool", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom", + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" + +[[package]] +name = "redox_syscall" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "rust-ini" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2" + +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + +[[package]] +name = "schannel" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +dependencies = [ + "lazy_static 1.4.0", + "winapi 0.3.9", +] + +[[package]] +name = "scheduled-thread-pool" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6f74fd1204073fa02d5d5d68bec8021be4c38690b61264b2fdb48083d0e7d7" +dependencies = [ + "parking_lot 0.11.2", +] + +[[package]] +name = "scoped-tls" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "security-framework" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" + +[[package]] +name = "serde" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-hjson" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b833c5ad67d52ced5f5938b2980f32a9c1c5ef047f0b4fb3127e7a423c76153" +dependencies = [ + "lazy_static 0.2.11", + "linked-hash-map 0.3.0", + "num-traits 0.1.43", + "regex", + "serde 0.8.23", +] + +[[package]] +name = "serde_derive" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +dependencies = [ + "itoa", + "ryu", + "serde 1.0.136", +] + +[[package]] +name = "serde_test" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "110b3dbdf8607ec493c22d5d947753282f3bae73c0f56d322af1e8c78e4c23d5" +dependencies = [ + "serde 0.8.23", +] + +[[package]] +name = "slab" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" + +[[package]] +name = "slab" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" + +[[package]] +name = "smallvec" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" +dependencies = [ + "maybe-uninit", +] + +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + +[[package]] +name = "socket2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "syn" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if 1.0.0", + "fastrand", + "libc", + "redox_syscall 0.2.13", + "remove_dir_all", + "winapi 0.3.9", +] + +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "time" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi 0.3.9", +] + +[[package]] +name = "tokio" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" +dependencies = [ + "bytes", + "futures", + "mio", + "num_cpus", + "tokio-codec", + "tokio-current-thread", + "tokio-executor", + "tokio-fs", + "tokio-io", + "tokio-reactor", + "tokio-sync", + "tokio-tcp", + "tokio-threadpool", + "tokio-timer 0.2.13", + "tokio-udp", + "tokio-uds", +] + +[[package]] +name = "tokio-codec" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" +dependencies = [ + "bytes", + "futures", + "tokio-io", +] + +[[package]] +name = "tokio-core" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87b1395334443abca552f63d4f61d0486f12377c2ba8b368e523f89e828cffd4" +dependencies = [ + "bytes", + "futures", + "iovec", + "log", + "mio", + "scoped-tls", + "tokio", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "tokio-timer 0.2.13", +] + +[[package]] +name = "tokio-current-thread" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" +dependencies = [ + "futures", + "tokio-executor", +] + +[[package]] +name = "tokio-executor" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" +dependencies = [ + "crossbeam-utils", + "futures", +] + +[[package]] +name = "tokio-fs" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" +dependencies = [ + "futures", + "tokio-io", + "tokio-threadpool", +] + +[[package]] +name = "tokio-io" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" +dependencies = [ + "bytes", + "futures", + "log", +] + +[[package]] +name = "tokio-mockstream" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41bfc436ef8b7f60c19adf3df086330ae9992385e4d8c53b17a323cad288e155" +dependencies = [ + "futures", + "tokio-io", +] + +[[package]] +name = "tokio-reactor" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" +dependencies = [ + "crossbeam-utils", + "futures", + "lazy_static 1.4.0", + "log", + "mio", + "num_cpus", + "parking_lot 0.9.0", + "slab 0.4.6", + "tokio-executor", + "tokio-io", + "tokio-sync", +] + +[[package]] +name = "tokio-sync" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" +dependencies = [ + "fnv", + "futures", +] + +[[package]] +name = "tokio-tcp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" +dependencies = [ + "bytes", + "futures", + "iovec", + "mio", + "tokio-io", + "tokio-reactor", +] + +[[package]] +name = "tokio-threadpool" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" +dependencies = [ + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-utils", + "futures", + "lazy_static 1.4.0", + "log", + "num_cpus", + "slab 0.4.6", + "tokio-executor", +] + +[[package]] +name = "tokio-timer" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6131e780037787ff1b3f8aad9da83bca02438b72277850dd6ad0d455e0e20efc" +dependencies = [ + "futures", + "slab 0.3.0", +] + +[[package]] +name = "tokio-timer" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" +dependencies = [ + "crossbeam-utils", + "futures", + "slab 0.4.6", + "tokio-executor", +] + +[[package]] +name = "tokio-tls" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" +dependencies = [ + "futures", + "native-tls", + "tokio-io", +] + +[[package]] +name = "tokio-udp" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" +dependencies = [ + "bytes", + "futures", + "log", + "mio", + "tokio-codec", + "tokio-io", + "tokio-reactor", +] + +[[package]] +name = "tokio-uds" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0" +dependencies = [ + "bytes", + "futures", + "iovec", + "libc", + "log", + "mio", + "mio-uds", + "tokio-codec", + "tokio-io", + "tokio-reactor", +] + +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" +dependencies = [ + "serde 1.0.136", +] + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map 0.5.4", +] diff --git a/fun/paroxysm/Cargo.toml b/fun/paroxysm/Cargo.toml new file mode 100644 index 000000000000..4d282285fd97 --- /dev/null +++ b/fun/paroxysm/Cargo.toml @@ -0,0 +1,22 @@ +[package] +authors = ["eeeeeta <eta@theta.eu.org>"] +edition = "2018" +name = "paroxysm" +version = "0.1.0" + +[dependencies] +chrono = "0.4" +config = "0.9" +crimp = "0.2" +env_logger = "0.7" +failure = "0.1" +irc = "0.13" +lazy_static = "1.4" +log = "0.4" +rand = "0.7" +regex = "1.3" +serde = { version = "1.0", features = [ "derive" ] } + +[dependencies.diesel] +features = [ "postgres", "chrono", "r2d2" ] +version = "1.4" diff --git a/fun/paroxysm/OWNERS b/fun/paroxysm/OWNERS new file mode 100644 index 000000000000..7f8beb1aa7d7 --- /dev/null +++ b/fun/paroxysm/OWNERS @@ -0,0 +1,3 @@ +inherited: true +owners: + - eta diff --git a/fun/paroxysm/README.md b/fun/paroxysm/README.md new file mode 100644 index 000000000000..a595530982da --- /dev/null +++ b/fun/paroxysm/README.md @@ -0,0 +1,19 @@ +paroxysm +======== + +`paroxysm` is a bot for [internet relay chat +(IRC)](https://en.wikipedia.org/wiki/Internet_Relay_Chat) that lets you store +small pieces of information, called *factoids*, and retrieve them later. It's +useful for organising frequently-used information to avoid repeating oneself in +a busy chatroom, as well as making little todo lists or notes to self in a +private chatroom. + +It was directly inspired by the +[LearnDB](https://github.com/crawl/sequell/blob/master/docs/learndb.md) +functionality offered in `##crawl` on chat.freenode.net, and uses similar +syntax. + +## Usage instructions + +Will come soon; the project is very much still in beta, and is subject to +change. diff --git a/fun/paroxysm/default.nix b/fun/paroxysm/default.nix new file mode 100644 index 000000000000..e4ce4df1ae38 --- /dev/null +++ b/fun/paroxysm/default.nix @@ -0,0 +1,14 @@ +{ depot, pkgs, ... }: + +depot.third_party.naersk.buildPackage { + name = "paroxysm"; + version = "0.0.2"; + src = ./.; + + buildInputs = with pkgs; [ + openssl + pkgconfig + postgresql.lib + curl + ]; +} diff --git a/fun/paroxysm/docker/default.nix b/fun/paroxysm/docker/default.nix new file mode 100644 index 000000000000..cb5b2758ec63 --- /dev/null +++ b/fun/paroxysm/docker/default.nix @@ -0,0 +1,7 @@ +{ depot, pkgs, ... }: + +pkgs.dockerTools.buildLayeredImage { + name = "paroxysm"; + contents = [ depot.fun.paroxysm ]; + config.Entrypoint = [ "${depot.fun.paroxysm}/bin/paroxysm" ]; +} diff --git a/fun/paroxysm/migrations/20181209140247_initial/down.sql b/fun/paroxysm/migrations/20181209140247_initial/down.sql new file mode 100644 index 000000000000..aa02f4f63f92 --- /dev/null +++ b/fun/paroxysm/migrations/20181209140247_initial/down.sql @@ -0,0 +1,2 @@ +DROP TABLE entries; +DROP TABLE keywords; diff --git a/fun/paroxysm/migrations/20181209140247_initial/up.sql b/fun/paroxysm/migrations/20181209140247_initial/up.sql new file mode 100644 index 000000000000..e8b52d5a9b91 --- /dev/null +++ b/fun/paroxysm/migrations/20181209140247_initial/up.sql @@ -0,0 +1,15 @@ +CREATE TABLE keywords ( + id SERIAL PRIMARY KEY, + name VARCHAR UNIQUE NOT NULL, + chan VARCHAR NOT NULL, + UNIQUE(name, chan) +); + +CREATE TABLE entries ( + id SERIAL PRIMARY KEY, + keyword_id INT NOT NULL REFERENCES keywords ON DELETE CASCADE, + idx INT NOT NULL, + text VARCHAR NOT NULL, + creation_ts TIMESTAMP NOT NULL, + created_by VARCHAR NOT NULL +); diff --git a/fun/paroxysm/migrations/20181218142013_fix_unique/down.sql b/fun/paroxysm/migrations/20181218142013_fix_unique/down.sql new file mode 100644 index 000000000000..291a97c5ce1f --- /dev/null +++ b/fun/paroxysm/migrations/20181218142013_fix_unique/down.sql @@ -0,0 +1 @@ +-- This file should undo anything in `up.sql` \ No newline at end of file diff --git a/fun/paroxysm/migrations/20181218142013_fix_unique/up.sql b/fun/paroxysm/migrations/20181218142013_fix_unique/up.sql new file mode 100644 index 000000000000..4885ae5edefe --- /dev/null +++ b/fun/paroxysm/migrations/20181218142013_fix_unique/up.sql @@ -0,0 +1 @@ +ALTER TABLE keywords DROP CONSTRAINT IF EXISTS keywords_name_key; diff --git a/fun/paroxysm/src/cfg.rs b/fun/paroxysm/src/cfg.rs new file mode 100644 index 000000000000..cfb2e2073e27 --- /dev/null +++ b/fun/paroxysm/src/cfg.rs @@ -0,0 +1,12 @@ +use serde::Deserialize; +use std::collections::HashSet; + +#[derive(Deserialize)] +pub struct Config { + pub database_url: String, + pub irc_config_path: String, + #[serde(default)] + pub admins: HashSet<String>, + #[serde(default)] + pub log_filter: Option<String>, +} diff --git a/fun/paroxysm/src/keyword.rs b/fun/paroxysm/src/keyword.rs new file mode 100644 index 000000000000..fa40f5347a75 --- /dev/null +++ b/fun/paroxysm/src/keyword.rs @@ -0,0 +1,219 @@ +use crate::models::{Entry, Keyword, NewEntry, NewKeyword}; +use diesel::pg::PgConnection; +use diesel::prelude::*; +use failure::{format_err, Error}; +use std::borrow::Cow; + +/// Maximum number of times we'll follow a `see: ` pointer. +const RECURSION_LIMIT: usize = 5; + +pub struct KeywordDetails { + pub keyword: Keyword, + pub entries: Vec<Entry>, +} + +impl KeywordDetails { + pub fn learn(&mut self, nick: &str, text: &str, dbc: &PgConnection) -> Result<usize, Error> { + let now = ::chrono::Utc::now().naive_utc(); + let ins = NewEntry { + keyword_id: self.keyword.id, + idx: (self.entries.len() + 1) as _, + text, + creation_ts: now, + created_by: nick, + }; + let new = { + use crate::schema::entries; + ::diesel::insert_into(entries::table) + .values(ins) + .get_result(dbc)? + }; + self.entries.push(new); + Ok(self.entries.len()) + } + + pub fn process_moves(&mut self, moves: &[(i32, i32)], dbc: &PgConnection) -> Result<(), Error> { + for (oid, new_idx) in moves { + { + use crate::schema::entries::dsl::*; + ::diesel::update(entries.filter(id.eq(oid))) + .set(idx.eq(new_idx)) + .execute(dbc)?; + } + } + self.entries = Self::get_entries(self.keyword.id, dbc)?; + Ok(()) + } + + pub fn swap(&mut self, idx_a: usize, idx_b: usize, dbc: &PgConnection) -> Result<(), Error> { + let mut moves = vec![]; + for ent in self.entries.iter() { + if ent.idx == idx_a as i32 { + moves.push((ent.id, idx_b as i32)); + } + if ent.idx == idx_b as i32 { + moves.push((ent.id, idx_a as i32)); + } + } + if moves.len() != 2 { + Err(format_err!("Invalid swap operation."))?; + } + self.process_moves(&moves, dbc)?; + Ok(()) + } + + pub fn update(&mut self, idx: usize, val: &str, dbc: &PgConnection) -> Result<(), Error> { + let ent = self + .entries + .get_mut(idx.saturating_sub(1)) + .ok_or(format_err!("No such element to update."))?; + { + use crate::schema::entries::dsl::*; + ::diesel::update(entries.filter(id.eq(ent.id))) + .set(text.eq(val)) + .execute(dbc)?; + } + ent.text = val.to_string(); + Ok(()) + } + + pub fn delete(&mut self, idx: usize, dbc: &PgConnection) -> Result<(), Error> { + // step 1: delete the element + { + let ent = self + .entries + .get(idx.saturating_sub(1)) + .ok_or(format_err!("No such element to delete."))?; + { + use crate::schema::entries::dsl::*; + ::diesel::delete(entries.filter(id.eq(ent.id))).execute(dbc)?; + } + } + // step 2: move all the elements in front of it back one + let mut moves = vec![]; + for ent in self.entries.iter() { + if idx > ent.idx as _ { + moves.push((ent.id, ent.idx.saturating_sub(1))); + } + } + self.process_moves(&moves, dbc)?; + Ok(()) + } + + pub fn add_zwsp_to_name(name: &str) -> Option<String> { + let second_index = name.char_indices().nth(1).map(|(i, _)| i)?; + let (start, end) = name.split_at(second_index); + Some(format!("{}{}", start, end)) + } + + pub fn format_entry(&self, idx: usize) -> Option<String> { + self.format_entry_colours(idx, true) + } + + pub fn format_entry_colours(&self, idx: usize, with_colours: bool) -> Option<String> { + if let Some(ent) = self.entries.get(idx.saturating_sub(1)) { + let gen_clr = if self.keyword.chan == "*" && with_colours { + "\x0307" + } else { + "" + }; + let zwsp_name = Self::add_zwsp_to_name(&self.keyword.name) + .unwrap_or_else(|| self.keyword.name.clone()); + Some(format!( + "{}{}{name}{}[{idx}/{total}]{}: {text} {}[{date}]{}", + if with_colours { "\x02" } else { "" }, + gen_clr, + if with_colours { "\x0f\x0315" } else { "" }, + if with_colours { "\x0f" } else { "" }, + if with_colours { "\x0f\x0314" } else { "" }, + if with_colours { "\x0f" } else { "" }, + name = zwsp_name, + idx = idx, + total = self.entries.len(), + text = ent.text, + date = ent.creation_ts.date() + )) + } else { + None + } + } + + pub fn get_or_create(word: &str, c: &str, dbc: &PgConnection) -> Result<Self, Error> { + if let Some(ret) = Self::get(word, c, dbc)? { + Ok(ret) + } else { + Ok(Self::create(word, c, dbc)?) + } + } + + pub fn create(word: &str, c: &str, dbc: &PgConnection) -> Result<Self, Error> { + let val = NewKeyword { + name: word, + chan: c, + }; + let ret: Keyword = { + use crate::schema::keywords; + ::diesel::insert_into(keywords::table) + .values(val) + .get_result(dbc)? + }; + Ok(KeywordDetails { + keyword: ret, + entries: vec![], + }) + } + + fn get_entries(kid: i32, dbc: &PgConnection) -> Result<Vec<Entry>, Error> { + let entries: Vec<Entry> = { + use crate::schema::entries::dsl::*; + entries + .filter(keyword_id.eq(kid)) + .order_by(idx.asc()) + .load(dbc)? + }; + Ok(entries) + } + + fn get_inner<'a, T: Into<Cow<'a, str>>>( + word: T, + c: &str, + dbc: &PgConnection, + recursion_count: usize, + ) -> Result<Option<Self>, Error> { + let word = word.into(); + let keyword: Option<Keyword> = { + use crate::schema::keywords::dsl::*; + keywords + .filter(name.ilike(word).and(chan.eq(c).or(chan.eq("*")))) + .first(dbc) + .optional()? + }; + if let Some(k) = keyword { + let entries = Self::get_entries(k.id, dbc)?; + if let Some(e0) = entries.get(0) { + if e0.text.starts_with("see: ") { + if recursion_count > RECURSION_LIMIT { + // Oh dear. + Err(format_err!("Halt. You're having a bit too much fun."))? + } + let new_word = e0.text.replace("see: ", ""); + return Self::get_inner(new_word, c, dbc, recursion_count + 1); + } + } + Ok(Some(KeywordDetails { + keyword: k, + entries, + })) + } else { + Ok(None) + } + } + + pub fn get<'a, T: Into<Cow<'a, str>>>( + word: T, + c: &str, + dbc: &PgConnection, + ) -> Result<Option<Self>, Error> { + Self::get_inner(word, c, dbc, 0) + } +} diff --git a/fun/paroxysm/src/main.rs b/fun/paroxysm/src/main.rs new file mode 100644 index 000000000000..998d125bf41c --- /dev/null +++ b/fun/paroxysm/src/main.rs @@ -0,0 +1,395 @@ +// TODO(tazjin): Upgrade to a Diesel version with public derive +// macros. +#[macro_use] +extern crate diesel; + +use crate::cfg::Config; +use crate::keyword::KeywordDetails; +use diesel::pg::PgConnection; +use diesel::r2d2::{ConnectionManager, Pool}; +use failure::{format_err, Error}; +use irc::client::prelude::*; +use lazy_static::lazy_static; +use log::{debug, info, warn}; +use rand::rngs::ThreadRng; +use rand::{thread_rng, Rng}; +use regex::{Captures, Regex}; +use std::collections::HashMap; +use std::fmt::Display; + +mod cfg; +mod keyword; +mod models; +mod schema; + +lazy_static! { + static ref LEARN_RE: Regex = + Regex::new(r#"^\?\?(?P<gen>!)?\s*(?P<subj>[^\[:]*):\s*(?P<val>.*)"#).unwrap(); + static ref QUERY_RE: Regex = + Regex::new(r#"^\?\?\s*(?P<subj>[^\[:]*)(?P<idx>\[[^\]]+\])?"#).unwrap(); + static ref QLAST_RE: Regex = Regex::new(r#"^\?\?\s*(?P<subj>[^\[:]*)!"#).unwrap(); + static ref INCREMENT_RE: Regex = + Regex::new(r#"^\?\?(?P<gen>!)?\s*(?P<subj>[^\[:]*)(?P<incrdecr>\+\+|\-\-)"#).unwrap(); + static ref MOVE_RE: Regex = + Regex::new(r#"^\?\?(?P<gen>!)?\s*(?P<subj>[^\[:]*)(?P<idx>\[[^\]]+\])->(?P<new_idx>.*)"#) + .unwrap(); +} + +pub struct App { + client: IrcClient, + pg: Pool<ConnectionManager<PgConnection>>, + rng: ThreadRng, + cfg: Config, + last_msgs: HashMap<String, HashMap<String, String>>, +} + +impl App { + pub fn report_error<T: Display>( + &mut self, + nick: &str, + chan: &str, + msg: T, + ) -> Result<(), Error> { + self.client + .send_notice(nick, format!("[{}] \x0304Error:\x0f {}", chan, msg))?; + Ok(()) + } + + pub fn keyword_from_captures( + &mut self, + learn: &::regex::Captures, + nick: &str, + chan: &str, + ) -> Result<KeywordDetails, Error> { + let db = self.pg.get()?; + debug!("Fetching keyword for captures: {:?}", learn); + let subj = &learn["subj"]; + let learn_chan = if learn.name("gen").is_some() { + "*" + } else { + chan + }; + if !chan.starts_with("#") && learn_chan != "*" { + Err(format_err!("Only general entries may be taught via PM."))?; + } + debug!("Fetching keyword '{}' for chan {}", subj, learn_chan); + let kwd = KeywordDetails::get_or_create(subj, learn_chan, &db)?; + if kwd.keyword.chan == "*" && !self.cfg.admins.contains(nick) { + Err(format_err!( + "Only administrators can create or modify general entries." + ))?; + } + Ok(kwd) + } + + pub fn handle_move( + &mut self, + target: &str, + nick: &str, + chan: &str, + mv: Captures, + ) -> Result<(), Error> { + let db = self.pg.get()?; + let idx = &mv["idx"]; + let idx = match idx[1..(idx.len() - 1)].parse::<usize>() { + Ok(i) => i, + Err(e) => Err(format_err!("Could not parse index: {}", e))?, + }; + let new_idx = match mv["new_idx"].parse::<i32>() { + Ok(i) => i, + Err(e) => Err(format_err!("Could not parse target index: {}", e))?, + }; + let mut kwd = self.keyword_from_captures(&mv, nick, chan)?; + if new_idx < 0 { + kwd.delete(idx, &db)?; + self.client.send_notice( + target, + format!("\x02{}\x0f: Deleted entry {}.", kwd.keyword.name, idx), + )?; + } else { + kwd.swap(idx, new_idx as _, &db)?; + self.client.send_notice( + target, + format!( + "\x02{}\x0f: Swapped entries {} and {}.", + kwd.keyword.name, idx, new_idx + ), + )?; + } + Ok(()) + } + + pub fn handle_learn( + &mut self, + target: &str, + nick: &str, + chan: &str, + learn: Captures, + ) -> Result<(), Error> { + let db = self.pg.get()?; + let val = &learn["val"]; + let mut kwd = self.keyword_from_captures(&learn, nick, chan)?; + let idx = kwd.learn(nick, val, &db)?; + self.client + .send_notice(target, kwd.format_entry(idx).unwrap())?; + Ok(()) + } + + pub fn handle_insert_last_quote( + &mut self, + target: &str, + nick: &str, + chan: &str, + qlast: Captures, + ) -> Result<(), Error> { + let db = self.pg.get()?; + let nick_to_grab = &qlast["subj"].to_ascii_lowercase(); + let mut kwd = self.keyword_from_captures(&qlast, nick, chan)?; + let chan_lastmsgs = self + .last_msgs + .entry(chan.to_string()) + .or_insert(HashMap::new()); + // Use `nick` here, so things like "grfn: see glittershark" work. + let val = if let Some(last) = chan_lastmsgs.get(nick_to_grab) { + if last.starts_with("\x01ACTION ") { + // Yes, this is inefficient, but it's better than writing some hacky CTCP parsing + // code I guess (also, characters are hard, so just blindly slicing + // seems like a bad idea) + format!( + "* {} {}", + nick_to_grab, + last.replace("\x01ACTION ", "").replace("\x01", "") + ) + } else { + format!("<{}> {}", nick_to_grab, last) + } + } else { + Err(format_err!("I dunno what {} said...", kwd.keyword.name))? + }; + let idx = kwd.learn(nick, &val, &db)?; + self.client + .send_notice(target, kwd.format_entry(idx).unwrap())?; + Ok(()) + } + + pub fn handle_increment( + &mut self, + target: &str, + nick: &str, + chan: &str, + icr: Captures, + ) -> Result<(), Error> { + let db = self.pg.get()?; + let mut kwd = self.keyword_from_captures(&icr, nick, chan)?; + let is_incr = &icr["incrdecr"] == "++"; + let now = chrono::Utc::now().naive_utc().date(); + let mut idx = None; + for (i, ent) in kwd.entries.iter().enumerate() { + if ent.creation_ts.date() == now { + if let Ok(val) = ent.text.parse::<i32>() { + let val = if is_incr { val + 1 } else { val - 1 }; + idx = Some((i + 1, val)); + } + } + } + if let Some((i, val)) = idx { + kwd.update(i, &val.to_string(), &db)?; + self.client + .send_notice(target, kwd.format_entry(i).unwrap())?; + } else { + let val = if is_incr { 1 } else { -1 }; + let idx = kwd.learn(nick, &val.to_string(), &db)?; + self.client + .send_notice(target, kwd.format_entry(idx).unwrap())?; + } + Ok(()) + } + + pub fn handle_query( + &mut self, + target: &str, + nick: &str, + chan: &str, + query: Captures, + ) -> Result<(), Error> { + let db = self.pg.get()?; + let subj = &query["subj"]; + let idx = match query.name("idx") { + Some(i) => { + let i = i.as_str(); + match &i[1..(i.len() - 1)] { + "*" => Some(-1), + x => x.parse::<usize>().map(|x| x as i32).ok(), + } + } + None => None, + }; + debug!("Querying {} with idx {:?}", subj, idx); + match KeywordDetails::get(subj, chan, &db)? { + Some(kwd) => { + if let Some(mut idx) = idx { + if idx == -1 { + // 'get all entries' ('*' parses into this) + // step 1: make a blob of all the quotes + let mut data_to_upload = String::new(); + for i in 0..kwd.entries.len() { + data_to_upload + .push_str(&kwd.format_entry_colours(i + 1, false).unwrap()); + data_to_upload.push('\n'); + } + // step 2: attempt to POST it to eta's pastebin + // TODO(eta): make configurable + let response = crimp::Request::put("https://eta.st/lx/upload") + .user_agent("paroxysm/0.0.2 crimp/0.2")? + .header("Linx-Expiry", "7200")? // 2 hours + .body("text/plain", data_to_upload.as_bytes()) + .timeout(std::time::Duration::from_secs(2))? + .send()? + .as_string()?; + // step 3: tell the world about it + if response.status != 200 { + Err(format_err!( + "upload returned {}: {}", + response.status, + response.body + ))? + } + self.client.send_notice( + target, + format!( + "\x02{}\x0f: uploaded {} quotes to \x02\x0311{}\x0f (will expire in \x0224\x0f hours)", + subj, + kwd.entries.len(), + response.body + ) + )?; + } else { + if idx == 0 { + idx = 1; + } + if let Some(ent) = kwd.format_entry(idx as _) { + self.client.send_notice(target, ent)?; + } else { + let pluralised = if kwd.entries.len() == 1 { + "entry" + } else { + "entries" + }; + self.client.send_notice( + target, + format!( + "\x02{}\x0f: only has \x02\x0304{}\x0f {}", + subj, + kwd.entries.len(), + pluralised + ), + )?; + } + } + } else { + let entry = if kwd.entries.len() < 2 { + 1 // because [1, 1) does not a range make + } else { + self.rng.gen_range(1, kwd.entries.len()) + }; + if let Some(ent) = kwd.format_entry(entry) { + self.client.send_notice(target, ent)?; + } else { + self.client + .send_notice(target, format!("\x02{}\x0f: no entries yet", subj))?; + } + } + } + None => { + // If someone just posts "??????????", don't spam the channel with + // an error message (but do allow joke entries to appear if set). + if !subj.chars().all(|c| c == '?' || c == ' ') { + self.client + .send_notice(target, format!("\x02{}\x0f: never heard of it", subj))?; + } + } + } + Ok(()) + } + + pub fn handle_privmsg(&mut self, from: &str, chan: &str, msg: &str) -> Result<(), Error> { + let nick = from.split("!").next().ok_or(format_err!( + "Received PRIVMSG from a source without nickname (failed to split n!u@h)" + ))?; + let target = if chan.starts_with("#") { chan } else { nick }; + debug!("[{}] <{}> {}", chan, nick, msg); + if let Some(learn) = LEARN_RE.captures(msg) { + self.handle_learn(target, nick, chan, learn)?; + } else if let Some(qlast) = QLAST_RE.captures(msg) { + self.handle_insert_last_quote(target, nick, chan, qlast)?; + } else if let Some(mv) = MOVE_RE.captures(msg) { + self.handle_move(target, nick, chan, mv)?; + } else if let Some(icr) = INCREMENT_RE.captures(msg) { + self.handle_increment(target, nick, chan, icr)?; + } else if let Some(query) = QUERY_RE.captures(msg) { + self.handle_query(target, nick, chan, query)?; + } else { + let chan_lastmsgs = self + .last_msgs + .entry(chan.to_string()) + .or_insert(HashMap::new()); + chan_lastmsgs.insert(nick.to_string().to_ascii_lowercase(), msg.to_string()); + } + Ok(()) + } + + pub fn handle_msg(&mut self, m: Message) -> Result<(), Error> { + match m.command { + Command::PRIVMSG(channel, message) => { + if let Some(src) = m.prefix { + if let Err(e) = self.handle_privmsg(&src, &channel, &message) { + warn!("error handling command in {} (src {}): {}", channel, src, e); + if let Some(nick) = src.split("!").next() { + self.report_error(nick, &channel, e)?; + } + } + } + } + Command::INVITE(nick, channel) => { + if self.cfg.admins.contains(&nick) { + info!("Joining {} after admin invite", channel); + self.client.send_join(channel)?; + } + } + _ => {} + } + Ok(()) + } +} + +fn main() -> Result<(), Error> { + println!("[+] loading configuration"); + let default_log_filter = "paroxysm=info".to_string(); + let mut settings = config::Config::default(); + settings.merge(config::Environment::with_prefix("PARX"))?; + let cfg: Config = settings.try_into()?; + let env = env_logger::Env::new() + .default_filter_or(cfg.log_filter.clone().unwrap_or(default_log_filter)); + env_logger::init_from_env(env); + info!("paroxysm starting up"); + info!("connecting to database at {}", cfg.database_url); + let pg = Pool::new(ConnectionManager::new(&cfg.database_url))?; + info!("connecting to IRC using config {}", cfg.irc_config_path); + let client = IrcClient::new(&cfg.irc_config_path)?; + client.identify()?; + let st = client.stream(); + let mut app = App { + client, + pg, + cfg, + rng: thread_rng(), + last_msgs: HashMap::new(), + }; + info!("running!"); + st.for_each_incoming(|m| { + if let Err(e) = app.handle_msg(m) { + warn!("Error processing message: {}", e); + } + })?; + Ok(()) +} diff --git a/fun/paroxysm/src/models.rs b/fun/paroxysm/src/models.rs new file mode 100644 index 000000000000..721efbbb2e61 --- /dev/null +++ b/fun/paroxysm/src/models.rs @@ -0,0 +1,36 @@ +use crate::schema::{entries, keywords}; +use chrono::NaiveDateTime; + +#[derive(Queryable)] +pub struct Keyword { + pub id: i32, + pub name: String, + pub chan: String, +} + +#[derive(Queryable)] +pub struct Entry { + pub id: i32, + pub keyword_id: i32, + pub idx: i32, + pub text: String, + pub creation_ts: NaiveDateTime, + pub created_by: String, +} + +#[derive(Insertable)] +#[table_name = "keywords"] +pub struct NewKeyword<'a> { + pub name: &'a str, + pub chan: &'a str, +} + +#[derive(Insertable)] +#[table_name = "entries"] +pub struct NewEntry<'a> { + pub keyword_id: i32, + pub idx: i32, + pub text: &'a str, + pub creation_ts: NaiveDateTime, + pub created_by: &'a str, +} diff --git a/fun/paroxysm/src/schema.rs b/fun/paroxysm/src/schema.rs new file mode 100644 index 000000000000..ef4044531ee7 --- /dev/null +++ b/fun/paroxysm/src/schema.rs @@ -0,0 +1,18 @@ +table! { + entries (id) { + id -> Int4, + keyword_id -> Int4, + idx -> Int4, + text -> Varchar, + creation_ts -> Timestamp, + created_by -> Varchar, + } +} + +table! { + keywords (id) { + id -> Int4, + name -> Varchar, + chan -> Varchar, + } +} |