Compare commits

...

2 Commits

5 changed files with 519 additions and 106 deletions

395
Cargo.lock generated
View File

@@ -8,6 +8,16 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "aead"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
dependencies = [
"crypto-common",
"generic-array",
]
[[package]]
name = "aes"
version = "0.8.4"
@@ -19,6 +29,20 @@ dependencies = [
"cpufeatures",
]
[[package]]
name = "aes-gcm"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1"
dependencies = [
"aead",
"aes",
"cipher",
"ctr",
"ghash",
"subtle",
]
[[package]]
name = "ahash"
version = "0.8.12"
@@ -291,6 +315,25 @@ version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
[[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 = "git+https://github.com/amsam0/audiopus_sys?rev=3955ddb2b7b87e772e1c7bb93b8726a864f8c8f9#3955ddb2b7b87e772e1c7bb93b8726a864f8c8f9"
dependencies = [
"cmake",
"log",
"pkg-config",
]
[[package]]
name = "autocfg"
version = "1.5.0"
@@ -494,6 +537,12 @@ version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e"
[[package]]
name = "bytemuck"
version = "1.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec"
[[package]]
name = "byteorder"
version = "1.5.0"
@@ -597,6 +646,30 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "chacha20"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures",
]
[[package]]
name = "chacha20poly1305"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
dependencies = [
"aead",
"chacha20",
"cipher",
"poly1305",
"zeroize",
]
[[package]]
name = "chrono"
version = "0.4.44"
@@ -618,6 +691,7 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [
"crypto-common",
"inout",
"zeroize",
]
[[package]]
@@ -855,6 +929,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
dependencies = [
"generic-array",
"rand_core 0.6.4",
"typenum",
]
@@ -1200,6 +1275,15 @@ dependencies = [
"serde",
]
[[package]]
name = "encoding_rs"
version = "0.8.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
dependencies = [
"cfg-if",
]
[[package]]
name = "enum-as-inner"
version = "0.6.1"
@@ -1339,6 +1423,7 @@ checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095"
dependencies = [
"futures-core",
"futures-sink",
"nanorand",
"spin",
]
@@ -1576,6 +1661,19 @@ version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "312d2295c7302019c395cfb90dacd00a82a2eabd700429bba9c7a3f38dbbe11b"
[[package]]
name = "generator"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e"
dependencies = [
"cc",
"libc",
"log",
"rustversion",
"windows 0.48.0",
]
[[package]]
name = "generic-array"
version = "0.14.7"
@@ -1622,6 +1720,16 @@ dependencies = [
"prost 0.13.5",
]
[[package]]
name = "ghash"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1"
dependencies = [
"opaque-debug",
"polyval",
]
[[package]]
name = "glob"
version = "0.3.3"
@@ -2399,6 +2507,21 @@ dependencies = [
"value-bag",
]
[[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 = "lru-slab"
version = "0.1.2"
@@ -2679,6 +2802,15 @@ version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084"
[[package]]
name = "nanorand"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
dependencies = [
"getrandom 0.2.16",
]
[[package]]
name = "no-std-compat"
version = "0.2.0"
@@ -2691,6 +2823,12 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65"
[[package]]
name = "nohash-hasher"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
[[package]]
name = "nu-ansi-term"
version = "0.50.3"
@@ -2726,6 +2864,15 @@ dependencies = [
"zeroize",
]
[[package]]
name = "num-complex"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
dependencies = [
"num-traits",
]
[[package]]
name = "num-conv"
version = "0.1.0"
@@ -2762,6 +2909,16 @@ dependencies = [
"libm",
]
[[package]]
name = "num_cpus"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "once_cell"
version = "1.21.3"
@@ -2778,6 +2935,12 @@ version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
[[package]]
name = "opaque-debug"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "opendal"
version = "0.55.0"
@@ -3626,6 +3789,29 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "poly1305"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
dependencies = [
"cpufeatures",
"opaque-debug",
"universal-hash",
]
[[package]]
name = "polyval"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25"
dependencies = [
"cfg-if",
"cpufeatures",
"opaque-debug",
"universal-hash",
]
[[package]]
name = "portable-atomic"
version = "1.13.0"
@@ -3675,6 +3861,15 @@ dependencies = [
"syn 2.0.111",
]
[[package]]
name = "primal-check"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc0d895b311e3af9902528fbb8f928688abbd95872819320517cc24ca6b2bd08"
dependencies = [
"num-integer",
]
[[package]]
name = "proc-macro2"
version = "1.0.104"
@@ -3936,6 +4131,15 @@ dependencies = [
"getrandom 0.3.4",
]
[[package]]
name = "realfft"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f821338fddb99d089116342c46e9f1fbf3828dba077674613e734e01d6ea8677"
dependencies = [
"rustfft",
]
[[package]]
name = "redb"
version = "2.6.3"
@@ -4014,7 +4218,7 @@ dependencies = [
"cfg-if",
"libc",
"rustix",
"windows",
"windows 0.62.2",
]
[[package]]
@@ -4237,6 +4441,17 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "ringbuf"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe47b720588c8702e34b5979cb3271a8b1842c7cb6f57408efa70c779363488c"
dependencies = [
"crossbeam-utils",
"portable-atomic",
"portable-atomic-util",
]
[[package]]
name = "roxmltree"
version = "0.21.1"
@@ -4267,6 +4482,18 @@ dependencies = [
"zeroize",
]
[[package]]
name = "rubato"
version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5258099699851cfd0082aeb645feb9c084d9a5e1f1b8d5372086b989fc5e56a1"
dependencies = [
"num-complex",
"num-integer",
"num-traits",
"realfft",
]
[[package]]
name = "rust-ini"
version = "0.21.3"
@@ -4302,6 +4529,20 @@ dependencies = [
"semver",
]
[[package]]
name = "rustfft"
version = "6.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21db5f9893e91f41798c88680037dba611ca6674703c1a18601b01a72c8adb89"
dependencies = [
"num-complex",
"num-integer",
"num-traits",
"primal-check",
"strength_reduce",
"transpose",
]
[[package]]
name = "rustix"
version = "1.1.3"
@@ -4396,6 +4637,19 @@ version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "rusty_pool"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ed36cdb20de66d89a17ea04b8883fc7a386f2cf877aaedca5005583ce4876ff"
dependencies = [
"crossbeam-channel",
"futures",
"futures-channel",
"futures-executor",
"num_cpus",
]
[[package]]
name = "ryu"
version = "1.0.22"
@@ -4429,6 +4683,12 @@ dependencies = [
"windows-sys 0.61.2",
]
[[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.2.0"
@@ -4509,6 +4769,18 @@ dependencies = [
"serde_derive",
]
[[package]]
name = "serde-aux"
version = "4.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "207f67b28fe90fb596503a9bf0bf1ea5e831e21307658e177c5dfcdfc3ab8a0a"
dependencies = [
"chrono",
"serde",
"serde-value",
"serde_json",
]
[[package]]
name = "serde-value"
version = "0.7.0"
@@ -4645,6 +4917,19 @@ dependencies = [
"url",
]
[[package]]
name = "serenity-voice-model"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "790de0c27162611d3adbb98eb83abc295ecd0d608ad9c36653b3e5f2bd06dc22"
dependencies = [
"bitflags 2.10.0",
"num-traits",
"serde",
"serde_json",
"serde_repr",
]
[[package]]
name = "sha-1"
version = "0.10.1"
@@ -4861,23 +5146,49 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc0f2c269821881c25c6daa6863a611a10c9b40ed9f56e2955793bf06fb0fdfd"
dependencies = [
"aead",
"aes-gcm",
"async-trait",
"audiopus",
"byteorder",
"bytes",
"chacha20poly1305",
"crypto-common",
"dashmap 6.1.0",
"derivative",
"discortp",
"either",
"flume",
"futures",
"nohash-hasher",
"parking_lot 0.12.5",
"pin-project",
"rand 0.9.2",
"reqwest",
"ringbuf",
"rubato",
"rusty_pool",
"serde",
"serde-aux",
"serde_json",
"serenity",
"serenity-voice-model",
"socket2 0.5.10",
"stream_lib",
"streamcatcher",
"symphonia",
"symphonia-core",
"tokio",
"tokio-tungstenite 0.26.2",
"tokio-util",
"tokio-websockets 0.11.4",
"tracing",
"tracing-futures",
"twilight-gateway 0.16.0",
"twilight-model 0.16.0",
"typenum",
"url",
"uuid",
]
[[package]]
@@ -5144,6 +5455,23 @@ dependencies = [
"url",
]
[[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 = "strength_reduce"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82"
[[package]]
name = "stringprep"
version = "0.1.5"
@@ -5213,6 +5541,42 @@ dependencies = [
"thiserror 2.0.17",
]
[[package]]
name = "symphonia"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5773a4c030a19d9bfaa090f49746ff35c75dfddfa700df7a5939d5e076a57039"
dependencies = [
"lazy_static",
"symphonia-core",
"symphonia-metadata",
]
[[package]]
name = "symphonia-core"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea00cc4f79b7f6bb7ff87eddc065a1066f3a43fe1875979056672c9ef948c2af"
dependencies = [
"arrayvec",
"bitflags 1.3.2",
"bytemuck",
"lazy_static",
"log",
]
[[package]]
name = "symphonia-metadata"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36306ff42b9ffe6e5afc99d49e121e0bd62fe79b9db7b9681d48e29fa19e6b16"
dependencies = [
"encoding_rs",
"lazy_static",
"log",
"symphonia-core",
]
[[package]]
name = "syn"
version = "1.0.109"
@@ -5747,6 +6111,16 @@ dependencies = [
"tracing-log",
]
[[package]]
name = "transpose"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e"
dependencies = [
"num-integer",
"strength_reduce",
]
[[package]]
name = "triomphe"
version = "0.1.15"
@@ -6043,6 +6417,16 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "universal-hash"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
dependencies = [
"crypto-common",
"subtle",
]
[[package]]
name = "unsigned-varint"
version = "0.8.0"
@@ -6318,6 +6702,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows"
version = "0.62.2"

View File

@@ -47,9 +47,12 @@ rustls = "0.23"
secrecy = { version = "0.10.3", features = ["serde"] }
snafu = { version = "0.8.9", features = ["futures"] }
songbird = { version = "0.5.0", default-features = false, features = [
"driver",
"gateway",
"receive",
"rustls",
"twilight",
"tws",
] }
tokio = { version = "1.46.0", features = ["rt-multi-thread", "macros"] }
tracing = "0.1.41"
@@ -65,3 +68,6 @@ twilight-http = { version = "0.17", default-features = false, features = [
twilight-model = "0.17"
twilight-util = { version = "0.17", features = ["builder"] }
typed-builder = "0.23.2"
[patch.crates-io]
audiopus_sys = { git = "https://github.com/amsam0/audiopus_sys", rev = "3955ddb2b7b87e772e1c7bb93b8726a864f8c8f9" }

View File

@@ -1,10 +1,12 @@
mod one_to_many;
mod one_to_many_with_data;
mod one_to_one;
mod track_vcs;
mod vc_user;
pub use one_to_many::OneToManyUniqueBTreeMap;
pub use one_to_many_with_data::OneToManyUniqueBTreeMapWithData;
pub use one_to_one::OneToOneBTreeMap;
pub use track_vcs::{VCs, initialize_vcs, update_vcs};
pub use vc_user::{UserInVCData, VoiceStatus};

View File

@@ -1,29 +1,14 @@
use std::{
collections::BTreeMap,
fmt::{Debug, Display},
str::FromStr,
};
use clap::Parser;
use fomo_reducer::{VCs, initialize_vcs, update_vcs};
use opendal::{IntoOperatorUri, Operator, OperatorUri};
use secrecy::{ExposeSecret, SecretString};
use snafu::Snafu;
use std::{fmt::Debug, str::FromStr};
use tracing_subscriber::fmt::format::FmtSpan;
use twilight_gateway::{
Event, EventTypeFlags, Intents, Shard, ShardId, StreamExt, error::ReceiveMessageErrorType,
};
use twilight_model::{
channel::ChannelType,
id::{
Id,
marker::{ChannelMarker, GuildMarker, UserMarker},
},
};
use typed_builder::TypedBuilder;
use vc_notifier::{OneToManyUniqueBTreeMapWithData, UserInVCData, VoiceStatus};
type VCsInServer = OneToManyUniqueBTreeMapWithData<Id<ChannelMarker>, Id<UserMarker>, UserInVCData>;
type VCs = BTreeMap<Id<GuildMarker>, VCsInServer>;
use twilight_model::id::{Id, marker::UserMarker};
#[derive(Clone)]
struct OpendalOperator {
@@ -67,10 +52,17 @@ struct Args {
#[arg(long, env)]
storage: OpendalOperator,
#[arg(long, env)]
bot_owner: Id<UserMarker>,
}
#[derive(Debug, Snafu)]
enum MainError {}
#[snafu::report]
#[tokio::main]
async fn main() {
async fn main() -> Result<(), MainError> {
tracing_subscriber::fmt()
.pretty()
.with_span_events(FmtSpan::NEW | FmtSpan::CLOSE)
@@ -83,6 +75,7 @@ async fn main() {
let Args {
discord_token,
storage,
bot_owner,
} = args;
rustls::crypto::aws_lc_rs::default_provider()
@@ -112,98 +105,15 @@ async fn main() {
next_event = shard.next_event(vc_event_types);
}
}
#[tracing::instrument(skip(discord_client), ret)]
async fn initialize_vcs(discord_client: &twilight_http::Client) -> VCs {
let mut vcs = VCs::default();
if let Ok(guilds_res) = discord_client.current_user_guilds().limit(200).await
&& let Ok(guilds) = guilds_res.model().await
{
for guild in guilds {
if let Ok(guild_members_res) = discord_client.guild_members(guild.id).limit(999).await
&& let Ok(guild_members) = guild_members_res.model().await
{
for member in guild_members {
if let Ok(voice_state_res) = discord_client
.user_voice_state(guild.id, member.user.id)
.await
&& let Ok(voice_state) = voice_state_res.model().await
{
tracing::info!(?member.user.id, ?voice_state);
let voice_status = VoiceStatus::builder()
.self_deafened(voice_state.self_deaf)
.self_muted(voice_state.self_mute)
.server_deafened(voice_state.deaf)
.server_muted(voice_state.mute)
.camming(voice_state.self_video)
.streaming(voice_state.self_stream)
.build();
let user_in_vc_data = voice_status.into();
if let Some(channel_id) = voice_state.channel_id {
vcs.entry(guild.id).or_default().insert(
channel_id,
member.user.id,
user_in_vc_data,
);
}
}
}
}
}
}
vcs
Ok(())
}
#[tracing::instrument(skip(vcs))]
async fn handle_event(event: Event, vcs: &mut VCs) {
match event {
Event::VoiceStateUpdate(voice_state_update) => {
let user_id = voice_state_update.user_id;
match voice_state_update.guild_id {
Some(guild_id) => match voice_state_update.channel_id {
Some(channel_id) => {
let voice_status = VoiceStatus::builder()
.self_deafened(voice_state_update.self_deaf)
.self_muted(voice_state_update.self_mute)
.server_deafened(voice_state_update.deaf)
.server_muted(voice_state_update.mute)
.camming(voice_state_update.self_video)
.streaming(voice_state_update.self_stream)
.build();
let user_in_vc_data = voice_status.into();
vcs.entry(guild_id).or_default().insert(
channel_id,
user_id,
user_in_vc_data,
);
tracing::info!(
?guild_id,
?channel_id,
?user_id,
"connected or otherwise changed state while connected"
);
}
None => {
if let Some(channel_vcers) = vcs.get_mut(&guild_id) {
channel_vcers.remove_right(&user_id);
}
tracing::info!(?guild_id, ?user_id, "disconnected");
}
},
None => {
tracing::error!("why doesn't this have a guild id attached?!");
}
}
update_vcs(&voice_state_update, vcs);
}
other => {
tracing::warn!(?other, "wasn't expected");

102
src/track_vcs.rs Normal file
View File

@@ -0,0 +1,102 @@
type VCsInServer = OneToManyUniqueBTreeMapWithData<Id<ChannelMarker>, Id<UserMarker>, UserInVCData>;
pub type VCs = BTreeMap<Id<GuildMarker>, VCsInServer>;
use std::collections::BTreeMap;
use twilight_model::{
gateway::payload::incoming::VoiceStateUpdate,
id::{
Id,
marker::{ChannelMarker, GuildMarker, UserMarker},
},
};
use crate::{OneToManyUniqueBTreeMapWithData, UserInVCData, VoiceStatus};
#[tracing::instrument(skip(discord_client), ret)]
pub async fn initialize_vcs(discord_client: &twilight_http::Client) -> VCs {
let mut vcs = VCs::default();
if let Ok(guilds_res) = discord_client.current_user_guilds().limit(200).await
&& let Ok(guilds) = guilds_res.model().await
{
for guild in guilds {
if let Ok(guild_members_res) = discord_client.guild_members(guild.id).limit(999).await
&& let Ok(guild_members) = guild_members_res.model().await
{
for member in guild_members {
if let Ok(voice_state_res) = discord_client
.user_voice_state(guild.id, member.user.id)
.await
&& let Ok(voice_state) = voice_state_res.model().await
{
tracing::info!(?member.user.id, ?voice_state);
let voice_status = VoiceStatus::builder()
.self_deafened(voice_state.self_deaf)
.self_muted(voice_state.self_mute)
.server_deafened(voice_state.deaf)
.server_muted(voice_state.mute)
.camming(voice_state.self_video)
.streaming(voice_state.self_stream)
.build();
let user_in_vc_data = voice_status.into();
if let Some(channel_id) = voice_state.channel_id {
vcs.entry(guild.id).or_default().insert(
channel_id,
member.user.id,
user_in_vc_data,
);
}
}
}
}
}
}
vcs
}
pub fn update_vcs(voice_state_update: &VoiceStateUpdate, vcs: &mut VCs) {
let user_id = voice_state_update.user_id;
match voice_state_update.guild_id {
Some(guild_id) => match voice_state_update.channel_id {
Some(channel_id) => {
let voice_status = VoiceStatus::builder()
.self_deafened(voice_state_update.self_deaf)
.self_muted(voice_state_update.self_mute)
.server_deafened(voice_state_update.deaf)
.server_muted(voice_state_update.mute)
.camming(voice_state_update.self_video)
.streaming(voice_state_update.self_stream)
.build();
let user_in_vc_data = voice_status.into();
vcs.entry(guild_id)
.or_default()
.insert(channel_id, user_id, user_in_vc_data);
tracing::info!(
?guild_id,
?channel_id,
?user_id,
"connected or otherwise changed state while connected"
);
}
None => {
if let Some(channel_vcers) = vcs.get_mut(&guild_id) {
channel_vcers.remove_right(&user_id);
}
tracing::info!(?guild_id, ?user_id, "disconnected");
}
},
None => {
tracing::error!("why doesn't this have a guild id attached?!");
}
}
}