Skip to content

Commit

Permalink
feat: add per guild configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
getchoo committed Dec 2, 2023
1 parent e609e50 commit 2278f2e
Show file tree
Hide file tree
Showing 21 changed files with 350 additions and 148 deletions.
3 changes: 1 addition & 2 deletions src/commands/ask.rs → src/commands/general/ask.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::{consts, utils, Context};

use color_eyre::eyre::{Context as _, Result};

/// ask teawie a question!
Expand All @@ -11,7 +10,7 @@ pub async fn ask(
_question: String,
) -> Result<()> {
let resp = utils::random_choice(consts::RESPONSES)
.wrap_err("couldn't choose from random responses!")?;
.wrap_err("Couldn't choose from random responses!")?;

ctx.say(resp).await?;
Ok(())
Expand Down
1 change: 0 additions & 1 deletion src/commands/bing.rs → src/commands/general/bing.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::Context;

use color_eyre::eyre::Result;

/// make sure the wie is alive
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::Context;

use bottomify::bottom;
use color_eyre::eyre::Result;

Expand Down
11 changes: 11 additions & 0 deletions src/commands/general/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
mod ask;
mod bing;
mod convert;
mod random;
mod version;

pub use ask::ask;
pub use bing::bing;
pub use convert::convert;
pub use random::random;
pub use version::version;
1 change: 0 additions & 1 deletion src/commands/random.rs → src/commands/general/random.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::{api, consts, utils, Context};

use color_eyre::eyre::Result;

#[poise::command(slash_command, subcommands("lore", "teawie", "shiggy"))]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::colors::Colors;
use crate::Context;

use color_eyre::eyre::Result;

/// get version info
Expand Down
27 changes: 11 additions & 16 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,23 @@
pub mod ask;
pub mod bing;
pub mod convert;
pub mod copypasta;
pub mod random;
pub mod teawiespam;
pub mod version;

use crate::Data;

use color_eyre::eyre::Report;
use poise::Command;

mod general;
mod moderation;
mod optional;

pub fn to_global_commands() -> Vec<Command<Data, Report>> {
vec![
ask::ask(),
bing::bing(),
convert::convert(),
random::random(),
copypasta::copypasta(),
teawiespam::teawiespam(),
version::version(),
general::ask(),
general::bing(),
general::convert(),
general::random(),
general::version(),
moderation::config(),
]
}

pub fn to_guild_commands() -> Vec<Command<Data, Report>> {
vec![copypasta::copypasta(), teawiespam::teawiespam()]
vec![optional::copypasta(), optional::teawiespam()]
}
139 changes: 139 additions & 0 deletions src/commands/moderation/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
use crate::settings::{Settings, SettingsProperties};
use crate::Context;

use color_eyre::eyre::{eyre, Context as _, ContextCompat, Result};
use log::*;
use poise::serenity_prelude::{GuildChannel, ReactionType};

#[poise::command(
slash_command,
subcommands("set", "get"),
default_member_permissions = "MANAGE_GUILD"
)]
pub async fn config(_ctx: Context<'_>) -> Result<()> {
Ok(())
}

