2023-06-25 19:31:40 +02:00
|
|
|
mod data;
|
|
|
|
|
2024-05-09 15:59:08 -07:00
|
|
|
use std::{collections::BTreeMap, sync::Arc};
|
2024-03-02 20:55:02 -05:00
|
|
|
|
2024-07-04 03:26:19 +00:00
|
|
|
use conduit::{Error, Result};
|
2024-05-26 21:29:19 +00:00
|
|
|
use data::Data;
|
2023-06-25 19:31:40 +02:00
|
|
|
use ruma::{
|
|
|
|
api::client::{error::ErrorKind, threads::get_threads::v1::IncludeThreads},
|
2023-06-26 08:33:31 +02:00
|
|
|
events::relation::BundledThread,
|
|
|
|
uint, CanonicalJsonValue, EventId, RoomId, UserId,
|
2023-06-25 19:31:40 +02:00
|
|
|
};
|
2023-06-26 08:33:31 +02:00
|
|
|
use serde_json::json;
|
2023-06-25 19:31:40 +02:00
|
|
|
|
2024-06-28 22:51:39 +00:00
|
|
|
use crate::{services, PduEvent};
|
2023-06-25 19:31:40 +02:00
|
|
|
|
2024-05-09 15:59:08 -07:00
|
|
|
pub struct Service {
|
2024-06-28 22:51:39 +00:00
|
|
|
db: Data,
|
2023-06-25 19:31:40 +02:00
|
|
|
}
|
|
|
|
|
2024-07-04 03:26:19 +00:00
|
|
|
impl crate::Service for Service {
|
|
|
|
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
|
|
|
|
Ok(Arc::new(Self {
|
|
|
|
db: Data::new(args.db),
|
|
|
|
}))
|
2024-05-27 03:17:20 +00:00
|
|
|
}
|
|
|
|
|
2024-07-04 03:26:19 +00:00
|
|
|
fn name(&self) -> &str { crate::service::make_name(std::module_path!()) }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Service {
|
2024-05-09 15:59:08 -07:00
|
|
|
pub fn threads_until<'a>(
|
2023-06-25 19:31:40 +02:00
|
|
|
&'a self, user_id: &'a UserId, room_id: &'a RoomId, until: u64, include: &'a IncludeThreads,
|
|
|
|
) -> Result<impl Iterator<Item = Result<(u64, PduEvent)>> + 'a> {
|
|
|
|
self.db.threads_until(user_id, room_id, until, include)
|
|
|
|
}
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2024-05-09 15:59:08 -07:00
|
|
|
pub fn add_to_thread(&self, root_event_id: &EventId, pdu: &PduEvent) -> Result<()> {
|
2023-06-25 19:31:40 +02:00
|
|
|
let root_id = &services()
|
|
|
|
.rooms
|
|
|
|
.timeline
|
|
|
|
.get_pdu_id(root_event_id)?
|
|
|
|
.ok_or_else(|| Error::BadRequest(ErrorKind::InvalidParam, "Invalid event id in thread message"))?;
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2023-06-25 19:31:40 +02:00
|
|
|
let root_pdu = services()
|
|
|
|
.rooms
|
|
|
|
.timeline
|
|
|
|
.get_pdu_from_id(root_id)?
|
|
|
|
.ok_or_else(|| Error::BadRequest(ErrorKind::InvalidParam, "Thread root pdu not found"))?;
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2023-06-25 19:31:40 +02:00
|
|
|
let mut root_pdu_json = services()
|
|
|
|
.rooms
|
|
|
|
.timeline
|
|
|
|
.get_pdu_json_from_id(root_id)?
|
|
|
|
.ok_or_else(|| Error::BadRequest(ErrorKind::InvalidParam, "Thread root pdu not found"))?;
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2023-06-25 19:31:40 +02:00
|
|
|
if let CanonicalJsonValue::Object(unsigned) = root_pdu_json
|
|
|
|
.entry("unsigned".to_owned())
|
2024-03-02 20:55:02 -05:00
|
|
|
.or_insert_with(|| CanonicalJsonValue::Object(BTreeMap::default()))
|
2023-06-25 19:31:40 +02:00
|
|
|
{
|
|
|
|
if let Some(mut relations) = unsigned
|
|
|
|
.get("m.relations")
|
|
|
|
.and_then(|r| r.as_object())
|
|
|
|
.and_then(|r| r.get("m.thread"))
|
|
|
|
.and_then(|relations| serde_json::from_value::<BundledThread>(relations.clone().into()).ok())
|
|
|
|
{
|
|
|
|
// Thread already existed
|
2024-07-07 04:46:16 +00:00
|
|
|
relations.count = relations.count.saturating_add(uint!(1));
|
2023-06-25 19:31:40 +02:00
|
|
|
relations.latest_event = pdu.to_message_like_event();
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2023-06-25 19:31:40 +02:00
|
|
|
let content = serde_json::to_value(relations).expect("to_value always works");
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2023-06-25 19:31:40 +02:00
|
|
|
unsigned.insert(
|
|
|
|
"m.relations".to_owned(),
|
2024-03-25 17:05:11 -04:00
|
|
|
json!({ "m.thread": content })
|
|
|
|
.try_into()
|
|
|
|
.expect("thread is valid json"),
|
2023-06-25 19:31:40 +02:00
|
|
|
);
|
|
|
|
} else {
|
|
|
|
// New thread
|
|
|
|
let relations = BundledThread {
|
|
|
|
latest_event: pdu.to_message_like_event(),
|
|
|
|
count: uint!(1),
|
|
|
|
current_user_participated: true,
|
|
|
|
};
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2023-06-25 19:31:40 +02:00
|
|
|
let content = serde_json::to_value(relations).expect("to_value always works");
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2023-06-25 19:31:40 +02:00
|
|
|
unsigned.insert(
|
|
|
|
"m.relations".to_owned(),
|
2024-03-25 17:05:11 -04:00
|
|
|
json!({ "m.thread": content })
|
|
|
|
.try_into()
|
|
|
|
.expect("thread is valid json"),
|
2023-06-25 19:31:40 +02:00
|
|
|
);
|
|
|
|
}
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2024-03-25 17:05:11 -04:00
|
|
|
services()
|
|
|
|
.rooms
|
|
|
|
.timeline
|
|
|
|
.replace_pdu(root_id, &root_pdu_json, &root_pdu)?;
|
2023-06-25 19:31:40 +02:00
|
|
|
}
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2023-06-25 19:31:40 +02:00
|
|
|
let mut users = Vec::new();
|
2023-11-27 00:39:50 -05:00
|
|
|
if let Some(userids) = self.db.get_participants(root_id)? {
|
2023-06-25 19:31:40 +02:00
|
|
|
users.extend_from_slice(&userids);
|
|
|
|
} else {
|
|
|
|
users.push(root_pdu.sender);
|
|
|
|
}
|
2024-06-09 05:15:27 +00:00
|
|
|
users.push(pdu.sender.clone());
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2023-06-25 19:31:40 +02:00
|
|
|
self.db.update_participants(root_id, &users)
|
|
|
|
}
|
|
|
|
}
|