mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-12 05:28:28 +09:00
244 lines
9.5 KiB
TypeScript
244 lines
9.5 KiB
TypeScript
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
import {mapGuildFeatures} from '@app/api/guild/GuildFeatureUtils';
|
|
import {
|
|
stripGuildBannerForFeatures,
|
|
stripGuildIconForFeatures,
|
|
stripGuildSplashForFeatures,
|
|
} from '@app/api/infrastructure/AssetEntitlementUtils';
|
|
import type {UserCacheService} from '@app/api/infrastructure/UserCacheService';
|
|
import type {RequestCache} from '@app/api/middleware/RequestCacheMiddleware';
|
|
import type {Guild} from '@app/api/models/Guild';
|
|
import type {GuildBan} from '@app/api/models/GuildBan';
|
|
import type {GuildEmoji} from '@app/api/models/GuildEmoji';
|
|
import type {GuildMember} from '@app/api/models/GuildMember';
|
|
import type {GuildRole} from '@app/api/models/GuildRole';
|
|
import type {GuildSticker} from '@app/api/models/GuildSticker';
|
|
import {hiddenGuildMember, isHiddenPartial} from '@app/api/user/ProfileVisibility';
|
|
import {getCachedUserPartialResponse, getCachedUserPartialResponses} from '@app/api/user/UserCacheHelpers';
|
|
import type {
|
|
GuildEmojiResponse,
|
|
GuildEmojiWithUserResponse,
|
|
GuildStickerResponse,
|
|
GuildStickerWithUserResponse,
|
|
} from '@fluxer/schema/src/domains/guild/GuildEmojiSchemas';
|
|
import type {GuildBanResponse, GuildMemberResponse} from '@fluxer/schema/src/domains/guild/GuildMemberSchemas';
|
|
import type {GuildPartialResponse, GuildResponse} from '@fluxer/schema/src/domains/guild/GuildResponseSchemas';
|
|
import type {GuildRoleResponse} from '@fluxer/schema/src/domains/guild/GuildRoleSchemas';
|
|
import type {UserPartialResponse} from '@fluxer/schema/src/domains/user/UserResponseSchemas';
|
|
|
|
export function mapGuildToPartialResponse(guild: Guild): GuildPartialResponse {
|
|
const guildId = guild.id.toString();
|
|
const iconHash = stripGuildIconForFeatures(guild.iconHash, guild.features);
|
|
const bannerHash = stripGuildBannerForFeatures(guild.bannerHash, guild.features);
|
|
const splashHash = stripGuildSplashForFeatures(guild.splashHash, guild.features);
|
|
const embedSplashHash = stripGuildSplashForFeatures(guild.embedSplashHash, guild.features);
|
|
return {
|
|
id: guildId,
|
|
name: guild.name,
|
|
icon: iconHash,
|
|
banner: bannerHash,
|
|
banner_width: bannerHash ? guild.bannerWidth : null,
|
|
banner_height: bannerHash ? guild.bannerHeight : null,
|
|
splash: splashHash,
|
|
splash_width: splashHash ? guild.splashWidth : null,
|
|
splash_height: splashHash ? guild.splashHeight : null,
|
|
embed_splash: embedSplashHash,
|
|
embed_splash_width: embedSplashHash ? guild.embedSplashWidth : null,
|
|
embed_splash_height: embedSplashHash ? guild.embedSplashHeight : null,
|
|
splash_card_alignment: guild.splashCardAlignment,
|
|
features: mapGuildFeatures(guild.features),
|
|
};
|
|
}
|
|
|
|
export function mapGuildToGuildResponse(
|
|
guild: Guild,
|
|
options?: {
|
|
permissions?: bigint | null;
|
|
},
|
|
): GuildResponse {
|
|
const iconHash = stripGuildIconForFeatures(guild.iconHash, guild.features);
|
|
const bannerHash = stripGuildBannerForFeatures(guild.bannerHash, guild.features);
|
|
const splashHash = stripGuildSplashForFeatures(guild.splashHash, guild.features);
|
|
const embedSplashHash = stripGuildSplashForFeatures(guild.embedSplashHash, guild.features);
|
|
return {
|
|
id: guild.id.toString(),
|
|
name: guild.name,
|
|
icon: iconHash,
|
|
banner: bannerHash,
|
|
banner_width: bannerHash ? guild.bannerWidth : null,
|
|
banner_height: bannerHash ? guild.bannerHeight : null,
|
|
splash: splashHash,
|
|
splash_width: splashHash ? guild.splashWidth : null,
|
|
splash_height: splashHash ? guild.splashHeight : null,
|
|
embed_splash: embedSplashHash,
|
|
embed_splash_width: embedSplashHash ? guild.embedSplashWidth : null,
|
|
embed_splash_height: embedSplashHash ? guild.embedSplashHeight : null,
|
|
splash_card_alignment: guild.splashCardAlignment,
|
|
vanity_url_code: guild.vanityUrlCode,
|
|
owner_id: guild.ownerId.toString(),
|
|
system_channel_id: guild.systemChannelId ? guild.systemChannelId.toString() : null,
|
|
system_channel_flags: guild.systemChannelFlags,
|
|
rules_channel_id: guild.rulesChannelId ? guild.rulesChannelId.toString() : null,
|
|
afk_channel_id: guild.afkChannelId ? guild.afkChannelId.toString() : null,
|
|
afk_timeout: guild.afkTimeout,
|
|
features: mapGuildFeatures(guild.features),
|
|
verification_level: guild.verificationLevel,
|
|
mfa_level: guild.mfaLevel,
|
|
nsfw_level: guild.nsfwLevel,
|
|
nsfw: guild.nsfw,
|
|
content_warning_level: guild.contentWarningLevel as 0 | 1,
|
|
content_warning_text: guild.contentWarningText,
|
|
explicit_content_filter: guild.explicitContentFilter,
|
|
default_message_notifications: guild.defaultMessageNotifications,
|
|
disabled_operations: guild.disabledOperations,
|
|
message_history_cutoff: guild.messageHistoryCutoff ? guild.messageHistoryCutoff.toISOString() : null,
|
|
permissions: options?.permissions != null ? options.permissions.toString() : undefined,
|
|
};
|
|
}
|
|
|
|
export function mapGuildRoleToResponse(role: GuildRole): GuildRoleResponse {
|
|
return {
|
|
id: role.id.toString(),
|
|
name: role.name,
|
|
color: role.color,
|
|
position: role.position,
|
|
hoist_position: role.hoistPosition,
|
|
permissions: role.permissions.toString(),
|
|
hoist: role.isHoisted,
|
|
mentionable: role.isMentionable,
|
|
};
|
|
}
|
|
|
|
export function mapGuildEmojiToResponse(emoji: GuildEmoji): GuildEmojiResponse {
|
|
const id = emoji.id.toString();
|
|
return {
|
|
id,
|
|
name: emoji.name,
|
|
animated: emoji.isAnimated,
|
|
nsfw: false,
|
|
};
|
|
}
|
|
|
|
export function mapGuildStickerToResponse(sticker: GuildSticker): GuildStickerResponse {
|
|
const id = sticker.id.toString();
|
|
return {
|
|
id,
|
|
name: sticker.name,
|
|
description: sticker.description ?? '',
|
|
tags: sticker.tags,
|
|
animated: sticker.animated,
|
|
nsfw: false,
|
|
};
|
|
}
|
|
|
|
function mapMemberWithUser(member: GuildMember, userPartial: UserPartialResponse): GuildMemberResponse {
|
|
const response = mapMemberFields(member, userPartial);
|
|
return isHiddenPartial(userPartial) ? hiddenGuildMember(response) : response;
|
|
}
|
|
|
|
function mapMemberFields(member: GuildMember, userPartial: UserPartialResponse): GuildMemberResponse {
|
|
const now = Date.now();
|
|
const isTimedOut = member.communicationDisabledUntil != null && member.communicationDisabledUntil.getTime() > now;
|
|
return {
|
|
user: userPartial,
|
|
nick: member.nickname,
|
|
avatar: member.isPremiumSanitized ? null : member.avatarHash,
|
|
banner: member.isPremiumSanitized ? null : member.bannerHash,
|
|
accent_color: member.accentColor,
|
|
roles: Array.from(member.roleIds).map((id) => id.toString()),
|
|
joined_at: member.joinedAt.toISOString(),
|
|
mute: isTimedOut ? true : member.isMute,
|
|
deaf: member.isDeaf,
|
|
communication_disabled_until: member.communicationDisabledUntil?.toISOString() ?? null,
|
|
profile_flags: member.profileFlags || undefined,
|
|
mention_flags: member.mentionFlags || undefined,
|
|
};
|
|
}
|
|
|
|
export function isGuildMemberTimedOut(member?: GuildMemberResponse | null): boolean {
|
|
if (!member?.communication_disabled_until) {
|
|
return false;
|
|
}
|
|
const timestamp = Date.parse(member.communication_disabled_until);
|
|
return !Number.isNaN(timestamp) && timestamp > Date.now();
|
|
}
|
|
|
|
export async function mapGuildMemberToResponse(
|
|
member: GuildMember,
|
|
userCacheService: Pick<UserCacheService, 'getUserPartialResponse'>,
|
|
requestCache: RequestCache,
|
|
): Promise<GuildMemberResponse> {
|
|
const userPartial = await getCachedUserPartialResponse({userId: member.userId, userCacheService, requestCache});
|
|
return mapMemberWithUser(member, userPartial);
|
|
}
|
|
|
|
function mapEmojiWithUser(emoji: GuildEmoji, userPartial: UserPartialResponse): GuildEmojiWithUserResponse {
|
|
const id = emoji.id.toString();
|
|
return {
|
|
id,
|
|
name: emoji.name,
|
|
animated: emoji.isAnimated,
|
|
nsfw: false,
|
|
user: userPartial,
|
|
};
|
|
}
|
|
|
|
export async function mapGuildEmojisWithUsersToResponse(
|
|
emojis: Array<GuildEmoji>,
|
|
userCacheService: Pick<UserCacheService, 'getUserPartialResponses'>,
|
|
requestCache: RequestCache,
|
|
): Promise<Array<GuildEmojiWithUserResponse>> {
|
|
const userIds = [...new Set(emojis.map((emoji) => emoji.creatorId))];
|
|
const userPartials = await getCachedUserPartialResponses({userIds, userCacheService, requestCache});
|
|
return emojis
|
|
.filter((emoji) => userPartials.has(emoji.creatorId))
|
|
.map((emoji) => mapEmojiWithUser(emoji, userPartials.get(emoji.creatorId)!));
|
|
}
|
|
|
|
function mapStickerWithUser(sticker: GuildSticker, userPartial: UserPartialResponse): GuildStickerWithUserResponse {
|
|
return {
|
|
id: sticker.id.toString(),
|
|
name: sticker.name,
|
|
description: sticker.description ?? '',
|
|
tags: sticker.tags,
|
|
animated: sticker.animated,
|
|
nsfw: false,
|
|
user: userPartial,
|
|
};
|
|
}
|
|
|
|
export async function mapGuildStickersWithUsersToResponse(
|
|
stickers: Array<GuildSticker>,
|
|
userCacheService: Pick<UserCacheService, 'getUserPartialResponses'>,
|
|
requestCache: RequestCache,
|
|
): Promise<Array<GuildStickerWithUserResponse>> {
|
|
const userIds = [...new Set(stickers.map((sticker) => sticker.creatorId))];
|
|
const userPartials = await getCachedUserPartialResponses({userIds, userCacheService, requestCache});
|
|
return stickers
|
|
.filter((sticker) => userPartials.has(sticker.creatorId))
|
|
.map((sticker) => mapStickerWithUser(sticker, userPartials.get(sticker.creatorId)!));
|
|
}
|
|
|
|
function mapBanWithUser(ban: GuildBan, userPartial: UserPartialResponse): GuildBanResponse {
|
|
return {
|
|
user: userPartial,
|
|
reason: ban.reason,
|
|
moderator_id: ban.moderatorId.toString(),
|
|
banned_at: ban.bannedAt.toISOString(),
|
|
expires_at: ban.expiresAt ? ban.expiresAt.toISOString() : null,
|
|
};
|
|
}
|
|
|
|
export async function mapGuildBansToResponse(
|
|
bans: Array<GuildBan>,
|
|
userCacheService: Pick<UserCacheService, 'getUserPartialResponses'>,
|
|
requestCache: RequestCache,
|
|
): Promise<Array<GuildBanResponse>> {
|
|
const userIds = [...new Set(bans.map((ban) => ban.userId))];
|
|
const userPartials = await getCachedUserPartialResponses({userIds, userCacheService, requestCache});
|
|
return bans
|
|
.filter((ban) => userPartials.has(ban.userId))
|
|
.map((ban) => mapBanWithUser(ban, userPartials.get(ban.userId)!));
|
|
}
|