#[poise::command(slash_command, ephemeral, guild_only)]
pub async fn set(
ctx: Context<'_>,
#[channel_types("Text")]
#[description = "Where to redirect pins from channels. If empty (the default), the PinBoard is disabled."]
pinboard_channel: Option<GuildChannel>,
#[channel_types("Text")]
#[description = "A channel that PinBoard will redirect pins from. This will be all channels if empty."]
pinboard_watch: Option<GuildChannel>,
#[channel_types("Text")]
#[description = "Where to post messages that made it to the ReactBoard. If left empty, ReactBoard is disabled."]
reactboard_channel: Option<GuildChannel>,
#[description = "An emoji that will get messages on the ReactBoard. If empty, ReactBoard is disabled."]
reactboard_reaction: Option<String>,
#[description = "Minimum number of reactions a message needs to make it to the ReactBoard (defaults to 5)"]
reactboard_requirement: Option<u64>,
#[description = "Enables 'extra' commands like teawiespam and copypasta. Defaults to false."]
optional_commands_enabled: Option<bool>,
) -> Result<()> {
let redis = &ctx.data().redis;
let gid = ctx.guild_id().unwrap_or_default();
let mut settings = Settings::from_redis(redis, &gid).await?;
let previous_settings = settings.clone();

if let Some(channel) = pinboard_channel {
settings.pinboard_channel = Some(channel.id);
}

if let Some(watch) = pinboard_watch {
if let Some(mut prev) = settings.pinboard_watch {
prev.push(watch.id);
settings.pinboard_watch = Some(prev);
} else {
let new = Vec::from([watch.id]);
debug!("Setting pinboard_watch to {new:#?} for {} in Redis", gid);

settings.pinboard_watch = Some(new);
}
}

if let Some(channel) = reactboard_channel {
debug!(
"Setting reactboard_channel to {channel} for {} in Redis",
gid
);

settings.reactboard_channel = Some(channel.id);
}

if let Some(requirement) = reactboard_requirement {
debug!(
"Setting reactboard_requirement to {requirement} for {} in Redis",
gid
);

settings.reactboard_requirement = Some(requirement);
}

if let Some(reaction) = reactboard_reaction {
let emoji = reaction
.parse::<ReactionType>()
.wrap_err_with(|| format!("Couldn't parse {reaction} as string!"))?;

if let Some(mut prev) = settings.reactboard_reactions {
prev.push(emoji);
settings.reactboard_reactions = Some(prev);
} else {
let new = Vec::from([emoji]);
debug!("Setting pinboard_watch to {new:#?} for {} in Redis", gid);

settings.reactboard_reactions = Some(new);
}
}

if let Some(enabled) = optional_commands_enabled {
debug!(
"Setting optional_commands_enabled to {enabled} for {} in Redis",
gid
);

settings.optional_commands_enabled = enabled;
}

if previous_settings != settings {
settings.save(redis).await?;
ctx.reply("Configuration updated!").await?;
} else {
ctx.reply("No changes made, so i'm not updating anything")
.await?;
}

Ok(())
}

#[poise::command(slash_command, ephemeral, guild_only)]
pub async fn get(
ctx: Context<'_>,
#[description = "The setting you want to get"] setting: SettingsProperties,
) -> Result<()> {
let gid = &ctx
.guild_id()
.wrap_err_with(|| eyre!("Failed to get GuildId from context!"))?;

let settings = Settings::from_redis(&ctx.data().redis, gid).await?;

let value = match setting {
SettingsProperties::GuildId => settings.guild_id.to_string(),
SettingsProperties::PinBoardChannel => format!("{:#?}", settings.pinboard_channel),
SettingsProperties::PinBoardWatch => format!("{:#?}", settings.pinboard_watch),
SettingsProperties::ReactBoardChannel => format!("{:#?}", settings.reactboard_channel),
SettingsProperties::ReactBoardRequirement => {
format!("{:?}", settings.reactboard_requirement)
}
SettingsProperties::ReactBoardReactions => format!("{:?}", settings.reactboard_reactions),
SettingsProperties::OptionalCommandsEnabled => {
settings.optional_commands_enabled.to_string()
}
};

ctx.say(format!("{setting}: {value}")).await?;

Ok(())
}
3 changes: 3 additions & 0 deletions src/commands/moderation/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod config;

pub use config::config;
11 changes: 5 additions & 6 deletions src/commands/copypasta.rs → src/commands/optional/copypasta.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::Context;
use crate::{Context, Settings};

use std::collections::HashMap;

