284 lines
11 KiB
Rust
284 lines
11 KiB
Rust
use crate::model::data::id::BaseId;
|
|
use crate::model::processing::emoji::EmojiModel;
|
|
use crate::model::processing::note::{NoteModel, NoteVisibilityFilterModel};
|
|
use crate::model::processing::user::UserModel;
|
|
use crate::model::processing::{PackError, PackResult};
|
|
use crate::model::{PackType, PackingContext};
|
|
use crate::web::pagination::Pagination;
|
|
use futures_util::{StreamExt, TryStreamExt};
|
|
use magnetar_calckey_model::ck;
|
|
use magnetar_calckey_model::ck::sea_orm_active_enums::NotificationTypeEnum;
|
|
use magnetar_calckey_model::note_model::NoteResolveOptions;
|
|
use magnetar_calckey_model::notification_model::{NotificationData, NotificationResolveOptions};
|
|
use magnetar_calckey_model::user_model::UserResolveOptions;
|
|
use magnetar_sdk::types::notification::{
|
|
NotificationAppExt, NotificationBase, NotificationNoteExt, NotificationReactionExt,
|
|
NotificationType, NotificationUserExt, PackNotification, PackNotificationApp,
|
|
PackNotificationFollow, PackNotificationFollowRequestAccepted,
|
|
PackNotificationFollowRequestReceived, PackNotificationMention, PackNotificationPollEnd,
|
|
PackNotificationQuote, PackNotificationReaction, PackNotificationRenote, PackNotificationReply,
|
|
};
|
|
use magnetar_sdk::types::Id;
|
|
use magnetar_sdk::{Packed, Required};
|
|
use std::sync::Arc;
|
|
|
|
impl PackType<&NotificationType> for NotificationTypeEnum {
|
|
fn extract(_: &PackingContext, value: &NotificationType) -> Self {
|
|
use NotificationType as NT;
|
|
use NotificationTypeEnum as NTE;
|
|
match value {
|
|
NT::Follow => NTE::Follow,
|
|
NT::FollowRequestReceived => NTE::ReceiveFollowRequest,
|
|
NT::FollowRequestAccepted => NTE::FollowRequestAccepted,
|
|
NT::Mention => NTE::Mention,
|
|
NT::Reply => NTE::Reply,
|
|
NT::Renote => NTE::Renote,
|
|
NT::Reaction => NTE::Reaction,
|
|
NT::Quote => NTE::Quote,
|
|
NT::PollEnd => NTE::PollEnded,
|
|
NT::App => NTE::App,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PackType<&NotificationTypeEnum> for NotificationType {
|
|
fn extract(_: &PackingContext, value: &NotificationTypeEnum) -> Self {
|
|
use NotificationType as NT;
|
|
use NotificationTypeEnum as NTE;
|
|
match value {
|
|
NTE::Follow => NT::Follow,
|
|
NTE::ReceiveFollowRequest => NT::FollowRequestReceived,
|
|
NTE::FollowRequestAccepted => NT::FollowRequestAccepted,
|
|
NTE::Mention => NT::Mention,
|
|
NTE::Reply => NT::Reply,
|
|
NTE::Renote => NT::Renote,
|
|
NTE::Reaction => NT::Reaction,
|
|
NTE::Quote => NT::Quote,
|
|
NTE::PollEnded => NT::PollEnd,
|
|
NTE::App => NT::App,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct NotificationModel;
|
|
|
|
impl NotificationModel {
|
|
async fn pack_notification_single(
|
|
&self,
|
|
ctx: &PackingContext,
|
|
notification_data: &NotificationData,
|
|
note_model: &NoteModel,
|
|
user_model: &UserModel,
|
|
emoji_model: &EmojiModel,
|
|
) -> PackResult<PackNotification> {
|
|
let notification_type =
|
|
NotificationType::extract(ctx, ¬ification_data.notification.r#type);
|
|
let id = Required(Id::from(¬ification_data.notification.id));
|
|
let base = Required(NotificationBase::extract(
|
|
ctx,
|
|
¬ification_data.notification,
|
|
));
|
|
|
|
let notifier = notification_data
|
|
.notifier
|
|
.as_ref()
|
|
.ok_or_else(|| PackError::DataError("Missing notification user".to_string()));
|
|
let note = notification_data
|
|
.notification_note
|
|
.as_ref()
|
|
.ok_or_else(|| PackError::DataError("Missing notification note".to_string()));
|
|
let access_token = notification_data
|
|
.access_token
|
|
.as_ref()
|
|
.ok_or_else(|| PackError::DataError("Missing notification access token".to_string()));
|
|
|
|
Ok(match notification_type {
|
|
NotificationType::Follow => {
|
|
PackNotification::Follow(PackNotificationFollow::pack_from((
|
|
id,
|
|
base,
|
|
Required(NotificationUserExt::extract(
|
|
ctx,
|
|
&user_model.base_from_existing(ctx, ¬ifier?).await?,
|
|
)),
|
|
)))
|
|
}
|
|
NotificationType::FollowRequestReceived => PackNotification::FollowRequestReceived(
|
|
PackNotificationFollowRequestReceived::pack_from((
|
|
id,
|
|
base,
|
|
Required(NotificationUserExt::extract(
|
|
ctx,
|
|
&user_model.base_from_existing(ctx, ¬ifier?).await?,
|
|
)),
|
|
)),
|
|
),
|
|
NotificationType::FollowRequestAccepted => PackNotification::FollowRequestAccepted(
|
|
PackNotificationFollowRequestAccepted::pack_from((
|
|
id,
|
|
base,
|
|
Required(NotificationUserExt::extract(
|
|
ctx,
|
|
&user_model.base_from_existing(ctx, ¬ifier?).await?,
|
|
)),
|
|
)),
|
|
),
|
|
NotificationType::Mention => {
|
|
PackNotification::Mention(PackNotificationMention::pack_from((
|
|
id,
|
|
base,
|
|
Required(NotificationNoteExt::extract(
|
|
ctx,
|
|
¬e_model.pack_full_single(ctx, ¬e?).await?,
|
|
)),
|
|
)))
|
|
}
|
|
NotificationType::Reply => PackNotification::Reply(PackNotificationReply::pack_from((
|
|
id,
|
|
base,
|
|
Required(NotificationNoteExt::extract(
|
|
ctx,
|
|
¬e_model.pack_full_single(ctx, ¬e?).await?,
|
|
)),
|
|
))),
|
|
NotificationType::Renote => {
|
|
PackNotification::Renote(PackNotificationRenote::pack_from((
|
|
id,
|
|
base,
|
|
Required(NotificationNoteExt::extract(
|
|
ctx,
|
|
¬e_model.pack_full_single(ctx, ¬e?).await?,
|
|
)),
|
|
)))
|
|
}
|
|
NotificationType::Reaction => {
|
|
PackNotification::Reaction(PackNotificationReaction::pack_from((
|
|
id,
|
|
base,
|
|
Required(NotificationNoteExt::extract(
|
|
ctx,
|
|
¬e_model.pack_full_single(ctx, ¬e?).await?,
|
|
)),
|
|
Required(NotificationReactionExt::extract(
|
|
ctx,
|
|
&emoji_model
|
|
.resolve_reaction(
|
|
ctx,
|
|
notification_data
|
|
.notification
|
|
.reaction
|
|
.as_deref()
|
|
.ok_or_else(|| {
|
|
PackError::DataError(
|
|
"Missing notification reaction".to_string(),
|
|
)
|
|
})?,
|
|
)
|
|
.await?,
|
|
)),
|
|
Required(NotificationUserExt::extract(
|
|
ctx,
|
|
&user_model.base_from_existing(ctx, ¬ifier?).await?,
|
|
)),
|
|
)))
|
|
}
|
|
NotificationType::Quote => PackNotification::Quote(PackNotificationQuote::pack_from((
|
|
id,
|
|
base,
|
|
Required(NotificationNoteExt::extract(
|
|
ctx,
|
|
¬e_model.pack_full_single(ctx, ¬e?).await?,
|
|
)),
|
|
))),
|
|
NotificationType::PollEnd => {
|
|
PackNotification::PollEnd(PackNotificationPollEnd::pack_from((
|
|
id,
|
|
base,
|
|
Required(NotificationNoteExt::extract(
|
|
ctx,
|
|
¬e_model.pack_full_single(ctx, ¬e?).await?,
|
|
)),
|
|
)))
|
|
}
|
|
NotificationType::App => PackNotification::App(PackNotificationApp::pack_from((
|
|
id,
|
|
base,
|
|
Required(NotificationAppExt::extract(
|
|
ctx,
|
|
(¬ification_data.notification, access_token?),
|
|
)),
|
|
))),
|
|
})
|
|
}
|
|
|
|
pub async fn get_notifications(
|
|
&self,
|
|
ctx: &PackingContext,
|
|
id: &str,
|
|
notification_types: &[NotificationType],
|
|
unread_only: bool,
|
|
pagination: &mut Pagination,
|
|
) -> PackResult<Vec<PackNotification>> {
|
|
let user_resolve_options = UserResolveOptions {
|
|
with_avatar: true,
|
|
with_banner: false,
|
|
with_profile: false,
|
|
};
|
|
|
|
let self_id = ctx.self_user.as_deref().map(ck::user::Model::get_id);
|
|
let notifications_raw = ctx
|
|
.service
|
|
.db
|
|
.get_notification_resolver()
|
|
.get(
|
|
&NotificationResolveOptions {
|
|
note_options: NoteResolveOptions {
|
|
ids: None,
|
|
visibility_filter: Arc::new(
|
|
NoteVisibilityFilterModel.new_note_visibility_filter(Some(id)),
|
|
),
|
|
time_range: None,
|
|
limit: None,
|
|
with_reply_target: true,
|
|
with_renote_target: true,
|
|
with_interactions_from: self_id.map(str::to_string),
|
|
only_pins_from: None,
|
|
user_options: user_resolve_options.clone(),
|
|
},
|
|
user_options: user_resolve_options,
|
|
},
|
|
id,
|
|
¬ification_types
|
|
.iter()
|
|
.map(|v| NotificationTypeEnum::extract(ctx, v))
|
|
.collect::<Vec<_>>(),
|
|
unread_only,
|
|
&pagination.current,
|
|
&mut pagination.prev,
|
|
&mut pagination.next,
|
|
pagination.limit.into(),
|
|
)
|
|
.await?;
|
|
|
|
let note_model = NoteModel {
|
|
with_context: true,
|
|
attachments: false,
|
|
};
|
|
let user_model = UserModel;
|
|
let emoji_model = EmojiModel;
|
|
|
|
let fut_iter = notifications_raw
|
|
.iter()
|
|
.map(|n| self.pack_notification_single(ctx, n, ¬e_model, &user_model, &emoji_model))
|
|
.collect::<Vec<_>>();
|
|
|
|
let processed = futures::stream::iter(fut_iter)
|
|
.buffered(10)
|
|
.err_into::<PackError>()
|
|
.try_collect::<Vec<_>>()
|
|
.await?;
|
|
|
|
Ok(processed)
|
|
}
|
|
}
|