Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Channel support #139

Merged
merged 10 commits into from
Jan 12, 2023
10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ edition = "2021"

[dependencies]
twilight-gateway = "0.14.0"
twilight-http = "0.14.0"
twilight-model = "0.14.0"
twilight-validate = "0.14.0"
twilight-util = { version = "0.14.0", features = ["builder", "snowflake"] }
twilight-interactions = "0.14.0"
twilight-http = "0.14.1"
twilight-model = "0.14.2"
twilight-validate = "0.14.1"
twilight-util = { version = "0.14.1", features = ["builder", "snowflake"] }
twilight-interactions = { git = "https://github.com/circuitsacul/twilight-interactions", branch = "missing-channel-types" }
twilight-mention = "0.14.0"
twilight-standby = "0.14.0"

Expand Down
59 changes: 58 additions & 1 deletion src/cache/cache_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::sync::Arc;
use dashmap::{DashMap, DashSet};
use twilight_gateway::Event;
use twilight_model::{
channel::{Channel, Webhook},
channel::{Channel, ChannelType, Webhook},
id::{
marker::{
ChannelMarker, EmojiMarker, GuildMarker, MessageMarker, UserMarker, WebhookMarker,
Expand Down Expand Up @@ -126,6 +126,24 @@ impl Cache {
})
}

pub fn is_channel_forum(
&self,
guild_id: Id<GuildMarker>,
channel_id: Id<ChannelMarker>,
) -> bool {
self.guilds.with(&guild_id, |_, guild| {
guild
.as_ref()
.and_then(|guild| {
guild
.channels
.get(&channel_id)
.map(|channel| channel.kind == ChannelType::GuildForum)
})
.unwrap_or(false)
})
}

pub async fn qualified_channel_ids(
&self,
bot: &StarboardBot,
Expand Down Expand Up @@ -289,6 +307,45 @@ impl Cache {
}
}

pub async fn fog_parent_channel_id(
&self,
bot: &StarboardBot,
guild_id: Id<GuildMarker>,
channel_id: Id<ChannelMarker>,
) -> StarboardResult<Option<Id<ChannelMarker>>> {
let parent = self.guilds.with(&guild_id, |_, guild| {
let Some(guild) = guild else { return None; };

if guild.channels.contains_key(&channel_id) {
return Some(channel_id);
}

if let Some(parent) = guild.active_thread_parents.get(&channel_id) {
return Some(*parent);
}

None
});

if parent.is_some() {
return Ok(parent);
}

let Some(parent) = self.fetch_channel_or_thread_parent(bot, channel_id).await? else {
return Ok(None);
};

self.guilds.alter(&guild_id, |_, mut guild| {
guild.channels.insert(
parent.id,
CachedChannel::from_channel(guild.channels.get(&parent.id), &parent),
);
guild
});

Ok(Some(parent.id))
}

pub async fn fog_channel_nsfw(
&self,
bot: &StarboardBot,
Expand Down
6 changes: 5 additions & 1 deletion src/cache/events/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use twilight_model::gateway::payload::incoming::{
ThreadCreate, ThreadDelete, ThreadListSync, ThreadUpdate,
};

use crate::cache::{cache_struct::Cache, update::UpdateCache};
use crate::{
cache::{cache_struct::Cache, update::UpdateCache},
utils::into_id::IntoId,
};

#[async_trait]
impl UpdateCache for ThreadCreate {
Expand All @@ -27,6 +30,7 @@ impl UpdateCache for ThreadDelete {
guild.active_thread_parents.remove(&self.id);
guild
});
cache.messages.remove(&self.id.get().into_id()).await;
}
}

Expand Down
5 changes: 4 additions & 1 deletion src/cache/models/channel.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use twilight_model::{
channel::Channel,
channel::{Channel, ChannelType},
id::{marker::ChannelMarker, Id},
};

pub struct CachedChannel {
pub is_nsfw: Option<bool>,
pub parent_id: Option<Id<ChannelMarker>>,
pub kind: ChannelType,
}

impl CachedChannel {
Expand All @@ -14,11 +15,13 @@ impl CachedChannel {
Self {
is_nsfw: new.nsfw.or(original.is_nsfw),
parent_id: new.parent_id,
kind: new.kind,
}
} else {
Self {
is_nsfw: new.nsfw,
parent_id: new.parent_id,
kind: new.kind,
}
}
}
Expand Down
62 changes: 40 additions & 22 deletions src/core/autostar.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use std::time::Duration;

