Compare commits

..

1 commit

Author SHA1 Message Date
gallant f0ee4d6a5e conditional 2023-01-31 12:19:15 -06:00
7 changed files with 408 additions and 376 deletions

358
Cargo.lock generated
View file

@ -19,28 +19,35 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.71"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
[[package]]
name = "arrayvec"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
dependencies = [
"serde",
]
checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704"
[[package]]
name = "async-trait"
version = "0.1.68"
version = "0.1.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.22",
"syn",
]
[[package]]
name = "async-tungstenite"
version = "0.17.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1b71b31561643aa8e7df3effe284fa83ab1a840e52294c5f4bd7bfd8b2becbb"
dependencies = [
"futures-io",
"futures-util",
"log",
"native-tls",
"pin-project-lite",
"tokio",
"tokio-native-tls",
"tungstenite",
]
[[package]]
@ -55,12 +62,6 @@ version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]]
name = "base64"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
[[package]]
name = "bit-set"
version = "0.5.2"
@ -114,6 +115,9 @@ name = "cc"
version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
dependencies = [
"jobserver",
]
[[package]]
name = "cfg-if"
@ -193,9 +197,9 @@ dependencies = [
[[package]]
name = "digest"
version = "0.10.7"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
dependencies = [
"block-buffer",
"crypto-common",
@ -301,6 +305,26 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "enum-iterator"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45a0ac4aeb3a18f92eaf09c6bb9b3ac30ff61ca95514fc58cbead1c9a6bf5401"
dependencies = [
"enum-iterator-derive",
]
[[package]]
name = "enum-iterator-derive"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b13f1e69590421890f90448c3cd5f554746a31adc6dc0dac406ec6901db8dc25"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "fancy-regex"
version = "0.10.0"
@ -419,15 +443,6 @@ dependencies = [
"slab",
]
[[package]]
name = "fxhash"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
dependencies = [
"byteorder",
]
[[package]]
name = "generic-array"
version = "0.14.4"
@ -458,6 +473,31 @@ dependencies = [
"wasi 0.10.0+wasi-snapshot-preview1",
]
[[package]]
name = "getset"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9"
dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "git2"
version = "0.13.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29229cc1b24c0e6062f6e742aa3e256492a5323365e5ed3413599f8a5eff7d6"
dependencies = [
"bitflags",
"libc",
"libgit2-sys",
"log",
"url",
]
[[package]]
name = "h2"
version = "0.3.9"
@ -654,6 +694,15 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
[[package]]
name = "jobserver"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa"
dependencies = [
"libc",
]
[[package]]
name = "js-sys"
version = "0.3.55"
@ -675,6 +724,30 @@ version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
[[package]]
name = "libgit2-sys"
version = "0.12.26+1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19e1c899248e606fbfe68dcb31d8b0176ebab833b103824af31bddf4b7457494"
dependencies = [
"cc",
"libc",
"libz-sys",
"pkg-config",
]
[[package]]
name = "libz-sys"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "lock_api"
version = "0.4.7"
@ -687,9 +760,12 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.19"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]
[[package]]
name = "matches"
@ -789,10 +865,19 @@ dependencies = [
]
[[package]]
name = "once_cell"
version = "1.18.0"
name = "num_threads"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
dependencies = [
"libc",
]
[[package]]
name = "once_cell"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
[[package]]
name = "openssl"
@ -827,6 +912,15 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "ordered-float"
version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87"
dependencies = [
"num-traits",
]
[[package]]
name = "parking_lot"
version = "0.11.2"
@ -898,14 +992,14 @@ checksum = "b95af56fee93df76d721d356ac1ca41fccf168bc448eb14049234df764ba3e76"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.98",
"syn",
]
[[package]]
name = "pin-project-lite"
version = "0.2.9"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
[[package]]
name = "pin-utils"
@ -926,10 +1020,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba"
[[package]]
name = "proc-macro2"
version = "1.0.63"
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
dependencies = [
"unicode-ident",
]
@ -948,9 +1066,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.28"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
dependencies = [
"proc-macro2",
]
@ -1036,7 +1154,7 @@ version = "0.11.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c4e0a76dc12a116108933f6301b95e83634e0c47b0afbed6abbaa0601e99258"
dependencies = [
"base64 0.13.0",
"base64",
"bytes",
"encoding_rs",
"futures-core",
@ -1069,9 +1187,9 @@ dependencies = [
[[package]]
name = "rustversion"
version = "1.0.12"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06"
checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
[[package]]
name = "ryu"
@ -1095,16 +1213,6 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "secrecy"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e"
dependencies = [
"serde",
"zeroize",
]
[[package]]
name = "security-framework"
version = "2.4.2"
@ -1137,6 +1245,16 @@ dependencies = [
"serde_derive",
]
[[package]]
name = "serde-value"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
dependencies = [
"ordered-float",
"serde",
]
[[package]]
name = "serde_derive"
version = "1.0.140"
@ -1145,7 +1263,7 @@ checksum = "6f2122636b9fe3b81f1cb25099fcf2d3f542cdb1d45940d56c713158884a05da"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.98",
"syn",
]
[[package]]
@ -1173,38 +1291,39 @@ dependencies = [
[[package]]
name = "serenity"
version = "0.11.5"
source = "git+https://github.com/serenity-rs/serenity?rev=56867af#56867af31c5144029cf31dc1d563c99a47b38aac"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d1a6cef5e72d4e5787c96413ec0a45f9317c59f0099e2ff2038b73cb352fefd"
dependencies = [
"arrayvec",
"async-trait",
"base64 0.21.2",
"async-tungstenite",
"base64",
"bitflags",
"bytes",
"cfg-if",
"dashmap",
"flate2",
"futures",
"fxhash",
"mime",
"mime_guess",
"parking_lot 0.12.1",
"percent-encoding",
"reqwest",
"secrecy",
"serde",
"serde-value",
"serde_json",
"time 0.3.22",
"time 0.3.11",
"tokio",
"tokio-tungstenite",
"tracing",
"typemap_rev",
"url",
]
[[package]]
name = "sha1"
version = "0.10.5"
name = "sha-1"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
dependencies = [
"cfg-if",
"cpufeatures",
@ -1253,17 +1372,6 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tempfile"
version = "3.2.0"
@ -1295,7 +1403,7 @@ checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.98",
"syn",
]
[[package]]
@ -1311,29 +1419,14 @@ dependencies = [
[[package]]
name = "time"
version = "0.3.22"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd"
checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217"
dependencies = [
"itoa 1.0.1",
"libc",
"num_threads",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
[[package]]
name = "time-macros"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b"
dependencies = [
"time-core",
]
[[package]]
@ -1380,7 +1473,7 @@ checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.98",
"syn",
]
[[package]]
@ -1404,20 +1497,6 @@ dependencies = [
"tokio",
]
[[package]]
name = "tokio-tungstenite"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd"
dependencies = [
"futures-util",
"log",
"native-tls",
"tokio",
"tokio-native-tls",
"tungstenite",
]
[[package]]
name = "tokio-util"
version = "0.6.9"
@ -1449,9 +1528,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
[[package]]
name = "tracing"
version = "0.1.37"
version = "0.1.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105"
dependencies = [
"cfg-if",
"log",
@ -1462,22 +1541,22 @@ dependencies = [
[[package]]
name = "tracing-attributes"
version = "0.1.26"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.22",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.31"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4"
dependencies = [
"once_cell",
"lazy_static",
]
[[package]]
@ -1488,11 +1567,11 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
[[package]]
name = "tungstenite"
version = "0.18.0"
version = "0.17.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788"
checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0"
dependencies = [
"base64 0.13.0",
"base64",
"byteorder",
"bytes",
"http",
@ -1500,7 +1579,7 @@ dependencies = [
"log",
"native-tls",
"rand",
"sha1",
"sha-1",
"thiserror",
"url",
"utf-8",
@ -1508,9 +1587,9 @@ dependencies = [
[[package]]
name = "typemap_rev"
version = "0.3.0"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74b08b0c1257381af16a5c3605254d529d3e7e109f3c62befc5d168968192998"
checksum = "ed5b74f0a24b5454580a79abb6994393b09adf0ab8070f15827cb666255de155"
[[package]]
name = "typenum"
@ -1587,13 +1666,18 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "vergen"
version = "8.2.1"
version = "7.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b3c89c2c7e50f33e4d35527e5bf9c11d6d132226dbbd1753f0fbe9f19ef88c6"
checksum = "f10de320f0fe3f21913dabbfcbced6867bbe47a6b1a5db830e37df3a50279bd0"
dependencies = [
"anyhow",
"cfg-if",
"enum-iterator",
"getset",
"git2",
"rustversion",
"time 0.3.22",
"thiserror",
"time 0.3.11",
]
[[package]]
@ -1645,7 +1729,7 @@ dependencies = [
"log",
"proc-macro2",
"quote",
"syn 1.0.98",
"syn",
"wasm-bindgen-shared",
]
@ -1679,7 +1763,7 @@ checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.98",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@ -1773,9 +1857,3 @@ checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69"
dependencies = [
"winapi",
]
[[package]]
name = "zeroize"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"

View file

@ -21,13 +21,11 @@ version = "1.20.0"
features = ["full"]
[dependencies.serenity]
# version = "0.11.4"
git = "https://github.com/serenity-rs/serenity"
rev = "56867af"
version = "0.11.4"
default-features = false
features = ["builder", "cache", "client", "gateway", "model", "utils", "native_tls_backend"]
[build-dependencies.vergen]
version = "8.2.1"
version = "7.3.1"
default-features = false
features = ["git", "gitcl"]
features = ["git"]

View file

@ -12,3 +12,5 @@ TODO:
- [x] handle multiple pings
- [x] multiple channels
- [x] IRC and Discord formatting
<sub>For extra fun set the DIRCORD_POLARIAN_MODE environmental variable to any value ;)</sub>

View file

@ -1,7 +1,5 @@
use std::error::Error;
use vergen::EmitBuilder;
use vergen::{vergen, Config};
fn main() -> Result<(), Box<dyn Error>> {
EmitBuilder::builder().git_branch().git_sha(true).emit()?;
Ok(())
fn main() {
vergen(Config::default()).unwrap();
}

View file

@ -13,7 +13,7 @@ use serenity::{
channel::{Channel, Message, MessageReference, MessageType},
guild::Member,
id::GuildId,
prelude::{ChannelId, GuildMemberUpdateEvent, Ready, Role, RoleId},
prelude::{ChannelId, Ready, Role, RoleId},
user::User,
},
prelude::*,
@ -64,8 +64,16 @@ impl<'a> StrChunks<'a> {
}
async fn create_prefix(msg: &Message, is_reply: bool, http: impl CacheHttp) -> (String, usize) {
// it's okay to unwrap here since we know we're in a guild
let Ok(nick) = msg.member(http).await.map(|m| m.display_name().to_owned()) else { return ("(reply) ".into(), 400 - "(reply) ".len()) };
let mut nick = match msg.member(http).await {
Ok(Member {
nick: Some(nick), ..
}) => Cow::Owned(nick),
_ => Cow::Borrowed(&msg.author.name),
};
if option_env!("DIRCORD_POLARIAN_MODE").is_some() {
nick = Cow::Owned("polarbear".to_string());
}
let mut chars = nick.char_indices();
let first_char = chars.next().unwrap().1;
@ -116,8 +124,7 @@ impl EventHandler for Handler {
let (prefix, content_limit) = create_prefix(&msg, false, &ctx).await;
let (channel, channel_id) = match mapping.iter().find(|(_, &v)| v == msg.channel_id.0.get())
{
let (channel, channel_id) = match mapping.iter().find(|(_, &v)| v == msg.channel_id.0) {
Some((k, v)) => (k.as_str(), ChannelId::from(*v)),
None => return,
};
@ -137,7 +144,7 @@ impl EventHandler for Handler {
let members_lock = members.lock().await;
let computed = discord_to_irc_processing(&msg.content, &members_lock, &ctx, &roles).await;
let computed = discord_to_irc_processing(&msg.content, &**members_lock, &ctx, &roles).await;
if let Some(MessageReference {
guild_id,
@ -156,7 +163,7 @@ impl EventHandler for Handler {
let atts: Vec<&str> = reply.attachments.iter().map(|a| &*a.url).collect();
content = format!("{} {}", content, atts.join(" "));
content = discord_to_irc_processing(&content, &members_lock, &ctx, &roles).await;
content = discord_to_irc_processing(&content, &**members_lock, &ctx, &roles).await;
let to_send = (&*content).truncate_ellipse(
ref_content_limit
@ -165,14 +172,15 @@ impl EventHandler for Handler {
);
sender
.send_privmsg(channel, format!("{reply_prefix}{to_send}"))
.send_privmsg(channel, format!("{}{}", reply_prefix, to_send))
.unwrap();
}
}
if let Some((stripped, false)) = computed
.strip_prefix(raw_prefix)
.strip_prefix(&raw_prefix)
.map(str::trim)
.and_then(|v| v.strip_suffix('\x0F'))
.map(|v| (v, v.is_empty()))
{
let to_send = stripped.trim_matches('\u{f}');
@ -183,7 +191,7 @@ impl EventHandler for Handler {
for chunk in StrChunks::new(line, content_limit) {
let to_send = chunk.trim_matches('\u{f}');
sender
.send_privmsg(channel, &format!("{prefix}{to_send}"))
.send_privmsg(channel, &format!("{}{}", prefix, to_send))
.unwrap();
}
}
@ -191,7 +199,7 @@ impl EventHandler for Handler {
for attachment in attachments {
sender
.send_privmsg(channel, &format!("{prefix}{attachment}"))
.send_privmsg(channel, &format!("{}{}", prefix, attachment))
.unwrap();
}
}
@ -209,24 +217,16 @@ impl EventHandler for Handler {
members.push(new_member);
}
async fn guild_member_update(
&self,
ctx: Context,
_: Option<Member>,
new: Option<Member>,
_: GuildMemberUpdateEvent,
) {
async fn guild_member_update(&self, ctx: Context, _: Option<Member>, new: Member) {
let ctx_data = ctx.data.read().await;
let mut members = ctx_data.get::<MembersKey>().unwrap().lock().await;
if let Some(new) = new {
let x = members
.iter()
.position(|m| m.user.id == new.user.id)
.unwrap();
members.remove(x);
members.push(new);
}
let x = members
.iter()
.position(|m| m.user.id == new.user.id)
.unwrap();
members.remove(x);
members.push(new);
}
async fn guild_member_removal(
@ -259,11 +259,11 @@ async fn discord_to_irc_processing(
let id = caps[1].parse::<u64>().unwrap();
let display_name = self.members.iter().find_map(|member| {
(id == member.user.id.0.get()).then(|| member.display_name().to_owned())
(id == member.user.id.0).then(|| member.display_name().into_owned())
});
if let Some(display_name) = display_name {
write!(dst, "@{display_name}").unwrap();
write!(dst, "@{}", display_name).unwrap();
} else {
dst.push_str(caps.get(0).unwrap().as_str());
}
@ -273,7 +273,6 @@ async fn discord_to_irc_processing(
regex! {
static PING_RE_1 = r"<@([0-9]+)>";
static PING_RE_2 = r"<@!([0-9]+)>";
static PING_RE_3 = r"\{@([0-9]+)\}";
static EMOJI_RE = r"<:(\w+):[0-9]+>";
static CHANNEL_RE = r"<#([0-9]+)>";
static ROLE_RE = r"<@&([0-9]+)>";
@ -301,6 +300,7 @@ async fn discord_to_irc_processing(
.await
{
Ok(Channel::Guild(gc)) => Cow::Owned(format!("#{}", gc.name)),
Ok(Channel::Category(cat)) => Cow::Owned(format!("#{}", cat.name)),
_ => Cow::Borrowed("#deleted-channel"),
};
@ -318,74 +318,47 @@ async fn discord_to_irc_processing(
)
.into_owned();
// switch brackets of unknown pings
computed = PING_RE_1.replace_all(&computed, "{@$1}").into_owned();
computed = {
#[allow(clippy::enum_glob_use)]
use pulldown_cmark::{Event::*, Tag::*};
let mut new = String::with_capacity(computed.len());
let parser = Parser::new(&computed);
for line in computed.lines() {
let parser = Parser::new(line);
let mut list_level = 0;
let mut numbered = false;
let mut next_num = 0;
let mut computed_line = String::with_capacity(line.len());
for event in parser {
match event {
Text(t) | Html(t) => new.push_str(&t),
Code(t) => write!(new, "`{t}`").unwrap(),
Start(Emphasis) => new.push('\x1D'),
Start(Strong) => new.push('\x02'),
Start(Link(_, _, _)) => {
new.push('[');
}
End(Link(_, url, title)) => {
write!(new, "]: {url}").unwrap();
if !title.is_empty() {
write!(new, " ({title})").unwrap();
for event in parser {
match event {
Text(t) | Html(t) => computed_line.push_str(&t),
Code(t) => write!(computed_line, "`{}`", t).unwrap(),
End(_) => computed_line.push('\x0F'),
Start(Emphasis) => computed_line.push('\x1D'),
Start(Strong) => computed_line.push('\x02'),
Start(Link(_, dest, _)) => {
computed_line.push_str(&dest);
continue;
}
}
Start(List(num)) => {
list_level += 1;
if let Some(num) = num {
numbered = true;
next_num = num;
} else {
numbered = false;
Start(List(num)) => {
if let Some(num) = num {
write!(computed_line, "{}. ", num).unwrap();
} else {
computed_line.push_str("- ");
}
}
Start(BlockQuote) => computed_line.push_str("> "),
_ => {}
}
End(List(_)) => list_level -= 1,
Start(Item) => {
let prefix = if numbered {
format!("{next_num}.")
} else {
if list_level > 1 { '◦' } else { '•' }.into()
};
write!(new, "\n{}{} ", " ".repeat(list_level - 1), prefix).unwrap();
}
End(Item) => {
if numbered {
next_num += 1;
}
}
Start(BlockQuote) => new.push_str("> "),
Start(Heading(ty, _, _)) => {
write!(new, "{} \x02", "#".repeat(ty as usize)).unwrap();
}
SoftBreak | HardBreak | End(Paragraph) => new.push('\n'),
End(_) => new.push('\x0F'),
_ => {}
}
computed_line.push('\n');
new.push_str(&computed_line);
}
new
};
// switch them back
computed = PING_RE_3.replace_all(&computed, "<@$1>").into_owned();
computed
}

View file

@ -1,13 +1,12 @@
use irc::{client::Client as IrcClient, proto::Command};
use std::{collections::HashMap, num::NonZeroU64, sync::Arc, time::Instant};
use std::{collections::HashMap, sync::Arc, time::Instant};
use tokio::sync::{mpsc::unbounded_channel, Mutex};
use tokio_stream::wrappers::UnboundedReceiverStream;
use serenity::{
builder::{EditChannel, ExecuteWebhook},
cache::Cache,
futures::StreamExt,
http::Http,
@ -17,7 +16,7 @@ use serenity::{
prelude::{GuildChannel, Member, UserId},
webhook::Webhook,
},
prelude::Mentionable,
prelude::*,
utils::{content_safe, ContentSafeOptions},
};
@ -90,160 +89,145 @@ pub async fn irc_loop(
let topic = &args[2];
let channel = ChannelId::from(*unwrap_or_continue!(mapping.get(channel)));
let builder = EditChannel::new().topic(topic);
channel.edit(&http, builder).await?;
channel.edit(&http, |c| c.topic(topic)).await?;
}
continue;
};
let nickname = unwrap_or_continue!(orig_message.source_nickname());
let mut nickname = unwrap_or_continue!(orig_message.source_nickname());
match orig_message.command {
Command::PRIVMSG(ref channel, ref message)
| Command::NOTICE(ref channel, ref message) => {
let channel_id = ChannelId::from(*unwrap_or_continue!(mapping.get(channel)));
if option_env!("DIRCORD_POLARIAN_MODE").is_some() {
nickname = "polarbear";
}
if let Command::PRIVMSG(ref channel, ref message) = orig_message.command {
let channel_id = ChannelId::from(*unwrap_or_continue!(mapping.get(channel)));
if channels_cache.is_none() || guild.is_none() || emoji_cache.is_empty() {
let (cc, g, es) = {
let guild = channel_id
.to_channel(&http)
.await?
.guild()
.unwrap()
.guild_id;
if channels_cache.is_none() || guild.is_none() || emoji_cache.is_empty() {
let (cc, g, es) = {
let guild = channel_id
.to_channel(&http)
.await?
.guild()
.unwrap()
.guild_id;
let chans = guild.channels(&http).await?;
let emojis = guild.emojis(&http).await?;
let chans = guild.channels(&http).await?;
let emojis = guild.emojis(&http).await?;
(chans, guild, emojis)
};
channels_cache = Some(cc);
guild = Some(g);
emoji_cache = es;
}
let channels = channels_cache.as_ref().unwrap();
let members_lock = members.lock().await;
let mut computed = irc_to_discord_processing(
message,
&members_lock,
&mut id_cache,
channels,
&emoji_cache,
);
computed = {
let opts = ContentSafeOptions::new()
.clean_role(false)
.clean_user(false)
.clean_channel(false)
.show_discriminator(false)
.clean_here(true) // setting these to true explicitly isn't needed,
.clean_everyone(true); // but i did it anyway for readability
content_safe(&cache, computed, &opts, &[])
(chans, guild, emojis)
};
if let Some(webhook) = webhooks.get(channel) {
let avatar = &*avatar_cache.entry(nickname.to_owned()).or_insert_with(|| {
members_lock.iter().find_map(|member| {
(member.display_name() == nickname)
.then(|| member.user.avatar_url())
.flatten()
})
});
send.send(QueuedMessage::Webhook {
webhook: webhook.clone(),
http: http.clone(),
avatar_url: avatar.clone(),
content: computed,
nickname: nickname.to_string(),
})?;
} else {
send.send(QueuedMessage::Raw {
channel_id,
http: http.clone(),
message: format!("<{nickname}>, {computed}"),
})?;
}
channels_cache = Some(cc);
guild = Some(g);
emoji_cache = es;
}
Command::JOIN(ref channel, _, _) => {
let channel_id = ChannelId::from(*unwrap_or_continue!(mapping.get(channel)));
let users = unwrap_or_continue!(channel_users.get_mut(channel));
let channels = channels_cache.as_ref().unwrap();
users.push(nickname.to_string());
let members_lock = members.lock().await;
let mut computed = irc_to_discord_processing(
message,
&*members_lock,
&mut id_cache,
channels,
&emoji_cache,
);
computed = {
let opts = ContentSafeOptions::new()
.clean_role(false)
.clean_user(false)
.clean_channel(false)
.show_discriminator(false)
.clean_here(true) // setting these to true explicitly isn't needed,
.clean_everyone(true); // but i did it anyway for readability
content_safe(&cache, computed, &opts, &[])
};
if let Some(webhook) = webhooks.get(channel) {
let avatar = &*avatar_cache.entry(nickname.to_owned()).or_insert_with(|| {
members_lock.iter().find_map(|member| {
(*member.display_name() == nickname)
.then(|| member.user.avatar_url())
.flatten()
})
});
send.send(QueuedMessage::Webhook {
webhook: webhook.clone(),
http: http.clone(),
avatar_url: avatar.clone(),
content: computed,
nickname: nickname.to_string(),
})?;
} else {
send.send(QueuedMessage::Raw {
channel_id,
http: http.clone(),
message: format!("*{nickname}* has joined the channel"),
message: format!("<{}>, {}", nickname, computed),
})?;
}
Command::PART(ref channel, ref reason) => {
let users = unwrap_or_continue!(channel_users.get_mut(channel));
} else if let Command::JOIN(ref channel, _, _) = orig_message.command {
let channel_id = ChannelId::from(*unwrap_or_continue!(mapping.get(channel)));
let users = unwrap_or_continue!(channel_users.get_mut(channel));
users.push(nickname.to_string());
send.send(QueuedMessage::Raw {
channel_id,
http: http.clone(),
message: format!("*{}* has joined the channel", nickname),
})?;
} else if let Command::PART(ref channel, ref reason) = orig_message.command {
let users = unwrap_or_continue!(channel_users.get_mut(channel));
let channel_id = ChannelId::from(*unwrap_or_continue!(mapping.get(channel)));
let pos = unwrap_or_continue!(users.iter().position(|u| u == nickname));
users.swap_remove(pos);
let reason = reason.as_deref().unwrap_or("Connection closed");
send.send(QueuedMessage::Raw {
channel_id,
http: http.clone(),
message: format!("*{}* has quit ({})", nickname, reason),
})?;
} else if let Command::QUIT(ref reason) = orig_message.command {
for (channel, users) in &mut channel_users {
let channel_id = ChannelId::from(*unwrap_or_continue!(mapping.get(channel)));
let pos = unwrap_or_continue!(users.iter().position(|u| u == nickname));
users.swap_remove(pos);
let reason = reason.as_deref().unwrap_or("Connection closed");
if reason == "Ping timeout: 2m30s"
{
break;
}
send.send(QueuedMessage::Raw {
channel_id,
http: http.clone(),
message: format!("*{}* has quit ({})", nickname, reason),
})?;
}
} else if let Command::NICK(ref new_nick) = orig_message.command {
for (channel, users) in &mut channel_users {
let channel_id = ChannelId::from(*unwrap_or_continue!(mapping.get(channel)));
let pos = unwrap_or_continue!(users.iter().position(|u| u == nickname));
users[pos] = new_nick.to_string();
send.send(QueuedMessage::Raw {
channel_id,
http: http.clone(),
message: format!("*{nickname}* has quit ({reason})"),
message: format!("*{}* is now known as *{}*", nickname, new_nick),
})?;
}
Command::QUIT(ref reason) => {
for (channel, users) in &mut channel_users {
let channel_id = ChannelId::from(*unwrap_or_continue!(mapping.get(channel)));
let pos = unwrap_or_continue!(users.iter().position(|u| u == nickname));
users.swap_remove(pos);
let reason = reason.as_deref().unwrap_or("Connection closed");
send.send(QueuedMessage::Raw {
channel_id,
http: http.clone(),
message: format!("*{nickname}* has quit ({reason})"),
})?;
}
}
Command::NICK(ref new_nick) => {
for (channel, users) in &mut channel_users {
let channel_id = ChannelId::from(*unwrap_or_continue!(mapping.get(channel)));
let pos = unwrap_or_continue!(users.iter().position(|u| u == nickname));
users[pos] = new_nick.to_string();
send.send(QueuedMessage::Raw {
channel_id,
http: http.clone(),
message: format!("*{nickname}* is now known as *{new_nick}*"),
})?;
}
}
Command::TOPIC(ref channel, ref topic) => {
let topic = unwrap_or_continue!(topic.as_ref());
let channel_id = ChannelId::from(*unwrap_or_continue!(mapping.get(channel)));
let builder = EditChannel::new().topic(topic);
channel_id.edit(&http, builder).await?;
}
Command::KICK(ref channel, ref user, ref reason) => {
let channel_id = ChannelId::from(*unwrap_or_continue!(mapping.get(channel)));
let reason = reason.as_deref().unwrap_or("None");
send.send(QueuedMessage::Raw {
channel_id,
http: http.clone(),
message: format!("*{nickname}* has kicked *{user}* ({reason})"),
})?;
}
_ => {}
} else if let Command::TOPIC(ref channel, ref topic) = orig_message.command {
let topic = unwrap_or_continue!(topic.as_ref());
let channel_id = ChannelId::from(*unwrap_or_continue!(mapping.get(channel)));
channel_id.edit(&http, |c| c.topic(topic)).await?;
}
}
Ok(())
@ -270,12 +254,9 @@ fn irc_to_discord_processing(
.entry(slice.to_owned())
.or_insert_with(|| {
self.members.iter().find_map(|member| {
(slice == member.display_name() || slice == member.user.name.as_str())
.then_some(member.user.id.0.get())
(slice == member.display_name().as_str()).then(|| member.user.id.0)
})
})
.map(NonZeroU64::new)
.flatten()
.map(UserId);
if let Some(id) = id {
@ -288,15 +269,15 @@ fn irc_to_discord_processing(
regex! {
static PING_NICK_1 = r"^([\w+]+)(?::|,)";
static PING_RE_2 = r"(?<=\s|^)@(\w+)";
static PING_RE_2 = r"(?<=\s|^)@([\w\S]+)";
static CONTROL_CHAR_RE = r"\x1f|\x02|\x12|\x0f|\x16|\x03(?:\d{1,2}(?:,\d{1,2})?)?";
static WHITESPACE_RE = r"^\s";
static CHANNEL_RE = r"#([\w-]+)";
static CHANNEL_RE = r"#([A-Za-z-*]+)";
static EMOJI_RE = r":(\w+):";
}
if WHITESPACE_RE.is_match(message).unwrap() && !PING_RE_2.is_match(message).unwrap() {
return format!("`{message}`");
return format!("`{}`", message);
}
let mut computed = message.to_owned();
@ -336,7 +317,7 @@ fn irc_to_discord_processing(
computed = computed
.strip_prefix("\x01ACTION ")
.and_then(|s| s.strip_suffix('\x01'))
.map(|s| format!("*{s}*"))
.map(|s| format!("*{}*", s))
.unwrap_or_else(|| computed); // if any step in the way fails, fall back to using computed
}
@ -402,13 +383,15 @@ async fn msg_task(mut recv: UnboundedReceiverStream<QueuedMessage>) -> anyhow::R
if content.is_empty() {
continue;
}
let mut builder = ExecuteWebhook::new();
if let Some(ref url) = avatar_url {
builder = builder.avatar_url(url);
}
builder = builder.username(nickname).content(content);
webhook
.execute(&http, true, |w| {
if let Some(ref url) = avatar_url {
w.avatar_url(url);
}
webhook.execute(&http, true, builder).await?;
w.username(nickname).content(content)
})
.await?;
}
QueuedMessage::Raw {
channel_id,

View file

@ -114,14 +114,14 @@ async fn main() -> anyhow::Result<()> {
let irc_client = IrcClient::from_config(config).await?;
let http = discord_client.http.clone();
let cache = discord_client.cache.clone();
let http = discord_client.cache_and_http.http.clone();
let cache = discord_client.cache_and_http.cache.clone();
let members = Arc::new(Mutex::new({
let channel_id = ChannelId::from(*conf.channels.iter().next().unwrap().1);
channel_id
.to_channel(discord_client.http.clone())
.to_channel(discord_client.cache_and_http.clone())
.await?
.guild()
.unwrap() // we can panic here because if it's not a guild channel then the bot shouldn't even work
@ -196,6 +196,6 @@ async fn parse_webhook_url(http: Arc<Http>, url: String) -> anyhow::Result<Webho
let split = url.split('/').collect::<Vec<&str>>();
let id = split[0].parse::<u64>()?;
let token = split[1].to_string();
let webhook = http.get_webhook_with_token(id.into(), &token).await?;
let webhook = http.get_webhook_with_token(id, &token).await?;
Ok(webhook)
}