Compare commits

..

3 Commits

5 changed files with 50 additions and 12 deletions

View File

@ -0,0 +1,2 @@
-- Add migration script here
ALTER TABLE reminders ADD COLUMN `thread_id` BIGINT DEFAULT NULL;

View File

@ -53,19 +53,22 @@ async fn check_self_permissions(ctx: Context<'_>) -> bool {
.member_permissions(&ctx.discord(), user_id) .member_permissions(&ctx.discord(), user_id)
.await .await
.map_or(false, |p| p.manage_webhooks()); .map_or(false, |p| p.manage_webhooks());
let (view_channel, send_messages, embed_links) = ctx let (view_channel, send_messages, embed_links) = ctx
.channel_id() .channel_id()
.to_channel_cached(&ctx.discord()) .to_channel(&ctx.discord())
.await
.ok()
.and_then(|c| { .and_then(|c| {
if let Channel::Guild(channel) = c { if let Channel::Guild(channel) = c {
channel.permissions_for_user(&ctx.discord(), user_id).ok() let perms = channel.permissions_for_user(&ctx.discord(), user_id).ok()?;
Some((perms.view_channel(), perms.send_messages(), perms.embed_links()))
} else { } else {
None None
} }
}) })
.map_or((false, false, false), |p| { .unwrap_or((false, false, false));
(p.view_channel(), p.send_messages(), p.embed_links())
});
if manage_webhooks && send_messages && embed_links { if manage_webhooks && send_messages && embed_links {
true true
@ -81,8 +84,8 @@ async fn check_self_permissions(ctx: Context<'_>) -> bool {
{} **Manage Webhooks**", {} **Manage Webhooks**",
if view_channel { "" } else { "" }, if view_channel { "" } else { "" },
if send_messages { "" } else { "" }, if send_messages { "" } else { "" },
if manage_webhooks { "" } else { "" },
if embed_links { "" } else { "" }, if embed_links { "" } else { "" },
if manage_webhooks { "" } else { "" },
)) ))
}) })
.await; .await;

View File

@ -90,6 +90,8 @@ async fn _main(tx: Sender<()>) -> Result<(), Box<dyn StdError + Send + Sync>> {
if Path::new("/etc/reminder-rs/config.env").exists() { if Path::new("/etc/reminder-rs/config.env").exists() {
dotenv::from_path("/etc/reminder-rs/config.env")?; dotenv::from_path("/etc/reminder-rs/config.env")?;
} else {
dotenv::from_path(".env")?;
} }
let discord_token = env::var("DISCORD_TOKEN").expect("Missing DISCORD_TOKEN from environment"); let discord_token = env::var("DISCORD_TOKEN").expect("Missing DISCORD_TOKEN from environment");

View File

@ -5,7 +5,7 @@ pub mod timer;
pub mod user_data; pub mod user_data;
use chrono_tz::Tz; use chrono_tz::Tz;
use poise::serenity_prelude::{async_trait, model::id::UserId}; use poise::serenity_prelude::{async_trait, model::id::UserId, ChannelType};
use crate::{ use crate::{
models::{channel_data::ChannelData, user_data::UserData}, models::{channel_data::ChannelData, user_data::UserData},
@ -43,7 +43,20 @@ impl CtxData for Context<'_> {
} }
async fn channel_data(&self) -> Result<ChannelData, Box<dyn std::error::Error + Sync + Send>> { async fn channel_data(&self) -> Result<ChannelData, Box<dyn std::error::Error + Sync + Send>> {
let channel = self.channel_id().to_channel_cached(&self.discord()).unwrap(); // If we're in a thread, get the parent channel.
let recv_channel = self.channel_id().to_channel(&self.discord()).await?;
let channel = match recv_channel.guild() {
Some(guild_channel) => {
if guild_channel.kind == ChannelType::PublicThread {
guild_channel.parent_id.unwrap().to_channel_cached(&self.discord()).unwrap()
} else {
self.channel_id().to_channel_cached(&self.discord()).unwrap()
}
}
None => self.channel_id().to_channel_cached(&self.discord()).unwrap(),
};
ChannelData::from_channel(&channel, &self.data().database).await ChannelData::from_channel(&channel, &self.data().database).await
} }

View File

@ -9,7 +9,7 @@ use poise::serenity_prelude::{
id::{ChannelId, GuildId, UserId}, id::{ChannelId, GuildId, UserId},
webhook::Webhook, webhook::Webhook,
}, },
Result as SerenityResult, ChannelType, Result as SerenityResult,
}; };
use sqlx::MySqlPool; use sqlx::MySqlPool;
@ -51,6 +51,7 @@ pub struct ReminderBuilder {
pool: MySqlPool, pool: MySqlPool,
uid: String, uid: String,
channel: u32, channel: u32,
thread_id: Option<u64>,
utc_time: NaiveDateTime, utc_time: NaiveDateTime,
timezone: String, timezone: String,
interval_seconds: Option<i64>, interval_seconds: Option<i64>,
@ -226,6 +227,7 @@ impl<'a> MultiReminderBuilder<'a> {
errors.insert(ReminderError::LongInterval); errors.insert(ReminderError::LongInterval);
} else { } else {
for scope in self.scopes { for scope in self.scopes {
let thread_id = None;
let db_channel_id = match scope { let db_channel_id = match scope {
ReminderScope::User(user_id) => { ReminderScope::User(user_id) => {
if let Ok(user) = UserId(user_id).to_user(&self.ctx.discord()).await { if let Ok(user) = UserId(user_id).to_user(&self.ctx.discord()).await {
@ -258,14 +260,29 @@ impl<'a> MultiReminderBuilder<'a> {
let channel = let channel =
ChannelId(channel_id).to_channel(&self.ctx.discord()).await.unwrap(); ChannelId(channel_id).to_channel(&self.ctx.discord()).await.unwrap();
if let Some(guild_channel) = channel.clone().guild() { if let Some(mut guild_channel) = channel.clone().guild() {
if Some(guild_channel.guild_id) != self.guild_id { if Some(guild_channel.guild_id) != self.guild_id {
Err(ReminderError::InvalidTag) Err(ReminderError::InvalidTag)
} else { } else {
let mut channel_data = let mut channel_data = if guild_channel.kind
ChannelData::from_channel(&channel, &self.ctx.data().database) == ChannelType::PublicThread
{
// fixme jesus christ
let parent = guild_channel
.parent_id
.unwrap()
.to_channel(&self.ctx.discord())
.await .await
.unwrap(); .unwrap();
guild_channel = parent.clone().guild().unwrap();
ChannelData::from_channel(&parent, &self.ctx.data().database)
.await
.unwrap()
} else {
ChannelData::from_channel(&channel, &self.ctx.data().database)
.await
.unwrap()
};
if channel_data.webhook_id.is_none() if channel_data.webhook_id.is_none()
|| channel_data.webhook_token.is_none() || channel_data.webhook_token.is_none()
@ -307,6 +324,7 @@ impl<'a> MultiReminderBuilder<'a> {
pool: self.ctx.data().database.clone(), pool: self.ctx.data().database.clone(),
uid: generate_uid(), uid: generate_uid(),
channel: c, channel: c,
thread_id,
utc_time: self.utc_time, utc_time: self.utc_time,
timezone: self.timezone.to_string(), timezone: self.timezone.to_string(),
interval_seconds: self.interval.map(|i| i.sec as i64), interval_seconds: self.interval.map(|i| i.sec as i64),