// SPDX-License-Identifier: AGPL-3.0-or-later import type {UserID} from '@app/api/BrandedTypes'; import {Db, type DbOp} from '@app/api/database/CassandraTypes'; import type {ChannelRow, PrivateChannelRow} from '@app/api/database/types/ChannelTypes'; import {type ChannelType, ChannelTypes} from '@fluxer/constants/src/ChannelConstants'; type SnapshotPatch = Partial<{ is_gdm: DbOp; channel_type: DbOp; channel_name: DbOp; channel_icon_hash: DbOp; channel_owner_id: DbOp; channel_recipient_ids: DbOp | null>; channel_last_message_id: DbOp; channel_last_pin_timestamp: DbOp; channel_nicks: DbOp | null>; channel_rate_limit_per_user: DbOp; channel_nsfw: DbOp; channel_version: DbOp; snapshot_at: DbOp; }>; export function isPrivateChannelType(type: number): boolean { return type === ChannelTypes.DM || type === ChannelTypes.GROUP_DM || type === ChannelTypes.DM_PERSONAL_NOTES; } export function privateChannelFanOutTargets(row: ChannelRow): Array { if (!isPrivateChannelType(row.type)) { return []; } const targets = new Set(row.recipient_ids ?? []); if (row.type === ChannelTypes.DM_PERSONAL_NOTES && row.owner_id != null) { targets.add(row.owner_id); } return Array.from(targets); } function nonEmptySet(value: Set | null | undefined): Set | null { return value && value.size > 0 ? value : null; } function nonEmptyMap(value: Map | null | undefined): Map | null { return value && value.size > 0 ? value : null; } function snapshotMetadataPatch(row: ChannelRow): SnapshotPatch { return { is_gdm: Db.set(row.type === ChannelTypes.GROUP_DM), channel_type: Db.set(row.type), channel_name: Db.set(row.name ?? null), channel_icon_hash: Db.set(row.icon_hash ?? null), channel_owner_id: Db.set(row.owner_id ?? null), channel_recipient_ids: Db.set(nonEmptySet(row.recipient_ids)), channel_last_pin_timestamp: Db.set(row.last_pin_timestamp ?? null), channel_nicks: Db.set(nonEmptyMap(row.nicks)), channel_rate_limit_per_user: Db.set(row.rate_limit_per_user ?? null), channel_nsfw: Db.set(row.nsfw ?? null), channel_version: Db.set(row.version ?? 0), }; } export function privateChannelMetadataPatch(row: ChannelRow): SnapshotPatch { return snapshotMetadataPatch(row); } export function privateChannelHydrationPatch(row: ChannelRow, hydratedAt: Date): SnapshotPatch { return { ...snapshotMetadataPatch(row), channel_last_message_id: Db.set(row.last_message_id ?? null), snapshot_at: Db.set(hydratedAt), }; } export function privateChannelLastMessageIdPatch(messageId: ChannelRow['last_message_id']): SnapshotPatch { return {channel_last_message_id: Db.set(messageId)}; } export function channelRowFromPrivateChannelSnapshot(row: PrivateChannelRow): ChannelRow | null { if (row.snapshot_at == null || row.channel_type == null) { return null; } return { channel_id: row.channel_id, guild_id: null, type: row.channel_type as ChannelType, name: row.channel_name ?? null, topic: null, icon_hash: row.channel_icon_hash ?? null, url: null, parent_id: null, position: null, owner_id: row.channel_owner_id ?? null, recipient_ids: row.channel_recipient_ids ?? null, nsfw: row.channel_nsfw ?? null, content_warning_level: null, content_warning_text: null, rate_limit_per_user: row.channel_rate_limit_per_user ?? null, bitrate: null, user_limit: null, voice_connection_limit: null, rtc_region: null, rtc_p2p: null, last_message_id: row.channel_last_message_id ?? null, last_pin_timestamp: row.channel_last_pin_timestamp ?? null, permission_overwrites: null, nicks: row.channel_nicks ?? null, soft_deleted: false, indexed_at: null, version: row.channel_version ?? 0, }; }