component models
This commit is contained in:
parent
afc376c44f
commit
06c4deeaa9
@ -1,23 +1,23 @@
|
||||
mod sender;
|
||||
|
||||
use std::env;
|
||||
|
||||
use log::info;
|
||||
use serenity::client::Context;
|
||||
use sqlx::{Executor, MySql};
|
||||
use std::env;
|
||||
use tokio::time::sleep_until;
|
||||
use tokio::time::{Duration, Instant};
|
||||
use tokio::time::{sleep_until, Duration, Instant};
|
||||
|
||||
type Database = MySql;
|
||||
|
||||
pub async fn initialize(ctx: Context, pool: impl Executor<'_, Database = Database> + Copy) {
|
||||
let REMIND_INTERVAL = env::var("REMIND_INTERVAL")
|
||||
let remind_interval = env::var("REMIND_INTERVAL")
|
||||
.map(|inner| inner.parse::<u64>().ok())
|
||||
.ok()
|
||||
.flatten()
|
||||
.unwrap_or(10);
|
||||
|
||||
loop {
|
||||
let sleep_to = Instant::now() + Duration::from_secs(REMIND_INTERVAL);
|
||||
let sleep_to = Instant::now() + Duration::from_secs(remind_interval);
|
||||
let reminders = sender::Reminder::fetch_reminders(pool).await;
|
||||
|
||||
if reminders.len() > 0 {
|
||||
|
@ -1,4 +1,3 @@
|
||||
use crate::Database;
|
||||
use chrono::Duration;
|
||||
use chrono_tz::Tz;
|
||||
use lazy_static::lazy_static;
|
||||
@ -20,6 +19,8 @@ use sqlx::{
|
||||
Executor,
|
||||
};
|
||||
|
||||
use crate::Database;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref TIMEFROM_REGEX: Regex =
|
||||
Regex::new(r#"<<timefrom:(?P<time>\d+):(?P<format>.+)?>>"#).unwrap();
|
||||
|
@ -1,9 +1,11 @@
|
||||
use chrono::offset::Utc;
|
||||
use poise::serenity::builder::CreateEmbedFooter;
|
||||
use poise::{serenity_prelude as serenity, serenity_prelude::Mentionable};
|
||||
|
||||
use crate::{models::CtxData, Context, Error, THEME_COLOR};
|
||||
|
||||
fn footer(ctx: Context<'_>) -> impl FnOnce(&mut CreateEmbedFooter) -> &mut CreateEmbedFooter {
|
||||
fn footer(
|
||||
ctx: Context<'_>,
|
||||
) -> impl FnOnce(&mut serenity::CreateEmbedFooter) -> &mut serenity::CreateEmbedFooter {
|
||||
let shard_count = ctx.discord().cache.shard_count();
|
||||
let shard = ctx.discord().shard_id;
|
||||
|
||||
@ -22,9 +24,8 @@ fn footer(ctx: Context<'_>) -> impl FnOnce(&mut CreateEmbedFooter) -> &mut Creat
|
||||
pub async fn help(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let footer = footer(ctx);
|
||||
|
||||
let _ = ctx
|
||||
.send(|m| {
|
||||
m.embed(|e| {
|
||||
ctx.send(|m| {
|
||||
m.ephemeral(true).embed(|e| {
|
||||
e.title("Help")
|
||||
.color(*THEME_COLOR)
|
||||
.description(
|
||||
@ -56,7 +57,7 @@ __Advanced Commands__
|
||||
.footer(footer)
|
||||
})
|
||||
})
|
||||
.await;
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -68,7 +69,7 @@ pub async fn info(ctx: Context<'_>) -> Result<(), Error> {
|
||||
|
||||
let _ = ctx
|
||||
.send(|m| {
|
||||
m.embed(|e| {
|
||||
m.ephemeral(true).embed(|e| {
|
||||
e.title("Info")
|
||||
.description(format!(
|
||||
"Help: `/help`
|
||||
@ -95,9 +96,10 @@ Use our dashboard: https://reminder-bot.com/",
|
||||
pub async fn donate(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let footer = footer(ctx);
|
||||
|
||||
let _ = ctx.send(|m| m.embed(|e| {
|
||||
ctx.send(|m| m.embed(|e| {
|
||||
e.title("Donate")
|
||||
.description("Thinking of adding a monthly contribution? Click below for my Patreon and official bot server :)
|
||||
.description("Thinking of adding a monthly contribution?
|
||||
Click below for my Patreon and official bot server :)
|
||||
|
||||
**https://www.patreon.com/jellywx/**
|
||||
**https://discord.jellywx.com/**
|
||||
@ -116,7 +118,7 @@ Just $2 USD/month!
|
||||
.color(*THEME_COLOR)
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -126,21 +128,20 @@ Just $2 USD/month!
|
||||
pub async fn dashboard(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let footer = footer(ctx);
|
||||
|
||||
let _ = ctx
|
||||
.send(|m| {
|
||||
m.embed(|e| {
|
||||
ctx.send(|m| {
|
||||
m.ephemeral(true).embed(|e| {
|
||||
e.title("Dashboard")
|
||||
.description("**https://reminder-bot.com/dashboard**")
|
||||
.footer(footer)
|
||||
.color(*THEME_COLOR)
|
||||
})
|
||||
})
|
||||
.await;
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// View the current time in a user's selected timezone
|
||||
/// View the current time in your selected timezone
|
||||
#[poise::command(slash_command)]
|
||||
pub async fn clock(ctx: Context<'_>) -> Result<(), Error> {
|
||||
ctx.defer_ephemeral().await?;
|
||||
@ -155,3 +156,25 @@ pub async fn clock(ctx: Context<'_>) -> Result<(), Error> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// View the current time in a user's selected timezone
|
||||
#[poise::command(context_menu_command = "View Local Time")]
|
||||
pub async fn clock_context_menu(ctx: Context<'_>, user: serenity::User) -> Result<(), Error> {
|
||||
ctx.defer_ephemeral().await?;
|
||||
|
||||
let user_data = ctx.user_data(user.id).await?;
|
||||
let tz = user_data.timezone();
|
||||
|
||||
let now = Utc::now().with_timezone(&tz);
|
||||
|
||||
ctx.send(|m| {
|
||||
m.ephemeral(true).content(format!(
|
||||
"Time in {}'s timezone: `{}`",
|
||||
user.mention(),
|
||||
now.format("%H:%M")
|
||||
))
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ use chrono_tz::Tz;
|
||||
use num_integer::Integer;
|
||||
use poise::{
|
||||
serenity::{builder::CreateEmbed, model::channel::Channel},
|
||||
serenity_prelude::ActionRole::Create,
|
||||
CreateReply,
|
||||
};
|
||||
|
||||
@ -32,7 +31,6 @@ use crate::{
|
||||
Reminder,
|
||||
},
|
||||
timer::Timer,
|
||||
user_data::UserData,
|
||||
CtxData,
|
||||
},
|
||||
time_parser::natural_parser,
|
||||
@ -212,7 +210,7 @@ pub async fn look(
|
||||
None
|
||||
};
|
||||
|
||||
let reminders = Reminder::from_channel(&ctx, channel_id, &flags).await;
|
||||
let reminders = Reminder::from_channel(&ctx.data().database, channel_id, &flags).await;
|
||||
|
||||
if reminders.is_empty() {
|
||||
let _ = ctx.say("No reminders on specified channel").await;
|
||||
@ -266,7 +264,9 @@ pub async fn look(
|
||||
pub async fn delete(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let timezone = ctx.timezone().await;
|
||||
|
||||
let reminders = Reminder::from_guild(&ctx, ctx.guild_id(), ctx.author().id).await;
|
||||
let reminders =
|
||||
Reminder::from_guild(&ctx.discord(), &ctx.data().database, ctx.guild_id(), ctx.author().id)
|
||||
.await;
|
||||
|
||||
let resp = show_delete_page(&reminders, 0, timezone);
|
||||
|
||||
|
@ -6,6 +6,7 @@ use crate::{
|
||||
ComponentDataModel, TodoSelector,
|
||||
},
|
||||
consts::{EMBED_DESCRIPTION_MAX_LENGTH, SELECT_MAX_ENTRIES, THEME_COLOR},
|
||||
hooks::guild_only,
|
||||
Context, Error,
|
||||
};
|
||||
|
||||
@ -16,7 +17,7 @@ pub async fn todo_base(_ctx: Context<'_>) -> Result<(), Error> {
|
||||
}
|
||||
|
||||
/// Manage the server todo list
|
||||
#[poise::command(slash_command, rename = "server")]
|
||||
#[poise::command(slash_command, rename = "server", check = "guild_only")]
|
||||
pub async fn todo_guild_base(_ctx: Context<'_>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
@ -70,7 +71,7 @@ WHERE guilds.guild = ?",
|
||||
}
|
||||
|
||||
/// Manage the channel todo list
|
||||
#[poise::command(slash_command, rename = "channel")]
|
||||
#[poise::command(slash_command, rename = "channel", check = "guild_only")]
|
||||
pub async fn todo_channel_base(_ctx: Context<'_>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ use std::io::Cursor;
|
||||
use chrono_tz::Tz;
|
||||
use poise::serenity::{
|
||||
builder::CreateEmbed,
|
||||
client::Context,
|
||||
model::{
|
||||
channel::Channel,
|
||||
interactions::{message_component::MessageComponentInteraction, InteractionResponseType},
|
||||
@ -22,8 +23,9 @@ use crate::{
|
||||
},
|
||||
component_models::pager::{DelPager, LookPager, MacroPager, Pager, TodoPager},
|
||||
consts::{EMBED_DESCRIPTION_MAX_LENGTH, THEME_COLOR},
|
||||
models::{reminder::Reminder, CtxData},
|
||||
Context, Data,
|
||||
models::reminder::Reminder,
|
||||
utils::send_as_initial_response,
|
||||
Data,
|
||||
};
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
@ -53,12 +55,12 @@ impl ComponentDataModel {
|
||||
rmp_serde::from_read(cur).unwrap()
|
||||
}
|
||||
|
||||
pub async fn act(&self, ctx: Context<'_>, component: &MessageComponentInteraction) {
|
||||
pub async fn act(&self, ctx: &Context, data: &Data, component: &MessageComponentInteraction) {
|
||||
match self {
|
||||
ComponentDataModel::LookPager(pager) => {
|
||||
let flags = pager.flags;
|
||||
|
||||
let channel_opt = component.channel_id.to_channel_cached(&ctx.discord());
|
||||
let channel_opt = component.channel_id.to_channel_cached(&ctx);
|
||||
|
||||
let channel_id = if let Some(Channel::Guild(channel)) = channel_opt {
|
||||
if Some(channel.guild_id) == component.guild_id {
|
||||
@ -70,7 +72,7 @@ impl ComponentDataModel {
|
||||
component.channel_id
|
||||
};
|
||||
|
||||
let reminders = Reminder::from_channel(&ctx, channel_id, &flags).await;
|
||||
let reminders = Reminder::from_channel(&data.database, channel_id, &flags).await;
|
||||
|
||||
let pages = reminders
|
||||
.iter()
|
||||
@ -78,9 +80,8 @@ impl ComponentDataModel {
|
||||
.fold(0, |t, r| t + r.len())
|
||||
.div_ceil(EMBED_DESCRIPTION_MAX_LENGTH);
|
||||
|
||||
let channel_name = if let Some(Channel::Guild(channel)) =
|
||||
channel_id.to_channel_cached(&ctx.discord())
|
||||
{
|
||||
let channel_name =
|
||||
if let Some(Channel::Guild(channel)) = channel_id.to_channel_cached(&ctx) {
|
||||
Some(channel.name)
|
||||
} else {
|
||||
None
|
||||
@ -118,7 +119,7 @@ impl ComponentDataModel {
|
||||
.color(*THEME_COLOR);
|
||||
|
||||
let _ = component
|
||||
.create_interaction_response(&ctx.discord(), |r| {
|
||||
.create_interaction_response(&ctx, |r| {
|
||||
r.kind(InteractionResponseType::UpdateMessage).interaction_response_data(
|
||||
|response| {
|
||||
response.embeds(vec![embed]).components(|comp| {
|
||||
@ -132,17 +133,26 @@ impl ComponentDataModel {
|
||||
.await;
|
||||
}
|
||||
ComponentDataModel::DelPager(pager) => {
|
||||
let reminders =
|
||||
Reminder::from_guild(&ctx, component.guild_id, component.user.id).await;
|
||||
let reminders = Reminder::from_guild(
|
||||
&ctx,
|
||||
&data.database,
|
||||
component.guild_id,
|
||||
component.user.id,
|
||||
)
|
||||
.await;
|
||||
|
||||
let max_pages = max_delete_page(&reminders, &pager.timezone);
|
||||
|
||||
let resp = show_delete_page(&reminders, pager.next_page(max_pages), pager.timezone);
|
||||
|
||||
let _ = ctx
|
||||
.send(|r| {
|
||||
*r = resp;
|
||||
r
|
||||
let _ = component
|
||||
.create_interaction_response(&ctx, |f| {
|
||||
f.kind(InteractionResponseType::UpdateMessage).interaction_response_data(
|
||||
|d| {
|
||||
send_as_initial_response(resp, d);
|
||||
d
|
||||
},
|
||||
)
|
||||
})
|
||||
.await;
|
||||
}
|
||||
@ -150,19 +160,28 @@ impl ComponentDataModel {
|
||||
let selected_id = component.data.values.join(",");
|
||||
|
||||
sqlx::query!("DELETE FROM reminders WHERE FIND_IN_SET(id, ?)", selected_id)
|
||||
.execute(&ctx.data().database)
|
||||
.execute(&data.database)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let reminders =
|
||||
Reminder::from_guild(&ctx, component.guild_id, component.user.id).await;
|
||||
let reminders = Reminder::from_guild(
|
||||
&ctx,
|
||||
&data.database,
|
||||
component.guild_id,
|
||||
component.user.id,
|
||||
)
|
||||
.await;
|
||||
|
||||
let resp = show_delete_page(&reminders, selector.page, selector.timezone);
|
||||
|
||||
let _ = ctx
|
||||
.send(|r| {
|
||||
*r = resp;
|
||||
r
|
||||
let _ = component
|
||||
.create_interaction_response(&ctx, |f| {
|
||||
f.kind(InteractionResponseType::UpdateMessage).interaction_response_data(
|
||||
|d| {
|
||||
send_as_initial_response(resp, d);
|
||||
d
|
||||
},
|
||||
)
|
||||
})
|
||||
.await;
|
||||
}
|
||||
@ -175,7 +194,7 @@ INNER JOIN users ON todos.user_id = users.id
|
||||
WHERE users.user = ?",
|
||||
uid,
|
||||
)
|
||||
.fetch_all(&ctx.data().database)
|
||||
.fetch_all(&data.database)
|
||||
.await
|
||||
.unwrap()
|
||||
.iter()
|
||||
@ -188,7 +207,7 @@ INNER JOIN channels ON todos.channel_id = channels.id
|
||||
WHERE channels.channel = ?",
|
||||
cid,
|
||||
)
|
||||
.fetch_all(&ctx.data().database)
|
||||
.fetch_all(&data.database)
|
||||
.await
|
||||
.unwrap()
|
||||
.iter()
|
||||
@ -201,7 +220,7 @@ INNER JOIN guilds ON todos.guild_id = guilds.id
|
||||
WHERE guilds.guild = ?",
|
||||
pager.guild_id,
|
||||
)
|
||||
.fetch_all(&ctx.data().database)
|
||||
.fetch_all(&data.database)
|
||||
.await
|
||||
.unwrap()
|
||||
.iter()
|
||||
@ -219,15 +238,18 @@ WHERE guilds.guild = ?",
|
||||
pager.guild_id,
|
||||
);
|
||||
|
||||
let _ = ctx
|
||||
.send(|r| {
|
||||
*r = resp;
|
||||
r
|
||||
let _ = component
|
||||
.create_interaction_response(&ctx, |f| {
|
||||
f.kind(InteractionResponseType::UpdateMessage)
|
||||
.interaction_response_data(|d| {
|
||||
send_as_initial_response(resp, d);
|
||||
d
|
||||
})
|
||||
})
|
||||
.await;
|
||||
} else {
|
||||
let _ = component
|
||||
.create_interaction_response(&ctx.discord(), |r| {
|
||||
.create_interaction_response(&ctx, |r| {
|
||||
r.kind(InteractionResponseType::ChannelMessageWithSource)
|
||||
.interaction_response_data(|d| {
|
||||
d.flags(
|
||||
@ -244,7 +266,7 @@ WHERE guilds.guild = ?",
|
||||
let selected_id = component.data.values.join(",");
|
||||
|
||||
sqlx::query!("DELETE FROM todos WHERE FIND_IN_SET(id, ?)", selected_id)
|
||||
.execute(&ctx.data().database)
|
||||
.execute(&data.database)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@ -255,7 +277,7 @@ WHERE guilds.guild = ?",
|
||||
selector.channel_id,
|
||||
selector.guild_id,
|
||||
)
|
||||
.fetch_all(&ctx.data().database)
|
||||
.fetch_all(&data.database)
|
||||
.await
|
||||
.unwrap()
|
||||
.iter()
|
||||
@ -270,15 +292,18 @@ WHERE guilds.guild = ?",
|
||||
selector.guild_id,
|
||||
);
|
||||
|
||||
let _ = ctx
|
||||
.send(|r| {
|
||||
*r = resp;
|
||||
r
|
||||
let _ = component
|
||||
.create_interaction_response(&ctx, |f| {
|
||||
f.kind(InteractionResponseType::UpdateMessage)
|
||||
.interaction_response_data(|d| {
|
||||
send_as_initial_response(resp, d);
|
||||
d
|
||||
})
|
||||
})
|
||||
.await;
|
||||
} else {
|
||||
let _ = component
|
||||
.create_interaction_response(&ctx.discord(), |r| {
|
||||
.create_interaction_response(&ctx, |r| {
|
||||
r.kind(InteractionResponseType::ChannelMessageWithSource)
|
||||
.interaction_response_data(|d| {
|
||||
d.flags(
|
||||
@ -291,17 +316,21 @@ WHERE guilds.guild = ?",
|
||||
}
|
||||
}
|
||||
ComponentDataModel::MacroPager(pager) => {
|
||||
let macros = ctx.command_macros().await.unwrap();
|
||||
let macros = data.command_macros(component.guild_id.unwrap()).await.unwrap();
|
||||
|
||||
let max_page = max_macro_page(¯os);
|
||||
let page = pager.next_page(max_page);
|
||||
|
||||
let resp = show_macro_page(¯os, page);
|
||||
|
||||
let _ = ctx
|
||||
.send(|r| {
|
||||
*r = resp;
|
||||
r
|
||||
let _ = component
|
||||
.create_interaction_response(&ctx, |f| {
|
||||
f.kind(InteractionResponseType::UpdateMessage).interaction_response_data(
|
||||
|d| {
|
||||
send_as_initial_response(resp, d);
|
||||
d
|
||||
},
|
||||
)
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
@ -1,21 +1,12 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
env,
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
use std::{collections::HashMap, env, sync::atomic::Ordering};
|
||||
|
||||
use log::{info, warn};
|
||||
use poise::{
|
||||
serenity::{model::interactions::Interaction, utils::shard_id},
|
||||
serenity_prelude as serenity,
|
||||
serenity_prelude::{
|
||||
ApplicationCommandInteraction, ApplicationCommandInteractionData, ApplicationCommandType,
|
||||
InteractionType,
|
||||
},
|
||||
ApplicationCommandOrAutocompleteInteraction, ApplicationContext, Command,
|
||||
};
|
||||
|
||||
use crate::{component_models::ComponentDataModel, Context, Data, Error};
|
||||
use crate::{component_models::ComponentDataModel, Data, Error};
|
||||
|
||||
pub async fn listener(
|
||||
ctx: &serenity::Context,
|
||||
@ -56,12 +47,7 @@ pub async fn listener(
|
||||
}
|
||||
}
|
||||
poise::Event::ChannelDelete { channel } => {
|
||||
sqlx::query!(
|
||||
"
|
||||
DELETE FROM channels WHERE channel = ?
|
||||
",
|
||||
channel.id.as_u64()
|
||||
)
|
||||
sqlx::query!("DELETE FROM channels WHERE channel = ?", channel.id.as_u64())
|
||||
.execute(&data.database)
|
||||
.await
|
||||
.unwrap();
|
||||
@ -122,7 +108,7 @@ DELETE FROM channels WHERE channel = ?
|
||||
Interaction::MessageComponent(component) => {
|
||||
let component_model = ComponentDataModel::from_custom_id(&component.data.custom_id);
|
||||
|
||||
// component_model.act(ctx, component).await;
|
||||
component_model.act(ctx, data, component).await;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
|
@ -1,4 +1,4 @@
|
||||
use poise::{serenity::model::channel::Channel, ApplicationCommandOrAutocompleteInteraction};
|
||||
use poise::serenity::model::channel::Channel;
|
||||
|
||||
use crate::{consts::MACRO_MAX_COMMANDS, models::command_macro::RecordedCommand, Context, Error};
|
||||
|
||||
@ -14,9 +14,6 @@ pub async fn guild_only(ctx: Context<'_>) -> Result<bool, Error> {
|
||||
|
||||
async fn macro_check(ctx: Context<'_>) -> bool {
|
||||
if let Context::Application(app_ctx) = ctx {
|
||||
if let ApplicationCommandOrAutocompleteInteraction::ApplicationCommand(interaction) =
|
||||
app_ctx.interaction
|
||||
{
|
||||
if let Some(guild_id) = ctx.guild_id() {
|
||||
if ctx.command().identifying_name != "macro_finish" {
|
||||
let mut lock = ctx.data().recording_macros.write().await;
|
||||
@ -56,9 +53,6 @@ async fn macro_check(ctx: Context<'_>) -> bool {
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
async fn check_self_permissions(ctx: Context<'_>) -> bool {
|
||||
|
@ -59,6 +59,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
info_cmds::info(),
|
||||
info_cmds::donate(),
|
||||
info_cmds::clock(),
|
||||
info_cmds::clock_context_menu(),
|
||||
info_cmds::dashboard(),
|
||||
moderation_cmds::timezone(),
|
||||
poise::Command {
|
||||
|
@ -9,7 +9,7 @@ use poise::serenity::{async_trait, model::id::UserId};
|
||||
|
||||
use crate::{
|
||||
models::{channel_data::ChannelData, user_data::UserData},
|
||||
CommandMacro, Context, Data, Error,
|
||||
CommandMacro, Context, Data, Error, GuildId,
|
||||
};
|
||||
|
||||
#[async_trait]
|
||||
@ -49,13 +49,20 @@ impl CtxData for Context<'_> {
|
||||
}
|
||||
|
||||
async fn command_macros(&self) -> Result<Vec<CommandMacro<Data, Error>>, Error> {
|
||||
let guild_id = self.guild_id().unwrap();
|
||||
self.data().command_macros(self.guild_id().unwrap()).await
|
||||
}
|
||||
}
|
||||
|
||||
impl Data {
|
||||
pub(crate) async fn command_macros(
|
||||
&self,
|
||||
guild_id: GuildId,
|
||||
) -> Result<Vec<CommandMacro<Data, Error>>, Error> {
|
||||
let rows = sqlx::query!(
|
||||
"SELECT name, description FROM macro WHERE guild_id = (SELECT id FROM guilds WHERE guild = ?)",
|
||||
guild_id.0
|
||||
)
|
||||
.fetch_all(&self.data().database)
|
||||
.fetch_all(&self.database)
|
||||
.await?.iter().map(|row| CommandMacro {
|
||||
guild_id,
|
||||
name: row.name.clone(),
|
||||
|
@ -6,12 +6,15 @@ pub mod look_flags;
|
||||
|
||||
use chrono::{NaiveDateTime, TimeZone};
|
||||
use chrono_tz::Tz;
|
||||
use poise::serenity::model::id::{ChannelId, GuildId, UserId};
|
||||
use poise::{
|
||||
serenity::model::id::{ChannelId, GuildId, UserId},
|
||||
serenity_prelude::Cache,
|
||||
};
|
||||
use sqlx::Executor;
|
||||
|
||||
use crate::{
|
||||
models::reminder::look_flags::{LookFlags, TimeDisplayType},
|
||||
Context, Data, Database,
|
||||
Database,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -70,7 +73,7 @@ WHERE
|
||||
}
|
||||
|
||||
pub async fn from_channel<C: Into<ChannelId>>(
|
||||
ctx: &Context<'_>,
|
||||
pool: impl Executor<'_, Database = Database>,
|
||||
channel_id: C,
|
||||
flags: &LookFlags,
|
||||
) -> Vec<Self> {
|
||||
@ -111,18 +114,19 @@ ORDER BY
|
||||
channel_id.as_u64(),
|
||||
enabled,
|
||||
)
|
||||
.fetch_all(&ctx.data().database)
|
||||
.fetch_all(pool)
|
||||
.await
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub async fn from_guild(
|
||||
ctx: &Context<'_>,
|
||||
cache: impl AsRef<Cache>,
|
||||
pool: impl Executor<'_, Database = Database>,
|
||||
guild_id: Option<GuildId>,
|
||||
user: UserId,
|
||||
) -> Vec<Self> {
|
||||
if let Some(guild_id) = guild_id {
|
||||
let guild_opt = guild_id.to_guild_cached(&ctx.discord());
|
||||
let guild_opt = guild_id.to_guild_cached(cache);
|
||||
|
||||
if let Some(guild) = guild_opt {
|
||||
let channels = guild
|
||||
@ -163,7 +167,7 @@ WHERE
|
||||
",
|
||||
channels
|
||||
)
|
||||
.fetch_all(&ctx.data().database)
|
||||
.fetch_all(pool)
|
||||
.await
|
||||
} else {
|
||||
sqlx::query_as_unchecked!(
|
||||
@ -196,7 +200,7 @@ WHERE
|
||||
",
|
||||
guild_id.as_u64()
|
||||
)
|
||||
.fetch_all(&ctx.data().database)
|
||||
.fetch_all(pool)
|
||||
.await
|
||||
}
|
||||
} else {
|
||||
@ -230,7 +234,7 @@ WHERE
|
||||
",
|
||||
user.as_u64()
|
||||
)
|
||||
.fetch_all(&ctx.data().database)
|
||||
.fetch_all(pool)
|
||||
.await
|
||||
}
|
||||
.unwrap()
|
||||
|
42
src/utils.rs
42
src/utils.rs
@ -1,7 +1,10 @@
|
||||
use poise::serenity::{
|
||||
use poise::{
|
||||
serenity::{
|
||||
builder::CreateApplicationCommands,
|
||||
http::CacheHttp,
|
||||
model::id::{GuildId, UserId},
|
||||
},
|
||||
serenity_prelude as serenity,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@ -65,3 +68,40 @@ pub async fn check_guild_subscription(
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Sends the message, specified via [`crate::CreateReply`], to the interaction initial response
|
||||
/// endpoint
|
||||
pub fn send_as_initial_response(
|
||||
data: poise::CreateReply<'_>,
|
||||
f: &mut serenity::CreateInteractionResponseData,
|
||||
) {
|
||||
let poise::CreateReply {
|
||||
content,
|
||||
embeds,
|
||||
attachments: _, // serenity doesn't support attachments in initial response yet
|
||||
components,
|
||||
ephemeral,
|
||||
allowed_mentions,
|
||||
reference_message: _, // can't reply to a message in interactions
|
||||
} = data;
|
||||
|
||||
if let Some(content) = content {
|
||||
f.content(content);
|
||||
}
|
||||
f.embeds(embeds);
|
||||
if let Some(allowed_mentions) = allowed_mentions {
|
||||
f.allowed_mentions(|f| {
|
||||
*f = allowed_mentions.clone();
|
||||
f
|
||||
});
|
||||
}
|
||||
if let Some(components) = components {
|
||||
f.components(|f| {
|
||||
f.0 = components.0;
|
||||
f
|
||||
});
|
||||
}
|
||||
if ephemeral {
|
||||
f.flags(serenity::InteractionApplicationCommandCallbackDataFlags::EPHEMERAL);
|
||||
}
|
||||
}
|
||||
|
@ -4,17 +4,15 @@ extern crate rocket;
|
||||
mod consts;
|
||||
mod routes;
|
||||
|
||||
use rocket::fs::{relative, FileServer};
|
||||
use std::collections::HashMap;
|
||||
use std::{collections::HashMap, env};
|
||||
|
||||
use oauth2::basic::BasicClient;
|
||||
use oauth2::{AuthUrl, ClientId, ClientSecret, RedirectUrl, TokenUrl};
|
||||
|
||||
use crate::consts::{DISCORD_OAUTH_AUTHORIZE, DISCORD_OAUTH_TOKEN};
|
||||
use oauth2::{basic::BasicClient, AuthUrl, ClientId, ClientSecret, RedirectUrl, TokenUrl};
|
||||
use rocket::fs::FileServer;
|
||||
use rocket_dyn_templates::Template;
|
||||
use serenity::client::Context;
|
||||
use sqlx::{MySql, Pool};
|
||||
use std::env;
|
||||
|
||||
use crate::consts::{DISCORD_OAUTH_AUTHORIZE, DISCORD_OAUTH_TOKEN};
|
||||
|
||||
type Database = MySql;
|
||||
|
||||
|
@ -1,14 +1,13 @@
|
||||
use rocket::State;
|
||||
|
||||
use crate::consts::DISCORD_CDN;
|
||||
use rocket::{
|
||||
serde::json::{json, Json, Value as JsonValue},
|
||||
State,
|
||||
};
|
||||
use serde::Serialize;
|
||||
use serenity::{client::Context, model::id::GuildId};
|
||||
use sqlx::{MySql, Pool};
|
||||
|
||||
use super::Reminder;
|
||||
use rocket::serde::json::{json, Json, Value as JsonValue};
|
||||
use serenity::client::Context;
|
||||
use serenity::http::CacheHttp;
|
||||
use serenity::model::id::GuildId;
|
||||
use crate::consts::DISCORD_CDN;
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ChannelInfo {
|
||||
|
@ -1,22 +1,24 @@
|
||||
use rocket::serde::json::{json, Json, Value as JsonValue};
|
||||
use rocket::{http::CookieJar, State};
|
||||
|
||||
use reqwest::Client;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serenity::model::{
|
||||
id::{GuildId, RoleId},
|
||||
permissions::Permissions,
|
||||
};
|
||||
use sqlx::{MySql, Pool};
|
||||
use std::env;
|
||||
|
||||
use super::Reminder;
|
||||
use crate::consts::DISCORD_API;
|
||||
use crate::routes::dashboard::DeleteReminder;
|
||||
use chrono_tz::Tz;
|
||||
use serenity::client::Context;
|
||||
use serenity::model::id::UserId;
|
||||
use reqwest::Client;
|
||||
use rocket::{
|
||||
http::CookieJar,
|
||||
serde::json::{json, Json, Value as JsonValue},
|
||||
State,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serenity::{
|
||||
client::Context,
|
||||
model::{
|
||||
id::{GuildId, RoleId, UserId},
|
||||
permissions::Permissions,
|
||||
},
|
||||
};
|
||||
use sqlx::{MySql, Pool};
|
||||
|
||||
use super::Reminder;
|
||||
use crate::{consts::DISCORD_API, routes::dashboard::DeleteReminder};
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct UserInfo {
|
||||
@ -166,7 +168,7 @@ pub async fn get_user_guilds(cookies: &CookieJar<'_>, reqwest_client: &State<Cli
|
||||
#[post("/api/user/reminders", data = "<reminder>")]
|
||||
pub async fn create_reminder(
|
||||
reminder: Json<Reminder>,
|
||||
ctx: &State<Context>,
|
||||
_ctx: &State<Context>,
|
||||
pool: &State<Pool<MySql>>,
|
||||
) -> JsonValue {
|
||||
match sqlx::query!(
|
||||
|
Loading…
Reference in New Issue
Block a user