Add update-role-message command

This commit is contained in:
Natsu Kagami 2021-06-21 17:25:37 +09:00
parent 2feb91ac00
commit 6944ddfe75
Signed by: nki
GPG key ID: 7306B3D3C3AD6E51
2 changed files with 82 additions and 35 deletions

View file

@ -20,7 +20,7 @@ mod roles;
mod votes; mod votes;
use roles::{ use roles::{
ADD_COMMAND, LIST_COMMAND, REMOVE_COMMAND, RMROLEMESSAGE_COMMAND, ROLEMESSAGE_COMMAND, ADD_COMMAND, LIST_COMMAND, REMOVE_COMMAND, RMROLEMESSAGE_COMMAND, ROLEMESSAGE_COMMAND, UPDATEROLEMESSAGE_COMMAND,
TOGGLE_COMMAND, TOGGLE_COMMAND,
}; };
use votes::VOTE_COMMAND; use votes::VOTE_COMMAND;
@ -30,7 +30,7 @@ pub use roles::ReactionWatchers;
#[group] #[group]
#[description = "Community related commands. Usually comes with some sort of delays, since it involves pinging"] #[description = "Community related commands. Usually comes with some sort of delays, since it involves pinging"]
#[only_in("guilds")] #[only_in("guilds")]
#[commands(choose, vote, add, list, remove, toggle, rolemessage, rmrolemessage)] #[commands(choose, vote, add, list, remove, toggle, rolemessage, rmrolemessage, updaterolemessage)]
struct Community; struct Community;
#[command] #[command]

View file