use twilight_model::gateway::payload::incoming::MessageCreate;
use twilight_model::id::{
marker::{ChannelMarker, MessageMarker},
Id,
};

use crate::{
cache::models::message::CachedMessage,
client::bot::StarboardBot,
core::emoji::{EmojiCommon, SimpleEmoji},
database::AutoStarChannel,
Expand All @@ -12,54 +16,63 @@ use crate::{

use super::has_image::has_image;

pub async fn handle(bot: &StarboardBot, event: &MessageCreate) -> StarboardResult<()> {
// Ignore DMs
if event.guild_id.is_none() {
return Ok(());
}

pub async fn handle(
bot: &StarboardBot,
autostar_channel_id: Id<ChannelMarker>,
channel_id: Id<ChannelMarker>,
message_id: Id<MessageMarker>,
message: &CachedMessage,
) -> StarboardResult<()> {
// Check the cache...
if !bot.cache.autostar_channel_ids.contains(&event.channel_id) {
if !bot
.cache
.autostar_channel_ids
.contains(&autostar_channel_id)
{
return Ok(());
}

// Check cooldown
if bot
.cooldowns
.autostar_send
.trigger(&event.channel_id)
.trigger(&autostar_channel_id)
.is_some()
{
return Ok(());
}

// Fetch the autostar channels
let asc = AutoStarChannel::list_by_channel(&bot.pool, event.channel_id.get_i64()).await?;
let asc = AutoStarChannel::list_by_channel(&bot.pool, autostar_channel_id.get_i64()).await?;

// If none, remove the channel id from the cache
if asc.is_empty() {
bot.cache.autostar_channel_ids.remove(&event.channel_id);
bot.cache.autostar_channel_ids.remove(&autostar_channel_id);
return Ok(());
}

// Handle the autostar channels
for a in asc {
let status = get_status(bot, &a, event).await;
let status = get_status(bot, &a, message_id, message).await;

if matches!(status, Status::InvalidStay) {
continue;
}
if let Status::InvalidRemove(reasons) = status {
let _ = bot.http.delete_message(event.channel_id, event.id).await;

if !event.author.bot {
let message = {
let _ = bot.http.delete_message(channel_id, message_id).await;

let send = bot
.cache
.fog_user(bot, message.author_id)
.await?
.map_or(false, |u| !u.is_bot);
if send {
let to_send = {
format!(
"Your message in <#{}> was deleted for the following reason(s):\n",
event.channel_id
"Your message in <#{channel_id}> was deleted for the following reason(s):\n"
) + &reasons.join("\n - ")
};
notify::notify(bot, event.author.id, &message).await?;
notify::notify(bot, message.author_id, &to_send).await?;
}

continue;
Expand All @@ -68,7 +81,7 @@ pub async fn handle(bot: &StarboardBot, event: &MessageCreate) -> StarboardResul
for emoji in Vec::<SimpleEmoji>::from_stored(a.emojis) {
let _ = bot
.http
.create_reaction(event.channel_id, event.id, &emoji.reactable())
.create_reaction(channel_id, message_id, &emoji.reactable())
.await;
}
}
Expand All @@ -82,7 +95,12 @@ enum Status {
InvalidRemove(Vec<String>),
}

async fn get_status(bot: &StarboardBot, asc: &AutoStarChannel, event: &MessageCreate) -> Status {
async fn get_status(
bot: &StarboardBot,
asc: &AutoStarChannel,
message_id: Id<MessageMarker>,
event: &CachedMessage,
) -> Status {
let mut invalid = Vec::new();

if asc.min_chars != 0 && event.content.len() < asc.min_chars as usize {
Expand All @@ -101,7 +119,7 @@ async fn get_status(bot: &StarboardBot, asc: &AutoStarChannel, event: &MessageCr
if asc.require_image && !has_image(&event.embeds, &event.attachments) {
tokio::time::sleep(Duration::from_secs(3)).await;

let updated_msg = bot.cache.messages.get(&event.id);
let updated_msg = bot.cache.messages.get(&message_id);
let mut still_invalid = true;

if let Some(msg) = updated_msg {
Expand Down
Loading