170 lines
4.3 KiB
TypeScript
170 lines
4.3 KiB
TypeScript
import omit from 'lodash/omit';
|
|
|
|
import type {
|
|
AccountWarning,
|
|
Account as BaseAccount,
|
|
Notification as BaseNotification,
|
|
RelationshipSeveranceEvent,
|
|
} from 'pl-api';
|
|
|
|
type DeduplicatedNotification = BaseNotification & {
|
|
accounts: Array<BaseAccount>;
|
|
duplicate?: boolean;
|
|
};
|
|
|
|
const STATUS_NOTIFICATION_TYPES = [
|
|
'mention',
|
|
'status',
|
|
'reblog',
|
|
'favourite',
|
|
'poll',
|
|
'update',
|
|
'emoji_reaction',
|
|
'event_reminder',
|
|
'participation_accepted',
|
|
'participation_request',
|
|
];
|
|
|
|
const getNotificationStatus = (n: Pick<BaseNotification, 'type'>) => {
|
|
if (STATUS_NOTIFICATION_TYPES.includes(n.type))
|
|
// @ts-ignore
|
|
return n.status;
|
|
return null;
|
|
};
|
|
|
|
const deduplicateNotifications = (
|
|
notifications: Array<BaseNotification>,
|
|
): Array<DeduplicatedNotification> => {
|
|
const deduplicatedNotifications: DeduplicatedNotification[] = [];
|
|
|
|
for (const notification of notifications) {
|
|
if (STATUS_NOTIFICATION_TYPES.includes(notification.type)) {
|
|
const existingNotification = deduplicatedNotifications.find(
|
|
(deduplicated) =>
|
|
deduplicated.type === notification.type &&
|
|
(notification.type === 'emoji_reaction' && deduplicated.type === 'emoji_reaction'
|
|
? notification.emoji === deduplicated.emoji
|
|
: true) &&
|
|
getNotificationStatus(deduplicated)?.id === getNotificationStatus(notification)?.id,
|
|
);
|
|
|
|
if (existingNotification) {
|
|
existingNotification.accounts.push(notification.account);
|
|
deduplicatedNotifications.push({
|
|
...notification,
|
|
accounts: [notification.account],
|
|
duplicate: true,
|
|
});
|
|
} else {
|
|
deduplicatedNotifications.push({
|
|
...notification,
|
|
accounts: [notification.account],
|
|
duplicate: false,
|
|
});
|
|
}
|
|
} else {
|
|
deduplicatedNotifications.push({
|
|
...notification,
|
|
accounts: [notification.account],
|
|
duplicate: false,
|
|
});
|
|
}
|
|
}
|
|
|
|
return deduplicatedNotifications;
|
|
};
|
|
|
|
const normalizeNotification = (notification: BaseNotification | DeduplicatedNotification) => {
|
|
// @ts-ignore
|
|
const minifiedNotification: {
|
|
duplicate: boolean;
|
|
account_id: string;
|
|
account_ids: string[];
|
|
created_at: string;
|
|
id: string;
|
|
group_key: string;
|
|
} & (
|
|
| { type: 'follow' | 'follow_request' | 'admin.sign_up' | 'bite' }
|
|
| {
|
|
type: 'mention';
|
|
subtype?: 'reply';
|
|
status_id: string;
|
|
}
|
|
| {
|
|
type:
|
|
| 'status'
|
|
| 'reblog'
|
|
| 'favourite'
|
|
| 'poll'
|
|
| 'update'
|
|
| 'event_reminder'
|
|
| 'quote'
|
|
| 'quoted_update';
|
|
status_id: string;
|
|
}
|
|
| {
|
|
type: 'admin.report';
|
|
report: Report;
|
|
}
|
|
| {
|
|
type: 'severed_relationships';
|
|
relationship_severance_event: RelationshipSeveranceEvent;
|
|
}
|
|
| {
|
|
type: 'moderation_warning';
|
|
moderation_warning: AccountWarning;
|
|
}
|
|
| {
|
|
type: 'move';
|
|
target_id: string;
|
|
}
|
|
| {
|
|
type: 'emoji_reaction';
|
|
emoji: string;
|
|
emoji_url: string | null;
|
|
status_id: string;
|
|
}
|
|
| {
|
|
type: 'chat_mention';
|
|
chat_message_id: string;
|
|
}
|
|
| {
|
|
type: 'participation_accepted' | 'participation_request';
|
|
status_id: string;
|
|
participation_message: string | null;
|
|
}
|
|
) = {
|
|
duplicate: false,
|
|
...omit(notification, ['account', 'accounts', 'status', 'target', 'chat_message']),
|
|
account_id: notification.account.id,
|
|
account_ids:
|
|
'accounts' in notification
|
|
? notification.accounts.map(({ id }) => id)
|
|
: [notification.account.id],
|
|
created_at: notification.created_at,
|
|
id: notification.id,
|
|
type: notification.type,
|
|
};
|
|
|
|
// @ts-ignore
|
|
if (notification.status) minifiedNotification.status_id = notification.status.id;
|
|
// @ts-ignore
|
|
if (notification.target) minifiedNotification.target_id = notification.target.id;
|
|
// @ts-ignore
|
|
if (notification.chat_message)
|
|
// @ts-ignore
|
|
minifiedNotification.chat_message_id = notification.chat_message.id;
|
|
|
|
return minifiedNotification;
|
|
};
|
|
|
|
type NormalizedNotification = ReturnType<typeof normalizeNotification>;
|
|
|
|
export {
|
|
deduplicateNotifications,
|
|
getNotificationStatus,
|
|
normalizeNotification,
|
|
type DeduplicatedNotification,
|
|
type NormalizedNotification,
|
|
};
|