Expand Down Expand Up @@ -66,12 +66,11 @@ pub async fn copypasta(
ctx: Context<'_>,
#[description = "the copypasta you want to send"] copypasta: Copypastas,
) -> Result<()> {
let gid = ctx
.guild_id()
.ok_or_else(|| eyre!("couldnt get guild from message!"))?;
let gid = ctx.guild_id().unwrap_or_default();
let settings = Settings::from_redis(&ctx.data().redis, &gid).await?;

if !ctx.data().settings.is_guild_allowed(gid) {
info!("not running copypasta command in {gid}");
if !settings.optional_commands_enabled {
debug!("Not running copypasta command in {gid} since it's disabled");
return Ok(());
}

Expand Down
5 changes: 5 additions & 0 deletions src/commands/optional/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod copypasta;
mod teawiespam;

pub use copypasta::copypasta;
pub use teawiespam::teawiespam;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::Context;
use crate::{Context, Settings};

use color_eyre::eyre::Result;
use log::*;
Expand All @@ -7,9 +7,10 @@ use log::*;
#[poise::command(slash_command, prefix_command)]
pub async fn teawiespam(ctx: Context<'_>) -> Result<()> {
let gid = ctx.guild_id().unwrap_or_default();
let settings = Settings::from_redis(&ctx.data().redis, &gid).await?;

if !ctx.data().settings.is_guild_allowed(gid) {
info!("not running teawiespam command in {gid}");
if !settings.optional_commands_enabled {
debug!("Not running teawiespam in {gid} since it's disabled");
return Ok(());
}

Expand Down
4 changes: 2 additions & 2 deletions src/handlers/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use poise::FrameworkError;

pub async fn handle(error: poise::FrameworkError<'_, Data, Report>) {
match error {
FrameworkError::Setup { error, .. } => error!("error setting up client! {error:#?}"),
FrameworkError::Setup { error, .. } => error!("Error setting up client!\n{error:#?}"),

FrameworkError::Command { error, ctx } => {
error!("Error in command {}:\n{error:?}", ctx.command().name);
Expand All @@ -30,7 +30,7 @@ pub async fn handle(error: poise::FrameworkError<'_, Data, Report>) {
event: _,
framework: _,
} => {
error!("Error while handling event:\n{error:#?}");
error!("Error while handling event:\n{error:?}");
}

error => {
Expand Down
26 changes: 26 additions & 0 deletions src/handlers/event/guild.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use color_eyre::eyre::Result;
use log::*;
use poise::serenity_prelude::{Guild, UnavailableGuild};

use crate::{Data, Settings};

pub async fn handle_create(guild: &Guild, is_new: &bool, data: &Data) -> Result<()> {
if !is_new && Settings::from_redis(&data.redis, &guild.id).await.is_ok() {
debug!("Not recreating Redis key for {}", guild.id);
return Ok(());
}

info!("Creating new Redis key for {}", guild.id);
Settings::new_redis(&data.redis, &guild.id).await?;
Ok(())
}

pub async fn handle_delete(guild: &UnavailableGuild, data: &Data) -> Result<()> {
let redis = &data.redis;

info!("Deleting redis key for {}", guild.id);
let settings = Settings::from_redis(redis, &guild.id).await?;
settings.delete(redis).await?;

Ok(())
}
31 changes: 16 additions & 15 deletions src/handlers/event/message.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use crate::Settings;
use crate::{consts, Data};
use crate::{consts, Data, Settings};

use color_eyre::eyre::{Report, Result};
use log::info;
use log::*;
use poise::serenity_prelude::{Context, Message};
use poise::FrameworkContext;

Expand All @@ -12,35 +11,37 @@ pub async fn handle(
msg: &Message,
data: &Data,
) -> Result<()> {
if should_echo(framework, msg, &data.settings) {
if should_echo(framework, msg, data).await? {
msg.reply(ctx, &msg.content).await?;
}

Ok(())
}

fn should_echo(
async fn should_echo(
_framework: FrameworkContext<'_, Data, Report>,
msg: &Message,
settings: &Settings,
) -> bool {
let gid = msg.guild_id.unwrap_or_default();
data: &Data,
) -> Result<bool> {
if msg.author.bot && msg.webhook_id.is_none() {
info!("Not repeating another bot");
return false;
debug!("Not repeating another bot");
return Ok(false);
}

if !settings.is_guild_allowed(gid) {
info!("Not echoing in guild {gid}");
return false;
let gid = msg.guild_id.unwrap_or_default();
let settings = Settings::from_redis(&data.redis, &gid).await?;

if !settings.optional_commands_enabled {
debug!("Not echoing in guild {gid}");
return Ok(false);
}

let content = &msg.content;

content == "🗿"
Ok(content == "🗿"
|| consts::TEAMOJIS.contains(&content.as_str())
|| content.to_ascii_lowercase() == "moyai"
|| content
.to_ascii_lowercase()
.contains("twitter's recommendation algorithm")
.contains("twitter's recommendation algorithm"))
}
Loading

0 comments on commit 2278f2e

Please sign in to comment.