262 lines
12 KiB
Rust
262 lines
12 KiB
Rust
use std::{collections::HashMap, env};
|
|
|
|
use poise::serenity_prelude::{
|
|
model::{
|
|
application::interaction::{Interaction, InteractionResponseType},
|
|
channel::Channel,
|
|
},
|
|
utils::shard_id,
|
|
ActionRowComponent, Activity, Context, CreateActionRow, CreateComponents,
|
|
};
|
|
|
|
use crate::{
|
|
cmds::search::SoundPager,
|
|
models::{
|
|
guild_data::{AllowGreet, CtxGuildData},
|
|
join_sound::JoinSoundCtx,
|
|
sound::Sound,
|
|
},
|
|
utils::{join_channel, play_audio, play_from_query},
|
|
Data, Error,
|
|
};
|
|
|
|
pub async fn listener(ctx: &Context, event: &poise::Event<'_>, data: &Data) -> Result<(), Error> {
|
|
match event {
|
|
poise::Event::Ready { .. } => {
|
|
ctx.set_activity(Activity::watching("for /play")).await;
|
|
}
|
|
poise::Event::GuildCreate { guild, is_new, .. } => {
|
|
if *is_new {
|
|
if let Ok(token) = env::var("DISCORDBOTS_TOKEN") {
|
|
let shard_count = ctx.cache.shard_count();
|
|
let current_shard_id = shard_id(guild.id.as_u64().to_owned(), shard_count);
|
|
|
|
let guild_count = ctx
|
|
.cache
|
|
.guilds()
|
|
.iter()
|
|
.filter(|g| {
|
|
shard_id(g.as_u64().to_owned(), shard_count) == current_shard_id
|
|
})
|
|
.count() as u64;
|
|
|
|
let mut hm = HashMap::new();
|
|
hm.insert("server_count", guild_count);
|
|
hm.insert("shard_id", current_shard_id);
|
|
hm.insert("shard_count", shard_count);
|
|
|
|
let response = data
|
|
.http
|
|
.post(
|
|
format!(
|
|
"https://top.gg/api/bots/{}/stats",
|
|
ctx.cache.current_user_id().as_u64()
|
|
)
|
|
.as_str(),
|
|
)
|
|
.header("Authorization", token)
|
|
.json(&hm)
|
|
.send()
|
|
.await;
|
|
|
|
if let Err(res) = response {
|
|
println!("DiscordBots Response: {:?}", res);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
poise::Event::VoiceStateUpdate { old, new, .. } => {
|
|
if let Some(past_state) = old {
|
|
if let (Some(guild_id), None) = (past_state.guild_id, new.channel_id) {
|
|
if let Some(channel_id) = past_state.channel_id {
|
|
if let Some(Channel::Guild(channel)) = channel_id.to_channel_cached(&ctx) {
|
|
if channel.members(&ctx).await.map(|m| m.len()).unwrap_or(0) <= 1 {
|
|
let songbird = songbird::get(ctx).await.unwrap();
|
|
|
|
let _ = songbird.remove(guild_id).await;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if let (Some(guild_id), Some(user_channel)) = (new.guild_id, new.channel_id) {
|
|
if let Some(guild) = ctx.cache.guild(guild_id) {
|
|
let guild_data_opt = data.guild_data(guild.id).await;
|
|
|
|
if let Ok(guild_data) = guild_data_opt {
|
|
let volume;
|
|
let allowed_greets;
|
|
|
|
{
|
|
let read = guild_data.read().await;
|
|
|
|
volume = read.volume;
|
|
allowed_greets = read.allow_greets;
|
|
}
|
|
|
|
if allowed_greets != AllowGreet::Disabled {
|
|
if let Some(join_id) = data
|
|
.join_sound(
|
|
new.user_id,
|
|
new.guild_id,
|
|
allowed_greets == AllowGreet::GuildOnly,
|
|
)
|
|
.await
|
|
{
|
|
let mut sound = sqlx::query_as_unchecked!(
|
|
Sound,
|
|
"
|
|
SELECT name, id, public, server_id, uploader_id
|
|
FROM sounds
|
|
WHERE id = ?
|
|
",
|
|
join_id
|
|
)
|
|
.fetch_one(&data.database)
|
|
.await
|
|
.unwrap();
|
|
|
|
let (handler, _) = join_channel(&ctx, guild, user_channel).await;
|
|
|
|
play_audio(
|
|
&mut sound,
|
|
volume,
|
|
&mut handler.lock().await,
|
|
&data.database,
|
|
false,
|
|
)
|
|
.await
|
|
.unwrap();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
poise::Event::InteractionCreate { interaction } => match interaction {
|
|
Interaction::MessageComponent(component) => {
|
|
if let Some(guild_id) = component.guild_id {
|
|
if let Ok(()) = SoundPager::handle_interaction(ctx, &data, component).await {
|
|
} else {
|
|
let mode = component.data.custom_id.as_str();
|
|
match mode {
|
|
"#stop" => {
|
|
component
|
|
.create_interaction_response(ctx, |r| {
|
|
r.kind(InteractionResponseType::DeferredUpdateMessage)
|
|
})
|
|
.await
|
|
.unwrap();
|
|
|
|
let songbird = songbird::get(ctx).await.unwrap();
|
|
let call_opt = songbird.get(guild_id);
|
|
|
|
if let Some(call) = call_opt {
|
|
let mut lock = call.lock().await;
|
|
|
|
lock.stop();
|
|
}
|
|
}
|
|
|
|
"#loop" | "#queue" | "#instant" => {
|
|
component
|
|
.create_interaction_response(ctx, |r| {
|
|
r.kind(InteractionResponseType::UpdateMessage)
|
|
.interaction_response_data(|d| {
|
|
let mut c: CreateComponents = Default::default();
|
|
|
|
for action_row in &component.message.components {
|
|
let mut a: CreateActionRow = Default::default();
|
|
// These are always buttons
|
|
for component in &action_row.components {
|
|
match component {
|
|
ActionRowComponent::Button(button) => {
|
|
a.create_button(|b| {
|
|
if let Some(label) =
|
|
&button.label
|
|
{
|
|
b.label(label);
|
|
}
|
|
if let Some(emoji) =
|
|
&button.emoji
|
|
{
|
|
b.emoji(emoji.clone());
|
|
}
|
|
if let Some(custom_id) =
|
|
&button.custom_id
|
|
{
|
|
if custom_id
|
|
.starts_with('#')
|
|
{
|
|
b.custom_id(custom_id)
|
|
.disabled(
|
|
custom_id
|
|
== "#mode"
|
|
|| custom_id
|
|
== mode,
|
|
);
|
|
} else {
|
|
b.custom_id(format!(
|
|
"{}{}",
|
|
custom_id
|
|
.split('#')
|
|
.next()
|
|
.unwrap(),
|
|
mode
|
|
));
|
|
}
|
|
}
|
|
|
|
b.style(button.style);
|
|
|
|
b
|
|
});
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
|
|
c.add_action_row(a);
|
|
}
|
|
|
|
d.set_components(c)
|
|
})
|
|
})
|
|
.await
|
|
.unwrap();
|
|
}
|
|
|
|
id_mode => {
|
|
component
|
|
.create_interaction_response(ctx, |r| {
|
|
r.kind(InteractionResponseType::DeferredUpdateMessage)
|
|
})
|
|
.await
|
|
.unwrap();
|
|
|
|
let mut it = id_mode.split('#');
|
|
let id = it.next().unwrap();
|
|
let mode = it.next().unwrap_or("instant");
|
|
|
|
play_from_query(
|
|
&ctx,
|
|
&data,
|
|
guild_id.to_guild_cached(&ctx).unwrap(),
|
|
component.user.id,
|
|
None,
|
|
id.split('#').next().unwrap(),
|
|
mode == "loop",
|
|
)
|
|
.await;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_ => {}
|
|
},
|
|
_ => {}
|
|
}
|
|
|
|
Ok(())
|
|
}
|