diff --git a/backend/src/plugins/Cases/functions/createCase.ts b/backend/src/plugins/Cases/functions/createCase.ts index c16d937b..140ddce4 100644 --- a/backend/src/plugins/Cases/functions/createCase.ts +++ b/backend/src/plugins/Cases/functions/createCase.ts @@ -11,7 +11,7 @@ export async function createCase(pluginData: GuildPluginData, a const userName = renderUserUsername(user); const mod = await resolveUser(pluginData.client, args.modId); - const modName = mod.tag; + const modName = renderUserUsername(mod); let ppName: string | null = null; let ppId: Snowflake | null = null; diff --git a/backend/src/plugins/Cases/functions/createCaseNote.ts b/backend/src/plugins/Cases/functions/createCaseNote.ts index 92520b7d..a699908c 100644 --- a/backend/src/plugins/Cases/functions/createCaseNote.ts +++ b/backend/src/plugins/Cases/functions/createCaseNote.ts @@ -1,6 +1,6 @@ import { GuildPluginData } from "knub"; import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError"; -import { UnknownUser, resolveUser } from "../../../utils"; +import { UnknownUser, renderUserUsername, resolveUser } from "../../../utils"; import { CaseNoteArgs, CasesPluginType } from "../types"; import { postCaseToCaseLogChannel } from "./postToCaseLogChannel"; import { resolveCaseId } from "./resolveCaseId"; @@ -16,7 +16,7 @@ export async function createCaseNote(pluginData: GuildPluginData ({ diff --git a/backend/src/plugins/ModActions/commands/CasesModCmd.ts b/backend/src/plugins/ModActions/commands/CasesModCmd.ts index 5b0e3273..faaad2d1 100644 --- a/backend/src/plugins/ModActions/commands/CasesModCmd.ts +++ b/backend/src/plugins/ModActions/commands/CasesModCmd.ts @@ -1,7 +1,7 @@ -import { APIEmbed, User } from "discord.js"; +import { APIEmbed, GuildMember, User } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; import { sendErrorMessage } from "../../../pluginUtils"; -import { emptyEmbedValue, resolveUser, trimLines } from "../../../utils"; +import { emptyEmbedValue, renderUserUsername, resolveMember, resolveUser, trimLines } from "../../../utils"; import { asyncMap } from "../../../utils/async"; import { createPaginatedMessage } from "../../../utils/createPaginatedMessage"; import { getChunkedEmbedFields } from "../../../utils/getChunkedEmbedFields"; @@ -28,8 +28,10 @@ export const CasesModCmd = modActionsCmd({ async run({ pluginData, message: msg, args }) { const modId = args.mod || msg.author.id; - const mod = await resolveUser(pluginData.client, modId); - const modName = mod instanceof User ? mod.tag : modId; + const mod = + (await resolveMember(pluginData.client, pluginData.guild, modId)) || + (await resolveUser(pluginData.client, modId)); + const modName = mod instanceof User || mod instanceof GuildMember ? renderUserUsername(mod) : modId; const casesPlugin = pluginData.getPlugin(CasesPlugin); const totalCases = await casesPlugin.getTotalCasesByMod(modId); @@ -57,7 +59,7 @@ export const CasesModCmd = modActionsCmd({ const embed = { author: { name: title, - icon_url: mod instanceof User ? mod.displayAvatarURL() : undefined, + icon_url: mod instanceof GuildMember || mod instanceof User ? mod.displayAvatarURL() : undefined, }, fields: [ ...getChunkedEmbedFields(emptyEmbedValue, lines.join("\n")), diff --git a/backend/src/plugins/ModActions/commands/CasesUserCmd.ts b/backend/src/plugins/ModActions/commands/CasesUserCmd.ts index 069ad31f..3afc957a 100644 --- a/backend/src/plugins/ModActions/commands/CasesUserCmd.ts +++ b/backend/src/plugins/ModActions/commands/CasesUserCmd.ts @@ -1,9 +1,17 @@ -import { APIEmbed, User } from "discord.js"; +import { APIEmbed, GuildMember, User } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; import { CaseTypes } from "../../../data/CaseTypes"; import { sendErrorMessage } from "../../../pluginUtils"; import { CasesPlugin } from "../../../plugins/Cases/CasesPlugin"; -import { UnknownUser, chunkArray, emptyEmbedValue, renderUserUsername, resolveUser, trimLines } from "../../../utils"; +import { + UnknownUser, + chunkArray, + emptyEmbedValue, + renderUserUsername, + resolveMember, + resolveUser, + trimLines, +} from "../../../utils"; import { asyncMap } from "../../../utils/async"; import { getChunkedEmbedFields } from "../../../utils/getChunkedEmbedFields"; import { getGuildPrefix } from "../../../utils/getGuildPrefix"; @@ -35,7 +43,9 @@ export const CasesUserCmd = modActionsCmd({ ], async run({ pluginData, message: msg, args }) { - const user = await resolveUser(pluginData.client, args.user); + const user = + (await resolveMember(pluginData.client, pluginData.guild, args.user)) || + (await resolveUser(pluginData.client, args.user)); if (!user.id) { sendErrorMessage(pluginData, msg.channel, `User not found`); return; @@ -123,7 +133,7 @@ export const CasesUserCmd = modActionsCmd({ lineChunks.length === 1 ? `Cases for ${userName} (${lines.length} total)` : `Cases ${chunkStart}–${chunkEnd} of ${lines.length} for ${userName}`, - icon_url: user instanceof User ? user.displayAvatarURL() : undefined, + icon_url: user instanceof GuildMember || user instanceof User ? user.displayAvatarURL() : undefined, }, fields: [ ...getChunkedEmbedFields(emptyEmbedValue, linesInChunk.join("\n")), diff --git a/backend/src/plugins/Starboard/util/createStarboardEmbedFromMessage.ts b/backend/src/plugins/Starboard/util/createStarboardEmbedFromMessage.ts index 5f028c0a..d35e694f 100644 --- a/backend/src/plugins/Starboard/util/createStarboardEmbedFromMessage.ts +++ b/backend/src/plugins/Starboard/util/createStarboardEmbedFromMessage.ts @@ -1,6 +1,6 @@ import { GuildChannel, Message } from "discord.js"; import path from "path"; -import { EMPTY_CHAR, EmbedWith } from "../../../utils"; +import { EMPTY_CHAR, EmbedWith, renderUserUsername } from "../../../utils"; const imageAttachmentExtensions = ["jpeg", "jpg", "png", "gif", "webp"]; const audioAttachmentExtensions = ["wav", "mp3", "m4a"]; @@ -18,7 +18,7 @@ export function createStarboardEmbedFromMessage( text: `#${(msg.channel as GuildChannel).name}`, }, author: { - name: msg.author.tag, + name: renderUserUsername(msg.author), }, fields: [], timestamp: msg.createdAt.toISOString(), @@ -28,7 +28,7 @@ export function createStarboardEmbedFromMessage( embed.color = color; } - embed.author.icon_url = msg.author.displayAvatarURL(); + embed.author.icon_url = (msg.member || msg.author).displayAvatarURL(); // The second condition here checks for messages with only an image link that is then embedded. // The message content in that case is hidden by the Discord client, so we hide it here too. diff --git a/backend/src/plugins/Utility/commands/AvatarCmd.ts b/backend/src/plugins/Utility/commands/AvatarCmd.ts index ef44a2cb..7323d829 100644 --- a/backend/src/plugins/Utility/commands/AvatarCmd.ts +++ b/backend/src/plugins/Utility/commands/AvatarCmd.ts @@ -10,11 +10,11 @@ export const AvatarCmd = utilityCmd({ permission: "can_avatar", signature: { - user: ct.resolvedUserLoose({ required: false }), + user: ct.resolvedMember({ required: false }) || ct.resolvedUserLoose({ required: false }), }, async run({ message: msg, args, pluginData }) { - const user = args.user || msg.author; + const user = args.user || msg.member || msg.author; if (!(user instanceof UnknownUser)) { const embed: APIEmbed = { image: { diff --git a/backend/src/plugins/Utility/functions/getUserInfoEmbed.ts b/backend/src/plugins/Utility/functions/getUserInfoEmbed.ts index ef8d2320..a8901dd1 100644 --- a/backend/src/plugins/Utility/functions/getUserInfoEmbed.ts +++ b/backend/src/plugins/Utility/functions/getUserInfoEmbed.ts @@ -46,7 +46,7 @@ export async function getUserInfoEmbed( name: `${user.bot ? "Bot" : "User"}: ${renderUsername(user.username, user.discriminator)}`, }; - const avatarURL = user.displayAvatarURL(); + const avatarURL = (member || user).displayAvatarURL(); embed.author.icon_url = avatarURL; if (compact) { diff --git a/backend/src/plugins/Utility/search.ts b/backend/src/plugins/Utility/search.ts index 19710b58..1be7d483 100644 --- a/backend/src/plugins/Utility/search.ts +++ b/backend/src/plugins/Utility/search.ts @@ -495,7 +495,7 @@ function formatSearchResultList(members: Array): string { line = `${paddedId} ${renderUserUsername(member.user)}`; if (member.nickname) line += ` (${member.nickname})`; } else { - line = `${paddedId} ${member.tag}`; + line = `${paddedId} ${renderUserUsername(member)}`; } return line; }); diff --git a/backend/src/utils.ts b/backend/src/utils.ts index 1bb4d6ce..ed7837f8 100644 --- a/backend/src/utils.ts +++ b/backend/src/utils.ts @@ -1610,6 +1610,7 @@ export function renderUsername(username: string, discriminator: string): string return `${username}#${discriminator}`; } -export function renderUserUsername(user: User | UnknownUser): string { +export function renderUserUsername(user: GuildMember | User | UnknownUser): string { + user instanceof GuildMember ? (user = user.user) : null; return renderUsername(user.username, user.discriminator); } diff --git a/backend/src/utils/templateSafeObjects.ts b/backend/src/utils/templateSafeObjects.ts index 67517f19..6c9b5e08 100644 --- a/backend/src/utils/templateSafeObjects.ts +++ b/backend/src/utils/templateSafeObjects.ts @@ -91,7 +91,7 @@ export class TemplateSafeMember extends TemplateSafeUser { nick: string; roles: TemplateSafeRole[]; joinedAt?: number; - // guildAvatarURL: string, Once DJS supports per-server avatars + guildAvatarURL: string; guildName: string; constructor(data: InputProps) { @@ -259,7 +259,7 @@ export function userToTemplateSafeUser(user: User | UnknownUser): TemplateSafeUs discriminator: user.discriminator, mention: `<@${user.id}>`, tag: user.tag, - avatarURL: user.displayAvatarURL?.(), + avatarURL: user.displayAvatarURL(), bot: user.bot, createdAt: user.createdTimestamp, renderedUsername: renderUserUsername(user), @@ -285,6 +285,7 @@ export function memberToTemplateSafeMember(member: GuildMember | PartialGuildMem nick: member.nickname ?? "*None*", roles: [...member.roles.cache.mapValues((r) => roleToTemplateSafeRole(r)).values()], joinedAt: member.joinedTimestamp ?? undefined, + guildAvatarURL: member.displayAvatarURL(), guildName: member.guild.name, }); }