diff --git a/Dockerfile.bot-app b/Dockerfile.bot-app index 7ac5d58..777d2f8 100644 --- a/Dockerfile.bot-app +++ b/Dockerfile.bot-app @@ -1,28 +1,45 @@ -FROM ubuntu:24.04 +FROM debian:trixie-slim AS build ENV SHELL /bin/bash - RUN apt-get update && \ apt-get install -y \ - make git openssl curl unzip coreutils cron findutils && \ + make git openssl curl unzip coreutils && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* +RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - +RUN apt-get install -y nodejs -RUN useradd -ms /bin/sh -u 1001 bot-app +RUN curl -fsSL https://bun.sh/install | bash -s "bun-v1.1.21" +WORKDIR /bot-app -RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - -RUN apt-get install -y nodejs +COPY . . +ENV PATH="/root/.bun/bin:${PATH}" -RUN curl -fsSL https://bun.sh/install | bash -s "bun-v1.1.21" +RUN bun install -g rimraf pm2 +# Étape 2 : Image finale +FROM debian:trixie-slim + +ENV SHELL /bin/bash + +RUN apt-get update && \ + apt-get install -y \ + make openssl curl coreutils cron findutils && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN useradd -ms /bin/sh -u 1001 bot-app WORKDIR /bot-app -COPY --chown=bot-app:bot-app . . +COPY --from=build /root/.bun /root/.bun +COPY --from=build /usr/bin/node /usr/bin/ +COPY --from=build /usr/lib/node_modules /usr/lib/node_modules +COPY --from=build /bot-app /bot-app RUN touch /var/log/cron.log \ && chown bot-app:bot-app /var/log/cron.log \ @@ -33,8 +50,6 @@ RUN chmod 755 /bot-app/docker/utils/cron.sh ENV PATH="/root/.bun/bin:${PATH}" -RUN bun install -g rimraf pm2 - EXPOSE 3000 ENTRYPOINT ["/bot-app/docker/utils/cron.sh"] CMD ["make", "docker-bot-app-entrypoint"] diff --git a/docker-compose.yml b/docker-compose.yml index 15c6ff4..8719f7a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -29,7 +29,7 @@ services: COLLECTOR_OTLP_ENABLED: 'true' ports: - 127.0.0.1:16686:16686 - - 4318:4318 + - 127.0.0.1:4318:4318 networks: - bot_app_shared_network diff --git a/packages/shared-lib/package.json b/packages/shared-lib/package.json index 38d7985..e0b9932 100644 --- a/packages/shared-lib/package.json +++ b/packages/shared-lib/package.json @@ -15,6 +15,7 @@ "./discordjs/buildGuildInteractionFromGuildMemberToAnotherGuildMember": "./src/discordjs/buildGuildInteractionFromGuildMemberToAnotherGuildMember.ts", "./discordjs/canModerateThisMember": "./src/discordjs/canModerateThisMember.ts", "./discordjs/getBannedByMemberIdFromLogs": "./src/discordjs/getBannedByMemberIdFromLogs.ts", + "./discordjs/getUnbannedByMemberIdFromLogs": "./src/discordjs/getUnbannedByMemberIdFromLogs.ts", "./discordjs/getUserAvatar": "./src/discordjs/getUserAvatar.ts", "./discordjs/getUserOrGuildMemberFromSlashCommandUserOption": "./src/discordjs/getUserOrGuildMemberFromSlashCommandUserOption.ts", "./discordjs/isEveryoneRole": "./src/discordjs/isEveryoneRole.ts", @@ -89,6 +90,9 @@ "discordjs/getBannedByMemberIdFromLogs": [ "./src/discordjs/getBannedByMemberIdFromLogs.ts" ], + "discordjs/getUnbannedByMemberIdFromLogs": [ + "./src/discordjs/getUnbannedByMemberIdFromLogs.ts" + ], "discordjs/getUserAvatar": [ "./src/discordjs/getUserAvatar.ts" ], diff --git a/packages/shared-lib/src/discordjs/getUnbannedByMemberIdFromLogs.ts b/packages/shared-lib/src/discordjs/getUnbannedByMemberIdFromLogs.ts new file mode 100644 index 0000000..da1e040 --- /dev/null +++ b/packages/shared-lib/src/discordjs/getUnbannedByMemberIdFromLogs.ts @@ -0,0 +1,31 @@ +import type { Limit } from '@wpm-discord-bot/shared-types/Number'; +import type { GuildMember, GuildBan, User } from 'discord.js'; + +import { NO_USER_ID } from '@wpm-discord-bot/shared-specs/Discord'; +import { AuditLogEvent } from 'discord.js'; + +import lazilyFetchGuildMember from './lazilyFetchGuildMember'; + +async function getUnbannedByMemberIdFromLogs( + guildBan: GuildBan, + discordBotId: User['id'], + limit: Limit = 100 +): Promise { + const botMember = await lazilyFetchGuildMember(guildBan.guild, discordBotId); + + if (botMember === null || !botMember.permissions.has('ViewAuditLog')) return NO_USER_ID; + + const auditLogs = await guildBan.guild.fetchAuditLogs({ + type: AuditLogEvent.MemberBanRemove, + limit + }); + + const matchingLogs = auditLogs.entries.filter((log) => log.target?.id === guildBan.user.id); + + const bestMatch = matchingLogs.first(); + + const bannedByMemberId = bestMatch?.executor?.id ?? NO_USER_ID; + return bannedByMemberId; +} + +export default getUnbannedByMemberIdFromLogs; diff --git a/src/events/guildBanRemoveCallback.ts b/src/events/guildBanRemoveCallback.ts index 36718c7..8575606 100644 --- a/src/events/guildBanRemoveCallback.ts +++ b/src/events/guildBanRemoveCallback.ts @@ -6,7 +6,7 @@ import type { GuildBan, Guild } from 'discord.js'; import attemptToMoveTempBannedMemberToBannedMembersArchive from '#@/jobs/helpers/tempBans/db/attemptToMoveTempBannedMemberToBannedMembersArchive'; import attemptToMoveDefBannedMemberToBannedMembersArchive from '#@/jobs/helpers/tempBans/db/attemptToMoveDefBannedMemberToBannedMembersArchive'; import { attemptToTurnOffIsAbandonerFlagWithAuthorizedToManageBansBotClient } from '#@/db/dsl/guilds/isAbandonerFlagTweakers'; -import getBannedByMemberIdFromLogs from '@wpm-discord-bot/shared-lib/discordjs/getBannedByMemberIdFromLogs'; +import getUnbannedByMemberIdFromLogs from '@wpm-discord-bot/shared-lib/discordjs/getUnbannedByMemberIdFromLogs'; import verrou, { verrouKeysFactory } from '#@/config/verrou'; import traceError from '#@/helpers/interactions/traceError'; import { getDiscordBotId } from '#@/client'; @@ -24,6 +24,9 @@ async function getMaybeTempBanEntry({ unbannedUserIdAsBigInt, guildIdAsBigInt }: select: { bannedAt: true, id: true } }); + console.log('unbannedUserIdAsBigInt:', unbannedUserIdAsBigInt); + console.log('guildIdAsBigInt:', guildIdAsBigInt); + console.log('maybeTempBanEntry:', maybeTempBanEntry); return maybeTempBanEntry; } @@ -93,13 +96,17 @@ async function guildBanRemoveCallback(guildBan: GuildBan) { const { guild } = guildBan; const { id: guildId } = guild; + console.log('... 0'); + try { await verrou .use('redis') .createLock(verrouKeysFactory.processingUnbanOnUserViaTheBot(guildId, unbannedUserId), '10s') .run(async () => { + console.log('... 1'); + const discordBotId = await getDiscordBotId(); - const unbannedByMemberId = await getBannedByMemberIdFromLogs(guildBan, discordBotId); + const unbannedByMemberId = await getUnbannedByMemberIdFromLogs(guildBan, discordBotId); await attemptToTurnOffIsAbandonerFlagWithAuthorizedToManageBansBotClient(guild, { awaitGC: true }); @@ -109,8 +116,7 @@ async function guildBanRemoveCallback(guildBan: GuildBan) { const guildIdAsBigInt = BigInt(guildId); const unbannedUserIdAsBigInt = BigInt(unbannedUserId); - if (guildBan.partial) guildBan = await guildBan.fetch(true); - + console.log('... 2'); const maybeTempBanEntry = await getMaybeTempBanEntry({ unbannedUserIdAsBigInt, guildIdAsBigInt }); const maybeDefBanEntry = await getMaybeDefBanEntry({ unbannedUserIdAsBigInt, guildIdAsBigInt });