Skip to content
Snippets Groups Projects
Commit c00d64cd authored by Stephen D's avatar Stephen D
Browse files

refactor and add counts in new messages

parent fd3e0c90
No related branches found
No related tags found
No related merge requests found
......@@ -7,35 +7,43 @@ use anyhow::Context as AnyhowContext;
use bigdecimal::{BigDecimal, FromPrimitive, ToPrimitive};
use diesel::{ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl};
use serenity::async_trait;
use serenity::model::prelude::{ChannelId, EmojiId, GuildId, Message, Reaction, ReactionType};
use serenity::builder::CreateEmbed;
use serenity::model::prelude::{ChannelId, Emoji, EmojiId, Message, Reaction, ReactionType};
use serenity::prelude::*;
use std::sync::Arc;
use tokio::sync::Mutex;
pub struct StarboardHandler {
#[derive(Clone)]
pub struct SingleMessageHandler {
conn: Arc<Mutex<PgConnection>>,
server_settings: ServerSetting,
reaction_count: u64,
msg: Message,
emoji: Emoji,
name: String,
image: Option<String>,
}
impl StarboardHandler {
pub fn new(conn: Arc<Mutex<PgConnection>>) -> Self {
Self { conn }
}
async fn handle_reaction(&self, ctx: &Context, reaction: &Reaction) -> anyhow::Result<()> {
impl SingleMessageHandler {
pub async fn handle_reaction(
conn: Arc<Mutex<PgConnection>>,
ctx: &Context,
reaction: &Reaction,
) -> anyhow::Result<()> {
let guild = match reaction.channel_id.to_channel(ctx).await?.guild() {
Some(x) => x,
None => return Ok(()),
};
// get corresponding guild settings
let gs: Vec<ServerSetting> = server_settings::dsl::server_settings
let mut gs: Vec<ServerSetting> = server_settings::dsl::server_settings
.filter(
schema::server_settings::columns::guild_id
.eq(BigDecimal::from_u64(guild.guild_id.0).unwrap()),
)
.limit(1)
.get_results(&*self.conn.lock().await)?;
let gs = match gs.first() {
.get_results(&*conn.lock().await)?;
let gs = match gs.pop() {
Some(x) => x,
None => return Ok(()),
};
......@@ -49,8 +57,38 @@ impl StarboardHandler {
let msg = reaction.message(ctx).await?;
for mr in &msg.reactions {
if Self::emoji_match(&mr.reaction_type, emoji) {
self.handle_matching_reaction(ctx, gs, mr.count, &msg, &guild.guild_id)
.await?;
let guild_id = guild.guild_id;
let emoji = guild_id
.emoji(ctx, emoji)
.await
.context("Could not get emoji from guild")?;
let name = msg
.author
.nick_in(ctx, guild_id)
.await
.unwrap_or_else(|| msg.author.tag());
let image = msg
.attachments
.iter()
.filter(|a| a.width.is_some())
.map(|a| &a.url)
.next()
.cloned();
let handler = Self {
conn,
server_settings: gs,
reaction_count: mr.count,
msg,
emoji,
name,
image,
};
handler.process_match(ctx).await?;
break;
}
}
......@@ -59,16 +97,9 @@ impl StarboardHandler {
Ok(())
}
async fn handle_matching_reaction(
&self,
ctx: &Context,
gs: &ServerSetting,
count: u64,
msg: &Message,
guild: &GuildId,
) -> anyhow::Result<()> {
if count >= gs.starboard_threshold as u64 {
let original_id = BigDecimal::from(msg.id.0);
async fn process_match(&self, ctx: &Context) -> anyhow::Result<()> {
if self.reaction_count >= self.server_settings.starboard_threshold as u64 {
let original_id = BigDecimal::from(self.msg.id.0);
diesel::insert_into(starboard_mappings::dsl::starboard_mappings)
.values(starboard_mappings::columns::original_id.eq(&original_id))
.returning(starboard_mappings::columns::repost_id)
......@@ -85,47 +116,11 @@ impl StarboardHandler {
repost_id.get(0).context("Insert of mapping failed")?;
if repost_id.is_none() {
// post to repost channel
let name = msg
.author
.nick_in(&ctx, guild)
.await
.unwrap_or_else(|| msg.author.tag());
let image = msg
.attachments
.iter()
.filter(|a| a.width.is_some())
.map(|a| &a.url)
.next();
let repost = ChannelId(
gs.starboard_channel
.to_u64()
.context("Could not convert starboard channel to a u64")?,
)
.send_message(ctx, |m| {
m.embed(|e| {
let mut e = e
.description(format!(
"[Jump to source]({})\n{}",
msg.link(),
msg.content
))
.author(|a| a.name(&name).icon_url(msg.author.face()))
.timestamp(&msg.timestamp);
if let Some(url) = image {
e = e.image(url);
}
e
})
})
.await?;
// post to repost
let repost = self.post_new_starboard_message(ctx).await?;
// update the DB
let repost_id = BigDecimal::from_u64(repost.id.0);
let repost_id = BigDecimal::from_u64(repost);
diesel::update(
starboard_mappings::dsl::starboard_mappings
.filter(starboard_mappings::columns::original_id.eq(original_id)),
......@@ -138,11 +133,56 @@ impl StarboardHandler {
Ok(())
}
async fn post_new_starboard_message(&self, ctx: &Context) -> anyhow::Result<u64> {
let repost = ChannelId(
self.server_settings
.starboard_channel
.to_u64()
.context("Could not convert starboard channel to a u64")?,
)
.send_message(ctx, |m| m.embed(|e| self.clone().starboard_message(e)))
.await?;
Ok(repost.id.0)
}
fn starboard_message(self, e: &mut CreateEmbed) -> &mut CreateEmbed {
let mut e = e
.description(format!(
"[Jump to source]({})\n{}",
self.msg.link(),
self.msg.content
))
.title(format!("{} {}", self.reaction_count, self.emoji))
.author(|a| a.name(&self.name).icon_url(self.msg.author.face()))
.timestamp(&self.msg.timestamp);
if let Some(url) = self.image {
e = e.image(url);
}
e
}
fn emoji_match(rt: &ReactionType, em: EmojiId) -> bool {
matches!(rt, ReactionType::Custom { id, .. } if *id == em)
}
}
pub struct StarboardHandler {
conn: Arc<Mutex<PgConnection>>,
}
impl StarboardHandler {
pub fn new(conn: Arc<Mutex<PgConnection>>) -> Self {
Self { conn }
}
async fn handle_reaction(&self, ctx: &Context, reaction: &Reaction) -> anyhow::Result<()> {
SingleMessageHandler::handle_reaction(self.conn.clone(), ctx, reaction).await
}
}
#[async_trait]
impl ReactionHandler for StarboardHandler {
async fn reaction(&self, ctx: &Context, reaction: &Reaction) {
......
......@@ -17,7 +17,7 @@ pub struct NewUserProgram<'a> {
pub code: &'a str,
}
#[derive(Queryable)]
#[derive(Clone, Queryable)]
pub struct ServerSetting {
pub id: i32,
pub guild_id: BigDecimal,
......
table! {
server_settings (id) {
id -> Int4,
guild_id -> Numeric,
starboard_threshold -> Int4,
starboard_emoji_id -> Numeric,
starboard_channel -> Numeric,
}
server_settings (id) {
id -> Int4,
guild_id -> Numeric,
starboard_threshold -> Int4,
starboard_emoji_id -> Numeric,
starboard_channel -> Numeric,
}
}
table! {
starboard_mappings (original_id) {
original_id -> Numeric,
repost_id -> Nullable<Numeric>,
}
starboard_mappings (original_id) {
original_id -> Numeric,
repost_id -> Nullable<Numeric>,
}
}
table! {
user_programs (id) {
id -> Int4,
discord_user_id -> Numeric,
name -> Varchar,
code -> Text,
published -> Int4,
}
user_programs (id) {
id -> Int4,
discord_user_id -> Numeric,
name -> Varchar,
code -> Text,
published -> Int4,
}
}
allow_tables_to_appear_in_same_query!(server_settings, starboard_mappings, user_programs,);
allow_tables_to_appear_in_same_query!(
server_settings,
starboard_mappings,
user_programs,
);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment