import type { ApiAccountRelationshipSeveranceEventJSON, ApiAccountWarningJSON, ApiAnnualReportEventJSON, BaseNotificationGroupJSON, ApiNotificationGroupJSON, ApiNotificationJSON, NotificationType, NotificationWithStatusType, } from 'mastodon/api_types/notifications'; import type { ApiReportJSON } from 'mastodon/api_types/reports'; // Maximum number of avatars displayed in a notification group // This corresponds to the max lenght of `group.sampleAccountIds` export const NOTIFICATIONS_GROUP_MAX_AVATARS = 8; interface BaseNotificationGroup extends Omit { sampleAccountIds: string[]; } interface BaseNotificationWithStatus extends BaseNotificationGroup { type: Type; statusId: string | undefined; } interface BaseNotification extends BaseNotificationGroup { type: Type; } export type NotificationGroupFavourite = BaseNotificationWithStatus<'favourite'>; export type NotificationGroupReblog = BaseNotificationWithStatus<'reblog'>; export type NotificationGroupStatus = BaseNotificationWithStatus<'status'>; export type NotificationGroupMention = BaseNotificationWithStatus<'mention'>; export type NotificationGroupPoll = BaseNotificationWithStatus<'poll'>; export type NotificationGroupUpdate = BaseNotificationWithStatus<'update'>; export type NotificationGroupFollow = BaseNotification<'follow'>; export type NotificationGroupFollowRequest = BaseNotification<'follow_request'>; export type NotificationGroupAdminSignUp = BaseNotification<'admin.sign_up'>; export type AccountWarningAction = | 'none' | 'disable' | 'mark_statuses_as_sensitive' | 'delete_statuses' | 'sensitive' | 'silence' | 'suspend'; export interface AccountWarning extends Omit { targetAccountId: string; } export interface NotificationGroupModerationWarning extends BaseNotification<'moderation_warning'> { moderationWarning: AccountWarning; } type AccountRelationshipSeveranceEvent = ApiAccountRelationshipSeveranceEventJSON; export interface NotificationGroupSeveredRelationships extends BaseNotification<'severed_relationships'> { event: AccountRelationshipSeveranceEvent; } type AnnualReportEvent = ApiAnnualReportEventJSON; export interface NotificationGroupAnnualReport extends BaseNotification<'annual_report'> { annualReport: AnnualReportEvent; } interface Report extends Omit { targetAccountId: string; } export interface NotificationGroupAdminReport extends BaseNotification<'admin.report'> { report: Report; } export type NotificationGroup = | NotificationGroupFavourite | NotificationGroupReblog | NotificationGroupStatus | NotificationGroupMention | NotificationGroupPoll | NotificationGroupUpdate | NotificationGroupFollow | NotificationGroupFollowRequest | NotificationGroupModerationWarning | NotificationGroupSeveredRelationships | NotificationGroupAdminSignUp | NotificationGroupAdminReport | NotificationGroupAnnualReport; function createReportFromJSON(reportJSON: ApiReportJSON): Report { const { target_account, ...report } = reportJSON; return { targetAccountId: target_account.id, ...report, }; } function createAccountWarningFromJSON( warningJSON: ApiAccountWarningJSON, ): AccountWarning { const { target_account, ...warning } = warningJSON; return { targetAccountId: target_account.id, ...warning, }; } function createAccountRelationshipSeveranceEventFromJSON( eventJson: ApiAccountRelationshipSeveranceEventJSON, ): AccountRelationshipSeveranceEvent { return eventJson; } function createAnnualReportEventFromJSON( eventJson: ApiAnnualReportEventJSON, ): AnnualReportEvent { return eventJson; } export function createNotificationGroupFromJSON( groupJson: ApiNotificationGroupJSON, ): NotificationGroup { const { sample_account_ids: sampleAccountIds, ...group } = groupJson; switch (group.type) { case 'favourite': case 'reblog': case 'status': case 'mention': case 'poll': case 'update': { const { status_id: statusId, ...groupWithoutStatus } = group; return { statusId: statusId ?? undefined, sampleAccountIds, ...groupWithoutStatus, }; } case 'admin.report': { const { report, ...groupWithoutTargetAccount } = group; return { report: createReportFromJSON(report), sampleAccountIds, ...groupWithoutTargetAccount, }; } case 'severed_relationships': return { ...group, event: createAccountRelationshipSeveranceEventFromJSON(group.event), sampleAccountIds, }; case 'moderation_warning': { const { moderation_warning, ...groupWithoutModerationWarning } = group; return { ...groupWithoutModerationWarning, moderationWarning: createAccountWarningFromJSON(moderation_warning), sampleAccountIds, }; } case 'annual_report': { const { annual_report, ...groupWithoutAnnualReport } = group; return { ...groupWithoutAnnualReport, annualReport: createAnnualReportEventFromJSON(annual_report), sampleAccountIds, }; } default: return { sampleAccountIds, ...group, }; } } export function createNotificationGroupFromNotificationJSON( notification: ApiNotificationJSON, ) { const group = { sampleAccountIds: [notification.account.id], group_key: notification.group_key, notifications_count: 1, type: notification.type, most_recent_notification_id: notification.id, page_min_id: notification.id, page_max_id: notification.id, latest_page_notification_at: notification.created_at, } as NotificationGroup; switch (notification.type) { case 'favourite': case 'reblog': case 'status': case 'mention': case 'poll': case 'update': return { ...group, statusId: notification.status?.id }; case 'admin.report': return { ...group, report: createReportFromJSON(notification.report) }; case 'severed_relationships': return { ...group, event: createAccountRelationshipSeveranceEventFromJSON( notification.event, ), }; case 'moderation_warning': return { ...group, moderationWarning: createAccountWarningFromJSON( notification.moderation_warning, ), }; default: return group; } }