@ -1,13 +1,5 @@
use crate::db::Roles as DB; use crate::db::Roles as DB;
use serenity::{ use serenity::{framework::standard::{macros::command, Args, CommandResult}, model::{channel::{Message, ReactionType}, guild::Role, id::RoleId}, utils::MessageBuilder};
framework::standard::{macros::command, Args, CommandResult},
model::{
channel::{Message, ReactionType},
guild::Role,
id::RoleId,
},
utils::MessageBuilder,
};
use youmubot_prelude::*; use youmubot_prelude::*;
pub use reaction_watcher::Watchers as ReactionWatchers; pub use reaction_watcher::Watchers as ReactionWatchers;
@ -267,7 +259,21 @@ fn role_from_string(role: &str, roles: &std::collections::HashMap<RoleId, Role>)
#[min_args(1)] #[min_args(1)]
#[required_permissions(MANAGE_ROLES)] #[required_permissions(MANAGE_ROLES)]
#[only_in(guilds)] #[only_in(guilds)]
async fn rolemessage(ctx: &Context, m: &Message, mut args: Args) -> CommandResult { async fn rolemessage(ctx: &Context, m: &Message, args: Args) -> CommandResult {
let (title, roles) = match parse(ctx, m, args).await? {
Some(v) => v,
None => return Ok(())
};
let data = ctx.data.read().await;
let guild_id = m.guild_id.unwrap();
data.get::<ReactionWatchers>()
.unwrap()
.add(ctx.clone(), guild_id, m.channel_id, title, roles)
.await?;
Ok(())
}
async fn parse(ctx: &Context, m: &Message, mut args: Args) -> Result<Option<(String, Vec<(crate::db::Role, Role, ReactionType)>)>> {
let title = args.single_quoted::<String>().unwrap(); let title = args.single_quoted::<String>().unwrap();
let data = ctx.data.read().await; let data = ctx.data.read().await;
let guild_id = m.guild_id.unwrap(); let guild_id = m.guild_id.unwrap();
@ -293,7 +299,7 @@ async fn rolemessage(ctx: &Context, m: &Message, mut args: Args) -> CommandResul
None => { None => {
m.reply(&ctx, format!("Role `{}` not found", rolename)) m.reply(&ctx, format!("Role `{}` not found", rolename))
.await?; .await?;
return Ok(()); return Ok(None);
} }
}; };
let role = match assignables.get(&role.id) { let role = match assignables.get(&role.id) {
@ -305,21 +311,59 @@ async fn rolemessage(ctx: &Context, m: &Message, mut args: Args) -> CommandResul
format!("Role `{}` does not have a assignable emote.", rolename), format!("Role `{}` does not have a assignable emote.", rolename),
) )
.await?; .await?;
return Ok(()); return Ok(None);
} }
}, },
None => { None => {
m.reply(&ctx, format!("Role `{}` is not assignable.", rolename)) m.reply(&ctx, format!("Role `{}` is not assignable.", rolename))
.await?; .await?;
return Ok(()); return Ok(None);
} }
}; };
roles.push(role); roles.push(role);
} }
data.get::<ReactionWatchers>() Ok(Some((title, roles)))
}
#[command("updaterolemessage")]
#[description = "Update the role message to use the new list and title. All roles in the list must already be inside the set. Empty = all assignable roles."]
#[usage = "{title}/[role]/[role]/..."]
#[example = "Game Roles/Genshin/osu!"]
#[min_args(1)]
#[required_permissions(MANAGE_ROLES)]
#[only_in(guilds)]
async fn updaterolemessage(ctx: &Context, m: &Message, args: Args) -> CommandResult {
let (title, roles) = match parse(ctx, m, args).await? {
Some(v) => v,
None => return Ok(())
};
let data = ctx.data.read().await;
let guild_id = m.guild_id.unwrap();
let mut message = match &m.referenced_message {
Some(m) => m,
None => {
m.reply(&ctx, "No replied message found.").await?;
return Ok(());
}
}.clone();
if data
.get::<ReactionWatchers>()
.unwrap() .unwrap()
.add(ctx.clone(), guild_id, m.channel_id, title, roles) .remove(ctx, guild_id, message.id)
.await?; .await?
{
data
.get::<ReactionWatchers>()
.unwrap()
.setup(&mut *message, ctx.clone(), guild_id, title, roles).await?;
} else {
m.reply(&ctx, "Message does not come with a reaction handler")
.await
.ok();
}
Ok(()) Ok(())
} }
@ -341,20 +385,19 @@ async fn rmrolemessage(ctx: &Context, m: &Message, _args: Args) -> CommandResult
} }
}; };
if data if !data
.get::<ReactionWatchers>() .get::<ReactionWatchers>()
.unwrap() .unwrap()
.remove(ctx, guild_id, message.id) .remove(ctx, guild_id, message.id)
.await? .await?
{ {
message.delete(&ctx).await.ok();
m.react(&ctx, '👌').await.ok();
} else {
m.reply(&ctx, "Message does not come with a reaction handler") m.reply(&ctx, "Message does not come with a reaction handler")
.await .await
.ok(); .ok();
} }
Ok(()) Ok(())
} }
@ -365,7 +408,7 @@ mod reaction_watcher {
use serenity::{ use serenity::{
collector::ReactionAction, collector::ReactionAction,
model::{ model::{
channel::ReactionType, channel::{Message, ReactionType},
guild::Role as DiscordRole, guild::Role as DiscordRole,
id::{ChannelId, GuildId, MessageId}, id::{ChannelId, GuildId, MessageId},
}, },
@ -412,10 +455,21 @@ mod reaction_watcher {
channel: ChannelId, channel: ChannelId,
title: String, title: String,
roles: Vec<(Role, DiscordRole, ReactionType)>, roles: Vec<(Role, DiscordRole, ReactionType)>,
) -> Result<()> {
let mut msg = channel.send_message(&ctx, |c| c.content("Youmu is setting up the message...")).await?;
self.setup(&mut msg, ctx, guild, title, roles).await
}
pub async fn setup(
&self,
msg: &mut Message,
ctx: Context,
guild: GuildId,
title: String,
roles: Vec<(Role, DiscordRole, ReactionType)>,
) -> Result<()> { ) -> Result<()> {
// Send a message // Send a message
let msg = channel msg.edit(&ctx, |m| {
.send_message(&ctx, |m| {
m.content({ m.content({
let mut builder = serenity::utils::MessageBuilder::new(); let mut builder = serenity::utils::MessageBuilder::new();
builder builder
@ -438,16 +492,9 @@ mod reaction_watcher {
}) })
.await?; .await?;
// Do reactions // Do reactions
roles for (_, _, emoji) in &roles {
.iter() msg.react(&ctx, emoji.clone()).await.ok();
.map(|(_, _, emoji)| { }
msg.react(&ctx, emoji.clone()).map(|r| {
r.ok();
})
})
.collect::<stream::FuturesUnordered<_>>()
.collect::<()>()
.await;
// Store the message into the list. // Store the message into the list.
{ {
let data = ctx.data.read().await; let data = ctx.data.read().await;