diff --git a/.gitignore b/.gitignore index 426b74e..e020a9d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /target /.idea config.toml -stories/ \ No newline at end of file +stories/ +voices/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 2e8cf1e..0cb380f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,16 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array", + "rand_core", +] + [[package]] name = "ahash" version = "0.7.6" @@ -46,6 +56,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + [[package]] name = "async-trait" version = "0.1.58" @@ -84,6 +100,26 @@ dependencies = [ "winapi", ] +[[package]] +name = "audiopus" +version = "0.3.0-rc.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab55eb0e56d7c6de3d59f544e5db122d7725ec33be6a276ee8241f3be6473955" +dependencies = [ + "audiopus_sys", +] + +[[package]] +name = "audiopus_sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62314a1546a2064e033665d658e88c620a62904be945f8147e6b16c3db9f8651" +dependencies = [ + "cmake", + "log", + "pkg-config", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -148,6 +184,12 @@ version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +[[package]] +name = "bytemuck" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaa3a8d9a1ca92e282c96a32d6511b695d7d994d1d102ba85d279f9b2756947f" + [[package]] name = "byteorder" version = "1.4.3" @@ -189,7 +231,7 @@ checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" dependencies = [ "iana-time-zone", "num-integer", - "num-traits", + "num-traits 0.2.15", "serde", "winapi", ] @@ -216,6 +258,15 @@ dependencies = [ "phf_codegen", ] +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + [[package]] name = "clang-sys" version = "1.4.0" @@ -242,6 +293,15 @@ dependencies = [ "vec_map", ] +[[package]] +name = "cmake" +version = "0.1.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db34956e100b30725f2eb215f90d4871051239535632f84fea3bc92722c66b7c" +dependencies = [ + "cc", +] + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -393,6 +453,17 @@ dependencies = [ "serde", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "deunicode" version = "0.4.3" @@ -409,6 +480,16 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "discortp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb66017646a48220b5ea30d63ac18bb5952f647f1a41ed755880895125d26972" +dependencies = [ + "pnet_macros", + "pnet_macros_support", +] + [[package]] name = "dlv-list" version = "0.3.0" @@ -430,6 +511,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enum_primitive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" +dependencies = [ + "num-traits 0.1.43", +] + [[package]] name = "fastrand" version = "1.8.0" @@ -449,6 +539,19 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "flume" +version = "0.10.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "pin-project", + "spin 0.9.4", +] + [[package]] name = "fnv" version = "1.0.7" @@ -491,6 +594,7 @@ dependencies = [ "reqwest", "serde", "serenity", + "songbird", "structopt", "tera", "tokio", @@ -505,6 +609,7 @@ checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" dependencies = [ "futures-channel", "futures-core", + "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -527,12 +632,34 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +[[package]] +name = "futures-executor" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" +[[package]] +name = "futures-macro" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "futures-sink" version = "0.3.25" @@ -554,6 +681,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-io", + "futures-macro", "futures-sink", "futures-task", "memchr", @@ -562,6 +690,19 @@ dependencies = [ "slab", ] +[[package]] +name = "generator" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266041a359dfa931b370ef684cceb84b166beb14f7f0421f4a6a3d0c446d12e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows", +] + [[package]] name = "generic-array" version = "0.14.6" @@ -579,8 +720,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -920,6 +1063,21 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "serde", + "serde_json", + "tracing", + "tracing-subscriber", +] + [[package]] name = "magick_rust" version = "0.17.0" @@ -931,6 +1089,15 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + [[package]] name = "memchr" version = "2.5.0" @@ -980,6 +1147,15 @@ dependencies = [ "windows-sys 0.42.0", ] +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom", +] + [[package]] name = "native-tls" version = "0.2.11" @@ -1021,6 +1197,16 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -1028,7 +1214,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", - "num-traits", + "num-traits 0.2.15", +] + +[[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.15", ] [[package]] @@ -1056,6 +1251,12 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + [[package]] name = "openssl" version = "0.10.42" @@ -1107,7 +1308,7 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" dependencies = [ - "num-traits", + "num-traits 0.2.15", ] [[package]] @@ -1120,6 +1321,12 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "parking_lot" version = "0.12.1" @@ -1253,6 +1460,26 @@ dependencies = [ "uncased", ] +[[package]] +name = "pin-project" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pin-project-lite" version = "0.2.9" @@ -1271,6 +1498,44 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +[[package]] +name = "pnet_base" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25488cd551a753dcaaa6fffc9f69a7610a412dd8954425bf7ffad5f7d1156fb8" + +[[package]] +name = "pnet_macros" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30490e0852e58402b8fae0d39897b08a24f493023a4d6cf56b2e30f31ed57548" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "syn", +] + +[[package]] +name = "pnet_macros_support" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4714e10f30cab023005adce048f2d30dd4ac4f093662abf2220855655ef8f90" +dependencies = [ + "pnet_base", +] + +[[package]] +name = "poly1305" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1369,6 +1634,15 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax", +] + [[package]] name = "regex-syntax" version = "0.6.28" @@ -1437,7 +1711,7 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", + "spin 0.5.2", "untrusted", "web-sys", "winapi", @@ -1491,12 +1765,28 @@ dependencies = [ "base64", ] +[[package]] +name = "rustversion" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" + [[package]] name = "ryu" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +[[package]] +name = "salsa20" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0fbb5f676da676c260ba276a8f43a8dc67cf02d1438423aeb1c677a7212686" +dependencies = [ + "cipher", + "zeroize", +] + [[package]] name = "same-file" version = "1.0.6" @@ -1516,6 +1806,12 @@ dependencies = [ "windows-sys 0.36.1", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.1.0" @@ -1602,6 +1898,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1649,6 +1956,19 @@ dependencies = [ "uwl", ] +[[package]] +name = "serenity-voice-model" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be3aec8849ca2fde1e8a5dfbed96fbd68e9b5f4283fbe277d8694ce811d4952" +dependencies = [ + "bitflags", + "enum_primitive", + "serde", + "serde_json", + "serde_repr", +] + [[package]] name = "sha-1" version = "0.10.0" @@ -1671,12 +1991,30 @@ dependencies = [ "digest", ] +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + [[package]] name = "shlex" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + [[package]] name = "siphasher" version = "0.3.10" @@ -1717,18 +2055,71 @@ dependencies = [ "winapi", ] +[[package]] +name = "songbird" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4c965f6625a2653e0733abfe217679562eb8c4787f000f4f13047541a444217" +dependencies = [ + "async-trait", + "async-tungstenite", + "audiopus", + "byteorder", + "dashmap", + "derivative", + "discortp", + "flume", + "futures", + "parking_lot", + "pin-project", + "rand", + "serde", + "serde_json", + "serenity", + "serenity-voice-model", + "streamcatcher", + "symphonia-core", + "tokio", + "tracing", + "tracing-futures", + "typemap_rev", + "url", + "uuid", + "xsalsa20poly1305", +] + [[package]] name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" +dependencies = [ + "lock_api", +] + [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "streamcatcher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71664755c349abb0758fda6218fb2d2391ca2a73f9302c03b145491db4fcea29" +dependencies = [ + "crossbeam-utils", + "futures-util", + "loom", +] + [[package]] name = "strsim" version = "0.8.0" @@ -1759,6 +2150,25 @@ dependencies = [ "syn", ] +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "symphonia-core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "199a6417cd4115bac79289b64b859358ea050b7add0ceb364dc991f628c5b347" +dependencies = [ + "arrayvec", + "bitflags", + "bytemuck", + "lazy_static", + "log", +] + [[package]] name = "syn" version = "1.0.103" @@ -1908,6 +2318,7 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", + "signal-hook-registry", "socket2", "tokio-macros", "winapi", @@ -2005,6 +2416,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", ] [[package]] @@ -2153,6 +2604,16 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array", + "subtle", +] + [[package]] name = "untrusted" version = "0.7.1" @@ -2177,12 +2638,27 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom", +] + [[package]] name = "uwl" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4bf03e0ca70d626ecc4ba6b0763b934b6f2976e8c744088bb3c1d646fbb1ad0" +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "vcpkg" version = "0.2.15" @@ -2365,6 +2841,19 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1c4bd0a50ac6020f65184721f758dba47bb9fbc2133df715ec74a237b26794a" +dependencies = [ + "windows_aarch64_msvc 0.39.0", + "windows_i686_gnu 0.39.0", + "windows_i686_msvc 0.39.0", + "windows_x86_64_gnu 0.39.0", + "windows_x86_64_msvc 0.39.0", +] + [[package]] name = "windows-sys" version = "0.36.1" @@ -2405,6 +2894,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2" + [[package]] name = "windows_aarch64_msvc" version = "0.42.0" @@ -2417,6 +2912,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_gnu" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b" + [[package]] name = "windows_i686_gnu" version = "0.42.0" @@ -2429,6 +2930,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_i686_msvc" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106" + [[package]] name = "windows_i686_msvc" version = "0.42.0" @@ -2441,6 +2948,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65" + [[package]] name = "windows_x86_64_gnu" version = "0.42.0" @@ -2459,6 +2972,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "windows_x86_64_msvc" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809" + [[package]] name = "windows_x86_64_msvc" version = "0.42.0" @@ -2474,6 +2993,20 @@ dependencies = [ "winapi", ] +[[package]] +name = "xsalsa20poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e68bcb965d6c650091450b95cea12f07dcd299a01c15e2f9433b0813ea3c0886" +dependencies = [ + "aead", + "poly1305", + "rand_core", + "salsa20", + "subtle", + "zeroize", +] + [[package]] name = "yaml-rust" version = "0.4.5" @@ -2482,3 +3015,9 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "zeroize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" diff --git a/Cargo.toml b/Cargo.toml index 32c1710..09e8068 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ tera = "1.17.1" ndm = "0.9.9" regex = "1.7.0" magick_rust = "0.17.0" +songbird = "0.3.0" [dependencies.serenity] version = "0.11.5" diff --git a/src/config.rs b/src/config.rs index 0844aa6..79f0dc4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -47,6 +47,7 @@ pub struct BotConfig { pub bot_token: String, pub imgur_client_id: String, pub story_path: PathBuf, + pub voice_path: PathBuf, #[serde(default)] pub albums: Vec, diff --git a/src/discord/mod.rs b/src/discord/mod.rs index e5127d0..8ae835e 100644 --- a/src/discord/mod.rs +++ b/src/discord/mod.rs @@ -5,8 +5,9 @@ pub mod color; pub mod emoji_race; pub mod fren_coin; pub mod joke; -pub(crate) mod motivate; +pub mod motivate; pub mod story; +pub mod voices; use crate::discord::fren_coin::give_coin; use crate::discord::joke::random; diff --git a/src/discord/voices.rs b/src/discord/voices.rs new file mode 100644 index 0000000..99d8ef7 --- /dev/null +++ b/src/discord/voices.rs @@ -0,0 +1,250 @@ +use crate::{command, group, GlobalData}; +use serenity::client::Context; +use serenity::framework::standard::{Args, CommandResult}; +use serenity::model::channel::{AttachmentType, Message}; +use serenity::utils::MessageBuilder; +use songbird::driver::Bitrate; +use songbird::input; +use songbird::input::cached::Compressed; +use std::borrow::Cow; +use std::collections::HashMap; +use std::path::{Path, PathBuf}; + +#[group] +#[commands(say, list_words, list_voices)] +pub struct Voices; + +async fn get_voice_dictionary(path: &Path) -> Result, tokio::io::Error> { + let mut dir = tokio::fs::read_dir(path).await?; + let mut dict = HashMap::new(); + + while let Some(word) = &dir.next_entry().await? { + let word_name = word + .path() + .file_stem() + .unwrap() + .to_str() + .unwrap() + .to_string(); + dict.insert(word_name, word.path()); + } + + Ok(dict) +} + +async fn get_voices(voice_path: &Path) -> Result, tokio::io::Error> { + let mut dir = tokio::fs::read_dir(voice_path).await?; + let mut voices = Vec::new(); + + while let Some(file) = &dir.next_entry().await? { + if file.path().is_dir() { + let voice_name = file + .path() + .file_name() + .unwrap() + .to_str() + .unwrap() + .to_string(); + + voices.push(voice_name) + } + } + + Ok(voices) +} + +async fn find_voice(voice_path: &Path, name: &str) -> Result, tokio::io::Error> { + let mut dir = tokio::fs::read_dir(voice_path).await?; + + while let Some(file) = &dir.next_entry().await? { + if file.path().is_dir() { + let voice_name = file + .path() + .file_name() + .unwrap() + .to_str() + .unwrap() + .to_string(); + + if voice_name.eq_ignore_ascii_case(name) { + return Ok(Some(file.path())); + } + } + } + + Ok(None) +} + +#[command] +#[only_in(guilds)] +#[min_args(1)] +async fn say(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { + let guild = msg.guild(&ctx.cache).unwrap(); + let guild_id = guild.id; + + let data = ctx.data.read().await; + let global_data = data.get::().unwrap(); + + let voice = args.parse::().unwrap(); + + let voice_path = match find_voice(&global_data.cfg.voice_path, &voice).await? { + None => { + msg.reply(&ctx.http, format!("No voice found called '{}'", voice)) + .await?; + return Ok(()); + } + Some(voice_path) => voice_path, + }; + + args.advance(); + + let dict = get_voice_dictionary(&voice_path).await?; + + let mut phrase = Vec::new(); + while let Some(word) = &args.current() { + let mut add_period = false; + let mut add_comma = false; + let word = if word.ends_with(',') { + add_comma = true; + word.replace(',', "") + } else if word.ends_with('.') { + add_period = true; + word.replace('.', "") + } else { + word.to_string() + }; + + if dict.contains_key(&word) { + phrase.push(word.to_string()); + } else { + msg.reply( + &ctx.http, + format!("The word '{}' is not in the dictionary", word), + ) + .await?; + return Ok(()); + } + + if add_comma { + phrase.push("_comma".to_string()); + } + + if add_period { + phrase.push("_period".to_string()); + } + + args.advance(); + } + + let channel_id = guild + .voice_states + .get(&msg.author.id) + .and_then(|voice_state| voice_state.channel_id); + + let connect_to = match channel_id { + Some(channel) => channel, + None => { + msg.reply(ctx, "You are not in a voice channel").await?; + + return Ok(()); + } + }; + + let manager = songbird::get(ctx) + .await + .expect("Songbird not initialized") + .clone(); + + let (handler_lock, success_reader) = manager.join(guild_id, connect_to).await; + + success_reader?; + + let mut handler = handler_lock.lock().await; + + for word in phrase { + let word_path = dict.get(&word).unwrap(); + + let audio_src = Compressed::new( + input::ffmpeg(word_path.to_str().unwrap()) + .await + .expect("Bad audio link."), + Bitrate::BitsPerSecond(128_000), + ) + .expect("Bad params on message load"); + let _ = audio_src.raw.spawn_loader(); + + let duration = audio_src.metadata.duration.unwrap(); + let voice = handler.play_source(audio_src.into()); + voice.set_volume(0.5)?; + + tokio::time::sleep(duration).await; + } + + handler.leave().await?; + + Ok(()) +} + +#[command] +#[only_in(guilds)] +#[min_args(1)] +async fn list_words(ctx: &Context, msg: &Message, args: Args) -> CommandResult { + let data = ctx.data.read().await; + let global_data = data.get::().unwrap(); + + let voice = args.parse::().unwrap(); + + match find_voice(&global_data.cfg.voice_path, &voice).await? { + None => { + msg.reply(&ctx.http, format!("No voice found called '{}'", voice)) + .await?; + } + Some(voice_path) => { + let dict = get_voice_dictionary(&voice_path).await?; + let mut words: Vec = dict.keys().cloned().collect(); + + words.sort(); + + let mut list_msg = MessageBuilder::new(); + list_msg.push_line(format!("Here are the words for {}:", voice)); + + for word in words { + list_msg.push("* "); + list_msg.push_line(word); + } + + let file_data = list_msg.build(); + let file_data = file_data.as_bytes(); + let file_data = Cow::from(file_data); + + msg.channel_id + .send_message(&ctx.http, |m| { + m.add_file(AttachmentType::Bytes { + data: file_data, + filename: "words.txt".to_string(), + }) + }) + .await?; + } + }; + + Ok(()) +} + +#[command] +#[only_in(guilds)] +async fn list_voices(ctx: &Context, msg: &Message, _args: Args) -> CommandResult { + let data = ctx.data.read().await; + let global_data = data.get::().unwrap(); + + let mut voice_message = MessageBuilder::new(); + + for voice in get_voices(&global_data.cfg.voice_path).await? { + voice_message.push("* "); + voice_message.push_line(voice); + } + + msg.reply(&ctx.http, voice_message.build()).await?; + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index 92d98b7..b4eaf9c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,7 @@ use magick_rust::magick_wand_genesis; use serenity::framework::standard::macros::{command, group, help, hook}; use serenity::framework::standard::StandardFramework; use serenity::prelude::*; +use songbird::SerenityInit; use std::sync::Once; use structopt::StructOpt; @@ -54,6 +55,7 @@ async fn main() { .group(&discord::fren_coin::FRENCOIN_GROUP) .group(&discord::emoji_race::EMOJIRACE_GROUP) .group(&discord::motivate::MOTIVATE_GROUP) + .group(&discord::voices::VOICES_GROUP) .unrecognised_command(unrecognised_command_hook) .bucket("bad_apple", |b| b.delay(60 * 10)) .await @@ -66,6 +68,7 @@ async fn main() { let intents = GatewayIntents::all(); let mut client = Client::builder(&global_data.cfg.bot_token, intents) .framework(framework) + .register_songbird() .type_map_insert::(global_data) .type_map_insert::>(story_channel) .type_map_insert::>(race_channel)