Compare commits
1 Commits
main
...
4f8f16ee77
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f8f16ee77 |
151
src/main.rs
151
src/main.rs
@@ -1,6 +1,6 @@
|
||||
use std::{io, path::Path, time::Duration};
|
||||
use std::{future::Future, io, path::Path};
|
||||
|
||||
use ::serenity::all::{ChannelId, EditMessage, GuildId, Mentionable, UserId};
|
||||
use ::serenity::all::{ChannelId, EditMember, GuildId, UserId};
|
||||
use eyre::{Context as _, Error, OptionExt, Result};
|
||||
use futures::{FutureExt, StreamExt, TryStreamExt};
|
||||
use poise::serenity_prelude as serenity;
|
||||
@@ -107,21 +107,19 @@ async fn channel_children(
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
async fn move_users<'a>(
|
||||
fn move_users<'a>(
|
||||
ctx: Context<'a>,
|
||||
guild: GuildId,
|
||||
users: Vec<(ChannelId, UserId)>,
|
||||
) -> Result<()> {
|
||||
futures::stream::iter(users.into_iter())
|
||||
.map(Ok::<_, eyre::Error>)
|
||||
.try_for_each_concurrent(10, move |(channel, user)| async move {
|
||||
) -> impl Future<Output = Result<()>> + Send + 'a {
|
||||
futures::stream::iter(users.into_iter().map(move |(channel, user)| async move {
|
||||
tracing::info!(?channel, ?user, "Moving user");
|
||||
guild.move_member(ctx, user, channel).await?;
|
||||
tracing::info!(?channel, ?user, "Moved user");
|
||||
Ok(())
|
||||
})
|
||||
.await?;
|
||||
Ok(())
|
||||
}))
|
||||
.buffer_unordered(10)
|
||||
.try_collect::<()>()
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
@@ -269,88 +267,62 @@ async fn st(ctx: Context<'_>) -> Result<()> {
|
||||
.guild_id()
|
||||
.ok_or_eyre("This bot only works in servers")?;
|
||||
let GuildData { st, .. } = ctx.data().get(guild).await?;
|
||||
let sender = ctx.author().id;
|
||||
|
||||
futures::future::try_join_all(guild.members(&ctx, None, None).await?.into_iter().map(
|
||||
|member| async move {
|
||||
match (sender == member.user.id, member.roles.contains(&st)) {
|
||||
|mut member| async move {
|
||||
match (&member.user == ctx.author(), member.roles.contains(&st)) {
|
||||
(true, true) | (false, false) => Ok(()),
|
||||
(true, false) => member.add_role(&ctx, st).await,
|
||||
(false, true) => member.remove_role(&ctx, st).await,
|
||||
(true, false) => {
|
||||
member
|
||||
.edit(
|
||||
&ctx,
|
||||
EditMember::new().nickname(format!("(ST) {}", member.display_name())),
|
||||
)
|
||||
.await?;
|
||||
member.add_role(&ctx, st).await
|
||||
}
|
||||
(false, true) => {
|
||||
member
|
||||
.edit(
|
||||
&ctx,
|
||||
EditMember::new().nickname(
|
||||
member
|
||||
.display_name()
|
||||
.strip_prefix("(ST) ")
|
||||
.unwrap_or(member.display_name()),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
|
||||
member.remove_role(&ctx, st).await
|
||||
}
|
||||
}
|
||||
},
|
||||
))
|
||||
.await?;
|
||||
|
||||
ctx.reply("You are now the ST").await?;
|
||||
|
||||
ctx.reply("You have been granted ST").await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[poise::command(slash_command, ephemeral)]
|
||||
#[tracing::instrument]
|
||||
async fn spectate(ctx: Context<'_>, player: Option<serenity::UserId>) -> Result<()> {
|
||||
let guild = ctx
|
||||
.guild_id()
|
||||
.ok_or_eyre("This bot only works in servers")?;
|
||||
let GuildData { st, .. } = ctx.data().get(guild).await?;
|
||||
|
||||
let member = guild
|
||||
.member(&ctx, player.unwrap_or(ctx.author().id))
|
||||
.await?;
|
||||
|
||||
let msg = if member.roles.contains(&st) {
|
||||
member.remove_role(&ctx, st).await?;
|
||||
"no longer a spectator"
|
||||
} else {
|
||||
member.add_role(&ctx, st).await?;
|
||||
"now a spectator"
|
||||
};
|
||||
|
||||
ctx.reply(if player.is_some() {
|
||||
format!("{} is {}", member.mention(), msg)
|
||||
} else {
|
||||
format!("You are {}", msg)
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[poise::command(slash_command, ephemeral)]
|
||||
#[tracing::instrument]
|
||||
async fn currently_playing(ctx: Context<'_>, player: Option<serenity::UserId>) -> Result<()> {
|
||||
async fn currently_playing(ctx: Context<'_>, players: Vec<serenity::UserId>) -> Result<()> {
|
||||
let guild = ctx
|
||||
.guild_id()
|
||||
.ok_or_eyre("This bot only works in servers")?;
|
||||
let GuildData {
|
||||
currently_playing, ..
|
||||
} = ctx.data().get(guild).await?;
|
||||
|
||||
let member = guild
|
||||
.member(&ctx, player.unwrap_or(ctx.author().id))
|
||||
for player in &players {
|
||||
guild
|
||||
.member(&ctx, player)
|
||||
.await?
|
||||
.add_role(&ctx, currently_playing)
|
||||
.await?;
|
||||
|
||||
let msg = if member.roles.contains(¤tly_playing) {
|
||||
member.remove_role(&ctx, currently_playing).await?;
|
||||
"no longer"
|
||||
} else {
|
||||
member.add_role(&ctx, currently_playing).await?;
|
||||
"now"
|
||||
};
|
||||
|
||||
ctx.reply(if player.is_some() {
|
||||
format!(
|
||||
"{} is {} {}",
|
||||
member.mention(),
|
||||
msg,
|
||||
currently_playing.mention()
|
||||
)
|
||||
} else {
|
||||
format!("You are {} {}", msg, currently_playing.mention())
|
||||
})
|
||||
}
|
||||
ctx.reply(format!("Given {} members currently playing", players.len()))
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -391,38 +363,16 @@ async fn register_commands(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(ctx))]
|
||||
async fn handle_message(
|
||||
ctx: impl AsRef<serenity::Http>,
|
||||
message: &serenity::Message,
|
||||
) -> Result<()> {
|
||||
tracing::info!("Got message: {}", message.content);
|
||||
if message.content.contains("https://clocktower.live") {
|
||||
let mut message = message.clone();
|
||||
tokio::time::sleep(Duration::from_secs(2)).await;
|
||||
message
|
||||
.edit(&ctx.as_ref(), EditMessage::new().suppress_embeds(true))
|
||||
.await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(ctx, framework))]
|
||||
async fn on_event(
|
||||
ctx: &serenity::Context,
|
||||
event: &serenity::FullEvent,
|
||||
framework: poise::FrameworkContext<'_, Data, Error>,
|
||||
_: &Data,
|
||||
) -> Result<()> {
|
||||
match event {
|
||||
serenity::FullEvent::GuildCreate { guild, is_new: _ } => {
|
||||
register_commands(ctx, framework.options, guild.id).await?
|
||||
}
|
||||
serenity::FullEvent::Message { new_message: msg }
|
||||
| serenity::FullEvent::MessageUpdate { new: Some(msg), .. } => {
|
||||
handle_message(ctx, msg).await?
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if let serenity::FullEvent::GuildCreate { guild, is_new: _ } = event {
|
||||
register_commands(ctx, framework.options, guild.id).await?;
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -446,10 +396,8 @@ async fn main() -> Result<()> {
|
||||
)
|
||||
.wrap_err("A Discord token is required")?;
|
||||
let dbfile = std::env::var_os("DB_FILE").ok_or_eyre("A database file is required")?;
|
||||
let intents = serenity::GatewayIntents::non_privileged()
|
||||
| serenity::GatewayIntents::GUILD_MEMBERS
|
||||
| serenity::GatewayIntents::GUILD_MESSAGES
|
||||
| serenity::GatewayIntents::MESSAGE_CONTENT;
|
||||
let intents =
|
||||
serenity::GatewayIntents::non_privileged() | serenity::GatewayIntents::GUILD_MEMBERS;
|
||||
|
||||
let framework = poise::Framework::builder()
|
||||
.options(poise::FrameworkOptions {
|
||||
@@ -457,7 +405,6 @@ async fn main() -> Result<()> {
|
||||
dusk(),
|
||||
dawn(),
|
||||
st(),
|
||||
spectate(),
|
||||
currently_playing(),
|
||||
join(),
|
||||
configure(),
|
||||
|
||||
Reference in New Issue
Block a user