feat(core): implement message tasks

includes:
- acknowledgements
- last_message_id
- embeds
- web push
This commit is contained in:
Paul Makles
2023-08-27 11:17:03 +01:00
parent 41a47bdf8f
commit 5372296dc0
15 changed files with 1608 additions and 63 deletions

View File

@@ -1,10 +1,15 @@
use indexmap::{IndexMap, IndexSet};
use iso8601_timestamp::Timestamp;
use revolt_models::v0::{Embed, MessageSort, MessageWebhook};
use revolt_models::v0::{Embed, MessageAuthor, MessageSort, MessageWebhook, PushNotification};
use revolt_result::Result;
use serde_json::json;
use ulid::Ulid;
use crate::{events::client::EventV1, Database, File};
use crate::{
events::client::EventV1,
tasks::{self, ack::AckEvent},
Channel, Database, File,
};
auto_derived_partial!(
/// Message
@@ -170,7 +175,12 @@ auto_derived!(
#[allow(clippy::disallowed_methods)]
impl Message {
/// Send a message without any notifications
pub async fn send_without_notifications(&mut self, db: &Database) -> Result<()> {
pub async fn send_without_notifications(
&mut self,
db: &Database,
is_dm: bool,
generate_embeds: bool,
) -> Result<()> {
db.insert_message(self).await?;
// Fan out events
@@ -178,21 +188,90 @@ impl Message {
.p(self.channel.to_string())
.await;
// TODO: update last_message_id
// TODO: add mentions for affected users
// TODO: generate embeds
// Update last_message_id
tasks::last_message_id::queue(self.channel.to_string(), self.id.to_string(), is_dm).await;
// Add mentions for affected users
if let Some(mentions) = &self.mentions {
for user in mentions {
tasks::ack::queue(
self.channel.to_string(),
user.to_string(),
AckEvent::AddMention {
ids: vec![self.id.to_string()],
},
)
.await;
}
}
// Generate embeds
if generate_embeds {
if let Some(content) = &self.content {
tasks::process_embeds::queue(
self.channel.to_string(),
self.id.to_string(),
content.clone(),
)
.await;
}
}
Ok(())
}
/// Send a message
pub async fn send(&mut self, db: &Database) -> Result<()> {
self.send_without_notifications(db).await?;
pub async fn send(
&mut self,
db: &Database,
author: MessageAuthor<'_>,
channel: &Channel,
generate_embeds: bool,
) -> Result<()> {
self.send_without_notifications(
db,
matches!(channel, Channel::DirectMessage { .. }),
generate_embeds,
)
.await?;
// TODO: web push / FCM
// Push out Web Push notifications
crate::tasks::web_push::queue(
{
match channel {
Channel::DirectMessage { recipients, .. }
| Channel::Group { recipients, .. } => recipients.clone(),
Channel::TextChannel { .. } => self.mentions.clone().unwrap_or_default(),
_ => vec![],
}
},
json!(PushNotification::from(self.clone().into(), Some(author), &channel.id()).await)
.to_string(),
)
.await;
todo!()
}
/// Append content to message
pub async fn append(
db: &Database,
id: String,
channel: String,
append: AppendMessage,
) -> Result<()> {
db.append_message(&id, &append).await?;
EventV1::MessageAppend {
id,
channel: channel.to_string(),
append: append.into(),
}
.p(channel)
.await;
Ok(())
}
}
impl SystemMessage {
@@ -209,29 +288,6 @@ impl SystemMessage {
}
impl Interactions {
/// Validate interactions info is correct
/* pub async fn validate(
&self,
db: &Database,
permissions: &mut PermissionCalculator<'_>,
) -> Result<()> {
if let Some(reactions) = &self.reactions {
permissions.throw_permission(db, Permission::React).await?;
if reactions.len() > 20 {
return Err(Error::InvalidOperation);
}
for reaction in reactions {
if !Emoji::can_use(db, reaction).await? {
return Err(Error::InvalidOperation);
}
}
}
Ok(())
}*/
/// Check if we can use a given emoji to react
pub fn can_use(&self, emoji: &str) -> bool {
if self.restrict_reactions {

View File

@@ -131,7 +131,7 @@ impl Member {
id: user.id.clone(),
}
.into_message(id.to_string())
.send_without_notifications(db)
.send_without_notifications(db, false, false)
.await
.ok();
}