use revolt_models::v0::MessageSort;
use revolt_result::Result;
use crate::{Database, Message, MessageFilter, MessageQuery, MessageTimePeriod, Server, User};
auto_derived!(
pub struct Snapshot {
#[serde(rename = "_id")]
pub id: String,
pub report_id: String,
pub content: SnapshotContent,
}
#[serde(tag = "_type")]
pub enum SnapshotContent {
Message {
#[serde(rename = "_prior_context", default)]
prior_context: Vec<Message>,
#[serde(rename = "_leading_context", default)]
leading_context: Vec<Message>,
#[serde(flatten)]
message: Message,
},
Server(Server),
User(User),
}
);
impl SnapshotContent {
pub async fn generate_from_message(
db: &Database,
message: Message,
) -> Result<(SnapshotContent, Vec<String>)> {
let files = message
.attachments
.as_ref()
.map(|attachments| attachments.iter().map(|x| x.id.to_string()).collect())
.unwrap_or_default();
let prior_context = db
.fetch_messages(MessageQuery {
filter: MessageFilter {
channel: Some(message.channel.to_string()),
..Default::default()
},
limit: Some(15),
time_period: MessageTimePeriod::Absolute {
before: Some(message.id.to_string()),
after: None,
sort: Some(MessageSort::Latest),
},
})
.await?;
let leading_context = db
.fetch_messages(MessageQuery {
filter: MessageFilter {
channel: Some(message.channel.to_string()),
..Default::default()
},
limit: Some(15),
time_period: MessageTimePeriod::Absolute {
before: None,
after: Some(message.id.to_string()),
sort: Some(MessageSort::Oldest),
},
})
.await?;
Ok((
SnapshotContent::Message {
message,
prior_context: prior_context.into_iter().map(Into::into).collect(),
leading_context: leading_context.into_iter().map(Into::into).collect(),
},
files,
))
}
pub fn generate_from_server(server: Server) -> Result<(SnapshotContent, Vec<String>)> {
let files = [&server.icon, &server.banner]
.iter()
.filter_map(|x| x.as_ref().map(|x| x.id.to_string()))
.collect();
Ok((SnapshotContent::Server(server), files))
}
pub fn generate_from_user(user: User) -> Result<(SnapshotContent, Vec<String>)> {
let files = [
user.avatar.as_ref(),
user.profile
.as_ref()
.and_then(|profile| profile.background.as_ref()),
]
.iter()
.filter_map(|x| x.as_ref().map(|x| x.id.to_string()))
.collect();
Ok((SnapshotContent::User(user), files))
}
}