feat: search for links and author type

Signed-off-by: Zomatree <me@zomatree.live>
This commit is contained in:
Zomatree
2026-04-09 03:54:14 +01:00
parent b7ed543156
commit 9c62568132
27 changed files with 615 additions and 368 deletions

View File

@@ -1,6 +1,6 @@
use revolt_database::{
util::{permissions::DatabasePermissionQuery, reference::Reference},
Database, PartialMessage, User,
Database, PartialMessage, User, AMQP,
};
use revolt_permissions::{calculate_channel_permissions, ChannelPermission};
use revolt_result::Result;
@@ -16,6 +16,7 @@ use rocket_empty::EmptyResponse;
#[delete("/<target>/messages/<msg>/reactions")]
pub async fn clear_reactions(
db: &State<Database>,
amqp: &State<AMQP>,
user: User,
target: Reference<'_>,
msg: Reference<'_>,
@@ -33,11 +34,12 @@ pub async fn clear_reactions(
message
.update(
db,
Some(amqp),
PartialMessage {
reactions: Some(Default::default()),
..Default::default()
},
vec![]
vec![],
)
.await
.map(|_| EmptyResponse)

View File

@@ -1,7 +1,9 @@
use iso8601_timestamp::Timestamp;
use revolt_config::capture_error;
use revolt_database::{
AMQP, Database, Message, PartialMessage, User, tasks, util::{permissions::DatabasePermissionQuery, reference::Reference}
tasks,
util::{permissions::DatabasePermissionQuery, reference::Reference},
Database, Message, PartialMessage, User, AMQP,
};
use revolt_models::v0::{self, Embed};
use revolt_permissions::{calculate_channel_permissions, ChannelPermission};
@@ -82,7 +84,7 @@ pub async fn edit(
partial.embeds = Some(new_embeds);
message.update(db, partial, vec![]).await?;
message.update(db, Some(amqp), partial, vec![]).await?;
// Queue up a task for processing embeds if the we have sufficient permissions
if permissions.has_channel_permission(ChannelPermission::SendEmbeds) {
@@ -96,10 +98,5 @@ pub async fn edit(
}
}
if let Err(e) = amqp.edit_message_search(message.clone()).await {
log::error!("Error pushing message to RabbitMQ: {e}");
capture_error(&e);
}
Ok(Json(message.into_model(None, None)))
}

View File

@@ -39,6 +39,7 @@ pub async fn message_pin(
message
.update(
db,
Some(amqp),
PartialMessage {
pinned: Some(true),
..Default::default()
@@ -47,7 +48,10 @@ pub async fn message_pin(
)
.await?;
if let Err(e) = amqp.edit_message_search(message.clone()).await {
if let Err(e) = amqp
.edit_message_search(message.clone(), message.fetch_author(db).await)
.await
{
log::error!("Error pushing message to RabbitMQ: {e}");
capture_error(&e);
}
@@ -122,8 +126,8 @@ mod test {
flags: None,
},
v0::MessageAuthor::User(&user.clone().into(&harness.db, Some(&user)).await),
Some(user.clone().into(&harness.db, Some(&user)).await),
Some(member.into()),
Some(user.clone()),
Some(member),
user.limits().await,
IdempotencyKey::unchecked_from_string("0".to_string()),
false,

View File

@@ -126,16 +126,10 @@ pub async fn message_send(
// Make sure we have server member (edge case if server owner)
query.are_we_a_member().await;
// Create model user / members
let model_user = user
.clone()
.into_known_static(revolt_presence::is_online(&user.id).await)
.await;
let model_member: Option<v0::Member> = query
let member = query
.member_ref()
.as_ref()
.map(|member| member.clone().into_owned().into());
.map(|member| member.clone().into_owned());
Ok(Json(
Message::create_from_api(
@@ -144,15 +138,22 @@ pub async fn message_send(
channel,
data,
v0::MessageAuthor::User(&author),
Some(model_user.clone()),
model_member.clone(),
Some(user.clone()),
member.clone(),
user.limits().await,
idempotency,
permissions.has_channel_permission(ChannelPermission::SendEmbeds),
allow_mentions,
)
.await?
.into_model(Some(model_user), model_member),
.into_model(
Some(
user.clone()
.into_known_static(revolt_presence::is_online(&user.id).await)
.await,
),
member.map(Into::into),
),
))
}
@@ -262,8 +263,8 @@ mod test {
flags: None,
},
v0::MessageAuthor::User(&user.clone().into(&harness.db, Some(&user)).await),
Some(user.clone().into(&harness.db, Some(&user)).await),
Some(member.clone().into()),
Some(user.clone()),
Some(member.clone()),
user.limits().await,
IdempotencyKey::unchecked_from_string("0".to_string()),
false,
@@ -302,8 +303,8 @@ mod test {
flags: None,
},
v0::MessageAuthor::User(&user.clone().into(&harness.db, Some(&user)).await),
Some(user.clone().into(&harness.db, Some(&user)).await),
Some(member.clone().into()),
Some(user.clone()),
Some(member.clone()),
user.limits().await,
IdempotencyKey::unchecked_from_string("1".to_string()),
false,
@@ -350,8 +351,8 @@ mod test {
flags: None,
},
v0::MessageAuthor::User(&user.clone().into(&harness.db, Some(&user)).await),
Some(user.clone().into(&harness.db, Some(&user)).await),
Some(member.clone().into()),
Some(user.clone()),
Some(member.clone()),
user.limits().await,
IdempotencyKey::unchecked_from_string("2".to_string()),
false,
@@ -396,8 +397,8 @@ mod test {
flags: None,
},
v0::MessageAuthor::User(&user.clone().into(&harness.db, Some(&user)).await),
Some(user.clone().into(&harness.db, Some(&user)).await),
Some(member.clone().into()),
Some(user.clone()),
Some(member.clone()),
user.limits().await,
IdempotencyKey::unchecked_from_string("1".to_string()),
false,
@@ -447,8 +448,8 @@ mod test {
flags: None,
},
v0::MessageAuthor::User(&user.clone().into(&harness.db, Some(&user)).await),
Some(user.clone().into(&harness.db, Some(&user)).await),
Some(member.clone().into()),
Some(user.clone()),
Some(member.clone()),
user.limits().await,
IdempotencyKey::unchecked_from_string("3".to_string()),
false,
@@ -484,7 +485,7 @@ mod test {
flags: None,
},
v0::MessageAuthor::User(&user.clone().into(&harness.db, Some(&user)).await),
Some(user.clone().into(&harness.db, Some(&user)).await),
Some(user.clone()),
Some(member.clone().into()),
user.limits().await,
IdempotencyKey::unchecked_from_string("4".to_string()),
@@ -515,7 +516,7 @@ mod test {
flags: None,
},
v0::MessageAuthor::User(&user.clone().into(&harness.db, Some(&user)).await),
Some(user.clone().into(&harness.db, Some(&user)).await),
Some(user.clone()),
Some(member.clone().into()),
user.limits().await,
IdempotencyKey::unchecked_from_string("4".to_string()),
@@ -570,13 +571,8 @@ mod test {
.into(&harness.db, Some(&other_user))
.await,
),
Some(
other_user
.clone()
.into(&harness.db, Some(&other_user))
.await,
),
Some(other_member.clone().into()),
Some(other_user.clone()),
Some(other_member.clone()),
other_user.limits().await,
IdempotencyKey::unchecked_from_string("1".to_string()),
false,
@@ -615,13 +611,8 @@ mod test {
.into(&harness.db, Some(&other_user))
.await,
),
Some(
other_user
.clone()
.into(&harness.db, Some(&other_user))
.await,
),
Some(other_member.clone().into()),
Some(other_user.clone()),
Some(other_member.clone()),
other_user.limits().await,
IdempotencyKey::unchecked_from_string("1".to_string()),
false,
@@ -684,13 +675,8 @@ mod test {
.into(&harness.db, Some(&other_user))
.await,
),
Some(
other_user
.clone()
.into(&harness.db, Some(&other_user))
.await,
),
Some(other_member.clone().into()),
Some(other_user.clone()),
Some(other_member.clone()),
other_user.limits().await,
IdempotencyKey::unchecked_from_string("1".to_string()),
false,

View File

@@ -37,10 +37,18 @@ pub async fn message_unpin(
}
message
.update(db, PartialMessage::default(), vec![FieldsMessage::Pinned])
.update(
db,
Some(amqp),
PartialMessage::default(),
vec![FieldsMessage::Pinned],
)
.await?;
if let Err(e) = amqp.edit_message_search(message.clone()).await {
if let Err(e) = amqp
.edit_message_search(message.clone(), message.fetch_author(db).await)
.await
{
log::error!("Error pushing message to RabbitMQ: {e}");
capture_error(&e);
}
@@ -120,8 +128,8 @@ mod test {
flags: None,
},
v0::MessageAuthor::User(&user.clone().into(&harness.db, Some(&user)).await),
Some(user.clone().into(&harness.db, Some(&user)).await),
Some(member.into()),
Some(user.clone()),
Some(member),
user.limits().await,
IdempotencyKey::unchecked_from_string("0".to_string()),
false,

View File

@@ -1,6 +1,4 @@
use std::collections::HashSet;
use revolt_database::{util::permissions::DatabasePermissionQuery, Database, User};
use revolt_database::{util::permissions::DatabasePermissionQuery, Database, Message, User};
use revolt_models::v0;
use revolt_permissions::{calculate_channel_permissions, ChannelPermission};
use revolt_result::{create_error, Result, ToRevoltError};
@@ -66,12 +64,7 @@ pub async fn search_messages(
let message_ids = es.search(terms).await.to_internal_error()?;
let mut messages = db
.fetch_messages_by_id(&message_ids)
.await?
.into_iter()
.map(|msg| msg.into_model(None, None))
.collect::<Vec<_>>();
let mut messages = db.fetch_messages_by_id(&message_ids).await?;
// Fetching the messages looses the order so resort
let sort_order = data.sort.unwrap_or_default();
@@ -80,68 +73,15 @@ pub async fn search_messages(
v0::SortOrder::Desc => b.id.cmp(&a.id),
});
// TODO: abstract the user and member fetching logic out
let response = if let Some(true) = data.include_users {
let user_ids = messages
.iter()
.flat_map(|m| {
let mut users = vec![m.author.clone()];
if let Some(system) = &m.system {
match system {
v0::SystemMessage::ChannelDescriptionChanged { by } => {
users.push(by.clone())
}
v0::SystemMessage::ChannelIconChanged { by } => users.push(by.clone()),
v0::SystemMessage::ChannelOwnershipChanged { from, to, .. } => {
users.push(from.clone());
users.push(to.clone())
}
v0::SystemMessage::ChannelRenamed { by, .. } => users.push(by.clone()),
v0::SystemMessage::UserAdded { by, id, .. }
| v0::SystemMessage::UserRemove { by, id, .. } => {
users.push(by.clone());
users.push(id.clone());
}
v0::SystemMessage::UserBanned { id, .. }
| v0::SystemMessage::UserKicked { id, .. }
| v0::SystemMessage::UserJoined { id, .. }
| v0::SystemMessage::UserLeft { id, .. } => {
users.push(id.clone());
}
v0::SystemMessage::Text { .. } => {}
v0::SystemMessage::MessagePinned { by, .. } => {
users.push(by.clone());
}
v0::SystemMessage::MessageUnpinned { by, .. } => {
users.push(by.clone());
}
v0::SystemMessage::CallStarted { by, .. } => users.push(by.clone()),
}
}
users
})
.collect::<HashSet<String>>()
.into_iter()
.collect::<Vec<String>>();
let users = User::fetch_many_ids_as_mutuals(db, &user, &user_ids).await?;
let (users, members) = Message::fetch_users(db, &messages, server_id.as_deref()).await?;
v0::BulkMessageResponse::MessagesAndUsers {
messages,
users,
members: if let Some(server_id) = server_id {
Some(
db.fetch_members(&server_id, &user_ids)
.await?
.into_iter()
.map(Into::into)
.collect(),
)
} else {
None
},
}
} else {
v0::BulkMessageResponse::JustMessages(messages)
let response = v0::BulkMessageResponse::MessagesAndUsers {
messages: messages
.into_iter()
.map(|msg| msg.into_model(None, None))
.collect(),
users: User::into_mutuals(&user, users).await,
members: Some(members.into_iter().map(Into::into).collect()),
};
Ok(Json(response))

View File

@@ -203,8 +203,8 @@ impl TestHarness {
flags: None,
},
v0::MessageAuthor::User(&user.clone().into(&self.db, Some(user)).await),
Some(user.clone().into(&self.db, Some(user)).await),
Some(member.clone().into()),
Some(user.clone()),
Some(member.clone()),
user.limits().await,
IdempotencyKey::unchecked_from_string("0".to_string()),
false,