Files
GMW/services/backend/src/shared/utils/messageMapper.ts
T
asepharyana 8049b70738 fix: render server nick per user in messages tab and analysis
Extract server_nick from metadata.member.displayName in backend messageMapper,
add server_nick to frontend MessageRecord type, and update messages view +
analysis view to display the member's server-specific nickname (with @username
as secondary context) instead of the global username.
2026-08-27 14:38:05 +07:00

93 lines
3.6 KiB
TypeScript

// Shared message row mapper for backend repository modules
function resolveServerNick(row: Record<string, unknown>): string | null {
const metadata = row.metadata;
if (!metadata || typeof metadata !== "string") {
return (row.username as string | null) ?? null;
}
try {
const parsed = JSON.parse(metadata) as {
member?: { displayName?: string | null } | null;
};
return (
parsed?.member?.displayName ?? (row.username as string | null) ?? null
);
} catch {
return (row.username as string | null) ?? null;
}
}
export interface MappedMessage {
id: string;
guild_id: string;
channel_id: string;
thread_id: string | null;
user_id: string;
username: string;
/** Member's server-specific display name (nickname), from metadata.member.displayName. Falls back to username when absent. */
server_nick: string | null;
avatar_url: string | null;
content: string;
edited_content: string | null;
created_at: number;
edited_at: number | null;
deleted_at: number | null;
type: string;
metadata: string | null;
ai_status: string | null;
ai_moderation_flags: string | null;
ai_moderation_score: number | null;
ai_analysis: string | null;
ai_categories: string | null;
ai_severity: string | null;
ai_confidence: number | null;
ai_recommended_action: string | null;
ai_analyzed_at: number | null;
ai_analysis_duration_ms: number | null;
ai_error: string | null;
is_reply: boolean | null;
is_forward: boolean | null;
is_crosspost: boolean | null;
reference_message_id: string | null;
reference_channel_id: string | null;
reference_guild_id: string | null;
}
export function mapMessageRow(row: Record<string, unknown>): MappedMessage {
return {
id: String(row.id ?? ""),
guild_id: String(row.guild_id ?? ""),
channel_id: String(row.channel_id ?? ""),
thread_id: (row.thread_id as string | null) ?? null,
user_id: String(row.user_id ?? ""),
username: String(row.username ?? ""),
server_nick: resolveServerNick(row),
avatar_url: (row.avatar_url as string | null) ?? null,
content: String(row.content ?? ""),
edited_content: (row.edited_content as string | null) ?? null,
created_at: Number(row.created_at ?? 0),
edited_at: (row.edited_at as number | null) ?? null,
deleted_at: (row.deleted_at as number | null) ?? null,
type: String(row.type ?? "text"),
metadata: (row.metadata as string | null) ?? null,
ai_status: (row.ai_status as string | null) ?? null,
ai_moderation_flags: (row.ai_moderation_flags as string | null) ?? null,
ai_moderation_score: (row.ai_moderation_score as number | null) ?? null,
ai_analysis: (row.ai_analysis as string | null) ?? null,
ai_categories: (row.ai_categories as string | null) ?? null,
ai_severity: (row.ai_severity as string | null) ?? null,
ai_confidence: (row.ai_confidence as number | null) ?? null,
ai_recommended_action: (row.ai_recommended_action as string | null) ?? null,
ai_analyzed_at: (row.ai_analyzed_at as number | null) ?? null,
ai_analysis_duration_ms:
(row.ai_analysis_duration_ms as number | null) ?? null,
ai_error: (row.ai_error as string | null) ?? null,
is_reply: row.is_reply === null ? null : Boolean(row.is_reply),
is_forward: row.is_forward === null ? null : Boolean(row.is_forward),
is_crosspost: row.is_crosspost === null ? null : Boolean(row.is_crosspost),
reference_message_id: (row.reference_message_id as string | null) ?? null,
reference_channel_id: (row.reference_channel_id as string | null) ?? null,
reference_guild_id: (row.reference_guild_id as string | null) ?? null,
};
}