Files
ncd-fe/packages/pl-hooks/lib/normalizers/notification.ts
nicole mikołajczyk bbf0325146 pl-hooks: migrate from eslint
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2026-02-24 14:01:33 +01:00

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,
};