diff --git a/main.rs b/main.rs index 9cc4c61..73120b0 100644 --- a/main.rs +++ b/main.rs @@ -1,11 +1,14 @@ #[cfg(feature = "dotenv")] use dotenvy::dotenv; -use std::{env, error::Error, sync::Arc}; +use std::{env, error::Error, sync::Arc, time::Duration}; use twilight_cache_inmemory::{InMemoryCache, ResourceType}; use twilight_gateway::{Event, Intents, Shard, ShardId}; use twilight_http::Client as HttpClient; use twilight_mention::Mention; -use twilight_model::id::{Id, marker::RoleMarker}; +use twilight_model::id::{ + marker::{ChannelMarker, RoleMarker, UserMarker}, + Id, +}; #[tokio::main] async fn main() -> Result<(), Box> { @@ -25,9 +28,11 @@ async fn main() -> Result<(), Box> { let http = Arc::new(HttpClient::new(token)); // Since we only care about messages, make the cache only process messages. - let cache = InMemoryCache::builder() - .resource_types(ResourceType::MESSAGE) - .build(); + let cache = Arc::new( + InMemoryCache::builder() + .resource_types(ResourceType::VOICE_STATE) + .build(), + ); // Startup the event loop to process each event in the event stream as they // come in. @@ -48,7 +53,7 @@ async fn main() -> Result<(), Box> { cache.update(&event); // Spawn a new task to handle the event - tokio::spawn(handle_event(event, Arc::clone(&http))); + tokio::spawn(handle_event(event, Arc::clone(&http), Arc::clone(&cache))); } Ok(()) @@ -57,26 +62,65 @@ async fn main() -> Result<(), Box> { async fn handle_event( event: Event, http: Arc, + cache: Arc, ) -> Result<(), Box> { match event { - Event::MessageCreate(msg) if msg.content == "!ping" => { - http.create_message(msg.channel_id).content("Pong!")?.await?; - } Event::Ready(_) => { println!("Shard is ready"); } Event::VoiceStateUpdate(state) => { - let voice_channel_id: String = env::var("VOICE_CHANNEL_ID")?; - if state.channel_id.expect("Channel ID not found.").to_string() != voice_channel_id { + let Some(channel_id) = state.channel_id else { + return Ok(()); + }; + let voice_channel_id: Id = + Id::new(env::var("VOICE_CHANNEL_ID")?.parse().unwrap()); + // 指定したチャンネル以外のボイスチャンネルに入ったら何もしない + if channel_id != voice_channel_id { + return Ok(()); + } + // ボイスチャンネルの人数が1人の場合処理を続ける + let member_count = cache + .voice_channel_states(voice_channel_id) + .unwrap() + .count(); + if member_count != 1 { return Ok(()); } - let text_channel_id = Id::new(env::var("TEXT_CHANNEL_ID")?.parse().unwrap()); - let role_id: Id = Id::new(env::var("ROLE_ID")?.parse().unwrap()); - let message: String = format!("{}の皆さん{}は暇です! 誰かカモン〜ヌ!", role_id.mention(), state.user_id.mention()); - http.create_message(text_channel_id).content(&message)?.await?; + + // 10秒後にまだそのユーザーが参加していたらメッセージを送信する + tokio::time::sleep(Duration::from_secs(10)).await; + let Some(guild_id) = state.guild_id else { + return Ok(()); + }; + let Some(current_state) = cache.voice_state(state.0.user_id, guild_id) else { + return Ok(()); + }; + // ユーザーが指定したチャンネルのボイスチャンネルに入ってるか確認 + if current_state.channel_id() != voice_channel_id { + return Ok(()); + }; + + create_join_message(state.0.user_id, http).await?; } _ => {} } Ok(()) } + +async fn create_join_message( + user_id: Id, + http: Arc, +) -> Result<(), Box> { + let text_channel_id: Id = Id::new(env::var("TEXT_CHANNEL_ID")?.parse().unwrap()); + let role_id: Id = Id::new(env::var("ROLE_ID")?.parse().unwrap()); + let message: String = format!( + "{}の皆さん{}は暇です! 誰かカモン〜ヌ!", + role_id.mention(), + user_id.mention() + ); + http.create_message(text_channel_id) + .content(&message)? + .await?; + Ok(()) +}