~erk/lasagne-devel

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch

[PATCH] Remove message command support

Details
Message ID
<20220429152651.1833-1-flat@esoteric.moe>
DKIM signature
missing
Download raw message
Patch: +30 -462
Signed-off-by: Ken Swenson <flat@esoteric.moe>
---
 src/comic.rs           |  15 --
 src/command_handler.rs | 347 -----------------------------------------
 src/context.rs         |  20 +--
 src/database.rs        |  27 ++--
 src/main.rs            |  70 +--------
 src/slash_handler.rs   |  11 +-
 src/syndicate.rs       |   2 +-
 7 files changed, 30 insertions(+), 462 deletions(-)
 delete mode 100644 src/command_handler.rs

diff --git a/src/comic.rs b/src/comic.rs
index 8b867b3..3da8adb 100644
--- a/src/comic.rs
+++ b/src/comic.rs
@@ -340,21 +340,6 @@ impl ComicEmbed {
        }
    }

    pub fn add_deprecation_note(mut self, context: &str) -> Self {
        self.embed.footer = Some(EmbedFooter {
            icon_url: None,
            proxy_icon_url: None,
            text: format!(
                "You used the text based version of this \
                 command, which will stop working in April. You should \
                 start to use slash commands. Slash commands can be used by \
                 typing \"{}\".",
                context
            ),
        });
        self
    }

    fn default_embed() -> Embed {
        Embed {
            author: Some(EmbedAuthor {
diff --git a/src/command_handler.rs b/src/command_handler.rs
deleted file mode 100644
index f197962..0000000
--- a/src/command_handler.rs
@@ -1,347 +0,0 @@
#![allow(deprecated)]

use crate::comic::ComicEmbed;
use crate::Context;
use crate::GarfieldResult;
use crate::{ABOUT, HELP, INVITE, OWNER};

use twilight_command_parser::Command;
use twilight_model::channel::message::Message;
use twilight_model::gateway::presence::{Activity, ActivityType};

use tracing::info;

pub async fn handle_command(msg: Message, ctx: Context<'_>) -> GarfieldResult<()> {
    if let Some(command) = ctx.parser.parse(&msg.content) {
        match command {
            Command { name: "today", .. } => {
                info!("Sending TODAY to: {:?}", msg);
                ComicEmbed::new(ctx.db.clone(), ctx.rqc.clone())
                    .today()
                    .await
                    .add_deprecation_note("/today")
                    .send(&ctx.http, msg.channel_id)
                    .await?;
                Ok(())
            }
            Command {
                name: "date",
                arguments,
                ..
            } => {
                info!("Sending DATE to: {:?}", msg);
                let date = arguments.as_str();
                ComicEmbed::new(ctx.db.clone(), ctx.rqc.clone())
                    .date_str(date)
                    .await
                    .add_deprecation_note(&format!("/date {}", date))
                    .send(&ctx.http, msg.channel_id)
                    .await?;
                Ok(())
            }
            Command {
                name: "theme",
                arguments,
                ..
            } => {
                info!("Sending THEME to: {:?}", msg);
                let theme = arguments.as_str();
                let comic = ctx.tc.get_theme(theme).await?;
                comic
                    .add_deprecation_note(&format!("/theme {}", theme))
                    .send(&ctx.http, msg.channel_id)
                    .await?;
                Ok(())
            }
            Command {
                name: "tomorrow", ..
            } => {
                info!("Sending TOMORROW to: {:?}", msg);
                ComicEmbed::new(ctx.db.clone(), ctx.rqc.clone())
                    .tomorrow()
                    .await
                    .add_deprecation_note("/tomorrow")
                    .send(&ctx.http, msg.channel_id)
                    .await?;
                Ok(())
            }
            Command { name: "random", .. } => {
                info!("Sending RANDOM to: {:?}", msg);
                ComicEmbed::new(ctx.db.clone(), ctx.rqc.clone())
                    .random()
                    .await
                    .add_deprecation_note("/random")
                    .send(&ctx.http, msg.channel_id)
                    .await?;
                Ok(())
            }
            Command {
                name: "yesterday", ..
            } => {
                info!("Sending YESTERDAY to: {:?}", msg);
                ComicEmbed::new(ctx.db.clone(), ctx.rqc.clone())
                    .yesterday()
                    .await
                    .add_deprecation_note("/yesterday")
                    .send(&ctx.http, msg.channel_id)
                    .await?;
                Ok(())
            }
            Command { name: "help", .. } => {
                info!("Sending HELP to: {:?}", msg);
                ctx.http
                    .create_message(msg.channel_id)
                    .content(HELP)?
                    .exec()
                    .await?;
                Ok(())
            }
            Command { name: "about", .. } => {
                info!("Sending ABOUT to: {:?}", msg);
                ctx.http
                    .create_message(msg.channel_id)
                    .content(ABOUT)?
                    .exec()
                    .await?;
                Ok(())
            }
            Command {
                name: "status",
                arguments,
                ..
            } => {
                if msg.author.id == OWNER {
                    println!("GETTING SHARD");
                    if let Some(shard) = ctx.cls.shard(0) {
                        use twilight_model::gateway::payload::outgoing::update_presence::UpdatePresence;
                        use twilight_model::gateway::presence::Status::Online;
                        let name = arguments.as_str();
                        let com = UpdatePresence::new(vec![activity(name)], false, None, Online)?;
                        shard.command(&com).await?;
                        ctx.http
                            .create_message(msg.channel_id)
                            .content(&format!("Set status to:\n{}", name))?
                            .exec()
                            .await?;
                    }
                }
                Ok(())
            }
            Command {
                name: "comic_stats",
                ..
            } => {
                let stats_msg = ctx.db.stats()?;
                ctx.http
                    .create_message(msg.channel_id)
                    .content(&stats_msg)?
                    .exec()
                    .await?;
                Ok(())
            }
            Command { name: "invite", .. } => {
                ctx.http
                    .create_message(msg.channel_id)
                    .content(INVITE)?
                    .exec()
                    .await?;
                Ok(())
            }
            /*
            Command { name: "stats", .. } => {
                let users = ctx.cache.closure(|c| c.users.lock().len());
                let members = ctx.cache.closure(|c| c.members.lock().len());
                let guilds = ctx.cache.closure(|c| c.guilds.lock().len());
                let emojis = ctx.cache.closure(|c| c.emojis.lock().len());
                let channels = ctx.cache.closure(|c| c.channels.lock().len());
                let presences = ctx.cache.closure(|c| c.presences.lock().len());

                ctx.http
                    .create_message(msg.channel_id)
                    .content(format!(
                        "Users: {}\n\
                         Members: {}\n\
                         Guilds: {}\n\
                         Emojis: {}\n\
                         Channels: {}\n\
                         Presences: {}",
                        users, members, guilds, emojis, channels, presences
                    ))?
                    .await?;

                Ok(())
            }
            Command {
                name: "user",
                arguments,
                ..
            } => {
                if msg.author.id != OWNER {
                    return Ok(());
                }

                let id = UserId(arguments.as_str().parse::<u64>()?);

                let user = ctx.cache.user(id);

                ctx.http
                    .create_message(msg.channel_id)
                    .content(format!("```\n{:?}\n```", user))?
                    .await?;

                Ok(())
            }
            Command {
                name: "member",
                arguments,
                ..
            } => {
                if msg.author.id != OWNER {
                    return Ok(());
                }
                let args = arguments.collect::<Vec<_>>();
                if args.len() != 2 {
                    return Ok(());
                }

                let gid = GuildId(args[0].parse()?);
                let uid = UserId(args[1].parse()?);

                let member = ctx.cache.member(gid, uid);

                ctx.http
                    .create_message(msg.channel_id)
                    .content(format!("```\n{:?}\n```", member))?
                    .await?;

                Ok(())
            }
            Command {
                name: "guild",
                arguments,
                ..
            } => {
                if msg.author.id != OWNER {
                    return Ok(());
                }

                let id = GuildId(arguments.as_str().parse::<u64>()?);

                let guild = ctx.cache.guild(id);

                ctx.http
                    .create_message(msg.channel_id)
                    .content(format!("```\n{:?}\n```", guild))?
                    .await?;

                Ok(())
            }
            Command {
                name: "role",
                arguments,
                ..
            } => {
                if msg.author.id != OWNER {
                    return Ok(());
                }

                let id = RoleId(arguments.as_str().parse::<u64>()?);

                let role = ctx.cache.role(id);

                ctx.http
                    .create_message(msg.channel_id)
                    .content(format!("```\n{:?}\n```", role))?
                    .await?;

                Ok(())
            }
            Command {
                name: "emoji",
                arguments,
                ..
            } => {
                if msg.author.id != OWNER {
                    return Ok(());
                }

                let id = EmojiId(arguments.as_str().parse::<u64>()?);

                let emoji = ctx.cache.emoji(id);

                ctx.http
                    .create_message(msg.channel_id)
                    .content(format!("```\n{:?}\n```", emoji))?
                    .await?;

                Ok(())
            }
            Command {
                name: "channel",
                arguments,
                ..
            } => {
                if msg.author.id != OWNER {
                    return Ok(());
                }

                let id = ChannelId(arguments.as_str().parse::<u64>()?);

                let channel = ctx.cache.channel(id);

                ctx.http
                    .create_message(msg.channel_id)
                    .content(format!("```\n{:?}\n```", channel))?
                    .await?;

                Ok(())
            }
            Command {
                name: "presence",
                arguments,
                ..
            } => {
                if msg.author.id != OWNER {
                    return Ok(());
                }

                let id = UserId(arguments.as_str().parse::<u64>()?);

                let presence = ctx.cache.presence(id);

                ctx.http
                    .create_message(msg.channel_id)
                    .content(format!("```\n{:?}\n```", presence))?
                    .await?;

                Ok(())
            }
            */
            _ => Ok(()),
        }
    } else {
        // No command
        Ok(())
    }
}

fn activity(name: &str) -> Activity {
    Activity {
        application_id: None,
        assets: None,
        buttons: Vec::new(),
        created_at: None,
        details: None,
        flags: None,
        id: None,
        instance: None,
        kind: ActivityType::Playing,
        name: String::from(name),
        emoji: None,
        party: None,
        secrets: None,
        state: None,
        timestamps: None,
        url: None,
    }
}
diff --git a/src/context.rs b/src/context.rs
index 115f285..ef012d1 100644
--- a/src/context.rs
+++ b/src/context.rs
@@ -3,8 +3,6 @@
use std::{ops::Deref, sync::Arc};

use reqwest::Client as ReqwestClient;
#[allow(deprecated)]
use twilight_command_parser::Parser;
use twilight_gateway::Cluster;
use twilight_http::Client as HttpClient;

@@ -14,20 +12,18 @@ use twilight_model::id::{marker::ApplicationMarker, Id};
use crate::{database::ComicDb2, theme::ThemeClient};

#[derive(Clone)]
pub struct ContextRef<'a> {
pub struct ContextRef {
    pub application_id: Id<ApplicationMarker>,
    pub cls: Arc<Cluster>,
    pub db: ComicDb2,
    pub http: Arc<HttpClient>,
    pub index: Index,
    #[allow(deprecated)]
    pub parser: Parser<'a>,
    pub reader: IndexReader,
    pub rqc: ReqwestClient,
    pub tc: Arc<ThemeClient>,
}

impl<'a> ContextRef<'a> {
impl ContextRef {
    #[allow(clippy::too_many_arguments)]
    fn new(
        application_id: Id<ApplicationMarker>,
@@ -35,7 +31,6 @@ impl<'a> ContextRef<'a> {
        db: ComicDb2,
        http: Arc<HttpClient>,
        index: Index,
        parser: Parser<'a>,
        reader: IndexReader,
        rqc: ReqwestClient,
        tc: ThemeClient,
@@ -47,7 +42,6 @@ impl<'a> ContextRef<'a> {
            db,
            http,
            index,
            parser,
            reader,
            rqc,
            tc,
@@ -60,9 +54,9 @@ impl<'a> ContextRef<'a> {
}

#[derive(Clone)]
pub struct Context<'a>(pub Arc<ContextRef<'a>>);
pub struct Context(pub Arc<ContextRef>);

impl<'a> Context<'a> {
impl Context {
    #[allow(clippy::too_many_arguments)]
    pub fn new(
        application_id: Id<ApplicationMarker>,
@@ -70,7 +64,6 @@ impl<'a> Context<'a> {
        db: ComicDb2,
        http: Arc<HttpClient>,
        index: Index,
        parser: Parser<'a>,
        reader: IndexReader,
        rqc: ReqwestClient,
        tc: ThemeClient,
@@ -81,7 +74,6 @@ impl<'a> Context<'a> {
            db,
            http,
            index,
            parser,
            reader,
            rqc,
            tc,
@@ -89,8 +81,8 @@ impl<'a> Context<'a> {
    }
}

impl<'a> Deref for Context<'a> {
    type Target = ContextRef<'a>;
impl Deref for Context {
    type Target = ContextRef;

    fn deref(&self) -> &Self::Target {
        &self.0
diff --git a/src/database.rs b/src/database.rs
index fdde368..9e6cea7 100644
--- a/src/database.rs
+++ b/src/database.rs
@@ -88,17 +88,18 @@ impl ComicDb2 {
        Ok(())
    }

    pub fn stats(&self) -> GarfieldResult<String> {
        let rtxn = self
            .env
            .read_txn()
            .map_err(|err| DbError(err.to_string()))?;
        let uniqs = self
            .comic_db
            .len(&rtxn)
            .map_err(|err| DbError(err.to_string()))?;
        let ret = format!("There is a total of {} unique comic urls in the db", uniqs);
        rtxn.commit().map_err(|err| DbError(err.to_string()))?;
        Ok(ret)
    }
    // Currently unused
    // pub fn stats(&self) -> GarfieldResult<String> {
    //     let rtxn = self
    //         .env
    //         .read_txn()
    //         .map_err(|err| DbError(err.to_string()))?;
    //     let uniqs = self
    //         .comic_db
    //         .len(&rtxn)
    //         .map_err(|err| DbError(err.to_string()))?;
    //     let ret = format!("There is a total of {} unique comic urls in the db", uniqs);
    //     rtxn.commit().map_err(|err| DbError(err.to_string()))?;
    //     Ok(ret)
    // }
}
diff --git a/src/main.rs b/src/main.rs
index 53e6e0a..b03a455 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,18 +3,14 @@ use std::error::Error;
use std::sync::Arc;

use tantivy::Index;
#[allow(deprecated)]
use twilight_command_parser::{CommandParserConfig, Parser};
//use twilight::gateway::shard::Event;
use twilight_http::Client as HttpClient;
use twilight_model::gateway::event::Event;
use twilight_model::id::*;

use twilight_gateway::cluster::Cluster;
//use twilight_gateway::queue::Queue;

use futures::StreamExt;
use twilight_model::id::marker::UserMarker;

use std::time::Duration;

@@ -27,19 +23,6 @@ use reqwest::Client as ReqwestClient;
//#[global_allocator]
//static ALLOC: snmalloc_rs::SnMalloc = snmalloc_rs::SnMalloc;

const OWNER: Id<UserMarker> = Id::new(77_469_400_222_932_992);

const HELP: &str = "This is the **Lasagne Bot**
The bot has the following commands:
- `=today` Gets today's comic (Indiana time).
- `=date 2020-02-28` Gets a comic from a specific date.
- `=random` Gets a random comic.
- `=theme monday` Gets a comic about a specific topic.
- `=help` this menu.
- `=yesterday` Gets yesterday's comic.
- `=about` Gets information about the bot.
- `=invite` Gets a invite for the bot.";

const ABOUT: &str = "This is Lasagne Bot, created by Erk#2048.

Other than serving comics it serves as a testing ground for the Twilight Discord library.
@@ -52,7 +35,6 @@ const INVITE: &str = "Invite Lasagne bot to your server: \
                      <https://discord.com/oauth2/authorize?client_id=404364579645292564&scope=bot%20applications.commands&permissions=275414797312>)";

mod comic;
mod command_handler;
mod commands;
mod context;
mod database;
@@ -60,7 +42,6 @@ mod slash_handler;
mod syndicate;
mod theme;

use crate::command_handler::handle_command;
use crate::context::Context;
use crate::database::ComicDb2;
use crate::slash_handler::handle_slash;
@@ -95,8 +76,6 @@ async fn async_main() -> GarfieldResult<()> {
        .model()
        .await?;

    let current_user = http.current_user().exec().await?.model().await?;

    let interaction = http.interaction(current_app.id);

    interaction
@@ -114,37 +93,6 @@ async fn async_main() -> GarfieldResult<()> {
    //     .exec()
    //     .await?;

    #[allow(deprecated)]
    let parser = {
        let mut config = CommandParserConfig::new();
        config.add_command("today", true);
        config.add_command("date", true);
        config.add_command("theme", true);
        config.add_command("random", true);
        config.add_command("tomorrow", true);
        config.add_command("yesterday", true);
        config.add_command("help", true);
        config.add_command("about", true);
        config.add_command("status", true);
        config.add_command("invite", true);

        // tests
        config.add_command("comic_stats", true);
        // config.command("stats", true);
        // config.command("user", true);
        // config.command("member", true);
        // config.command("guild", true);
        // config.command("role", true);
        // config.command("emoji", true);
        // config.command("channel", true);
        // config.command("presence", true);

        config.add_prefix("=");
        config.add_prefix(format!("<@{}>", current_user.id));
        config.add_prefix(format!("<@!{}>", current_user.id));
        Parser::new(config)
    };

    let rqc = ReqwestClient::new();

    let comic_db = ComicDb2::new(&database_location)?;
@@ -152,8 +100,7 @@ async fn async_main() -> GarfieldResult<()> {
    let theme_client = ThemeClient::new_rwc(comic_db.clone(), rqc.clone())?;

    use twilight_model::gateway::Intents;
    let intents = Intents::GUILD_MESSAGES | Intents::DIRECT_MESSAGES;

    let intents = Intents::empty();
    use twilight_gateway::EventTypeFlags;
    let flags =
        EventTypeFlags::MESSAGE_CREATE | EventTypeFlags::READY | EventTypeFlags::INTERACTION_CREATE;
@@ -181,7 +128,6 @@ async fn async_main() -> GarfieldResult<()> {
        comic_db,
        http,
        index,
        parser,
        reader,
        rqc,
        theme_client,
@@ -202,24 +148,12 @@ async fn async_main() -> GarfieldResult<()> {
    Ok(())
}

async fn handle_event(event: Event, ctx: Context<'_>) -> GarfieldResult<()> {
async fn handle_event(event: Event, ctx: Context) -> GarfieldResult<()> {
    match event {
        Event::Ready(ready) => {
            info!("In {} guilds!", ready.guilds.len());
            Ok(())
        }
        Event::MessageCreate(msg) => {
            if msg.0.author.bot {
                // Don't react if message was sent by a bot.
                return Ok(());
            }

            match handle_command(msg.0, ctx).await {
                Ok(_) => (),
                Err(why) => warn!("Error handling command: {}", why),
            }
            Ok(())
        }
        Event::InteractionCreate(interaction) => {
            match handle_slash(interaction.0, ctx).await {
                Ok(_) => (),
diff --git a/src/slash_handler.rs b/src/slash_handler.rs
index f52e8a4..2df0bcc 100644
--- a/src/slash_handler.rs
+++ b/src/slash_handler.rs
@@ -1,7 +1,7 @@
use crate::comic::ComicEmbed;
use crate::Context;
use crate::GarfieldResult;
use crate::{ABOUT, HELP, INVITE, INVITE_URL};
use crate::{ABOUT, INVITE, INVITE_URL};

use tantivy::collector::TopDocs;
use tantivy::query::QueryParser;
@@ -22,7 +22,7 @@ use twilight_model::guild::Permissions;

async fn handle_autocomplete(
    ac: Box<ApplicationCommandAutocomplete>,
    ctx: Context<'_>,
    ctx: Context,
) -> GarfieldResult<()> {
    let start = std::time::Instant::now();
    let search_string = {
@@ -111,7 +111,7 @@ fn to_ac(docs: impl Iterator<Item = (f32, String, String)>) -> InteractionRespon
    }
}

pub async fn handle_slash(slash: Interaction, ctx: Context<'_>) -> GarfieldResult<()> {
pub async fn handle_slash(slash: Interaction, ctx: Context) -> GarfieldResult<()> {
    let slash = match slash {
        Interaction::Ping(_) => {
            warn!("Got slash ping!");
@@ -244,9 +244,12 @@ pub async fn handle_slash(slash: Interaction, ctx: Context<'_>) -> GarfieldResul
            .yesterday()
            .await
            .slash(),
        "tomorrow" => ComicEmbed::new(ctx.db.clone(), ctx.rqc.clone())
            .tomorrow()
            .await
            .slash(),
        "about" => slash_message(ABOUT),
        "invite" => slash_message(INVITE),
        "help" => slash_message(HELP),
        "subscribe" => {
            let have_permission = slash
                .member
diff --git a/src/syndicate.rs b/src/syndicate.rs
index a2951b6..06c6b0d 100644
--- a/src/syndicate.rs
+++ b/src/syndicate.rs
@@ -28,7 +28,7 @@ pub struct Syndicator {
}

impl Syndicator {
    pub fn new(ctx: &Context<'_>) -> Self {
    pub fn new(ctx: &Context) -> Self {
        let db = ctx.db.clone();
        let rqc = ctx.rqc.clone();
        let http = ctx.http.clone();
-- 
2.36.0.windows.1
Reply to thread Export thread (mbox)