diff --git a/packages/skin-database/api/DiscordEventHandler.ts b/packages/skin-database/api/DiscordEventHandler.ts index 7f395044..e79f0f16 100644 --- a/packages/skin-database/api/DiscordEventHandler.ts +++ b/packages/skin-database/api/DiscordEventHandler.ts @@ -15,20 +15,21 @@ export default class DiscordEventHandler { .then(() => _client); } - async getClient() { + private async getClient() { return this._clientPromise; } - async getChannel(channelId: string): Promise { + private async getChannel(channelId: string): Promise { const client = await this.getClient(); const dest = client.channels.get(channelId) as TextChannel | null; if (dest == null) { - throw new Error("Could not get NSFW channel"); + throw new Error(`Could not get channel with id: ${channelId}`); } return dest; } - async handle(action: ApiAction, ctx: UserContext) { + async handle(action: ApiAction): Promise { + const ctx = new UserContext(); switch (action.type) { case "REVIEW_REQUESTED": await this.requestReview(action.md5, ctx); @@ -55,10 +56,31 @@ export default class DiscordEventHandler { Config.NSFW_SKIN_CHANNEL_ID ); break; + case "CLASSIC_SKIN_UPLOADED": + await this.reportSkin( + action.md5, + ctx, + (filename) => `New skin uploaded: ${filename}`, + Config.SKIN_UPLOADS_CHANNEL_ID + ); + break; + case "MODERN_SKIN_UPLOADED": { + const dest = await this.getChannel(Config.SKIN_UPLOADS_CHANNEL_ID); + await dest.send(`Someone uploaded a new modern skin: ${action.md5}`); + break; + } + + case "SKIN_UPLOAD_ERROR": { + const dest = await this.getChannel(Config.SKIN_UPLOADS_CHANNEL_ID); + await dest.send( + `Encountered an error processing upload ${action.uploadId}: ${action.message}` + ); + break; + } } } - async reportSkin( + private async reportSkin( md5: string, ctx: UserContext, getFilename: (filename: string) => string, @@ -76,7 +98,7 @@ export default class DiscordEventHandler { }); } - async requestReview(md5: string, ctx: UserContext) { + private async requestReview(md5: string, ctx: UserContext) { const skin = await SkinModel.fromMd5(ctx, md5); if (skin == null) { return; diff --git a/packages/skin-database/api/__tests__/router.test.ts b/packages/skin-database/api/__tests__/router.test.ts index eb34d1a8..0a4c2a9e 100644 --- a/packages/skin-database/api/__tests__/router.test.ts +++ b/packages/skin-database/api/__tests__/router.test.ts @@ -24,7 +24,7 @@ beforeEach(async () => { jest.clearAllMocks(); username = ""; app = createApp({ - eventHandler: (action, _ctx) => handler(action), + eventHandler: handler, extraMiddleware: (req, res, next) => { req.session.username = username; next(); diff --git a/packages/skin-database/api/app.ts b/packages/skin-database/api/app.ts index 04360953..82a53a03 100644 --- a/packages/skin-database/api/app.ts +++ b/packages/skin-database/api/app.ts @@ -16,9 +16,12 @@ export type ApiAction = | { type: "APPROVED_SKIN"; md5: string } | { type: "MARKED_SKIN_NSFW"; md5: string } | { type: "SKIN_UPLOADED"; md5: string } - | { type: "ERROR_PROCESSING_UPLOAD"; id: string; message: string }; + | { type: "ERROR_PROCESSING_UPLOAD"; id: string; message: string } + | { type: "CLASSIC_SKIN_UPLOADED"; md5: string } + | { type: "MODERN_SKIN_UPLOADED"; md5: string } + | { type: "SKIN_UPLOAD_ERROR"; uploadId: string; message: string }; -export type EventHandler = (event: ApiAction, ctx: UserContext) => void; +export type EventHandler = (event: ApiAction) => void; export type Logger = { log(message: string, context: any): void; logError(message: string, context: any): void; @@ -81,7 +84,7 @@ export function createApp({ eventHandler, extraMiddleware, logger }: Options) { app.use((req, res, next) => { req.notify = (action) => { if (eventHandler) { - eventHandler(action, req.ctx); + eventHandler(action); } }; next(); diff --git a/packages/skin-database/api/processUserUploads.ts b/packages/skin-database/api/processUserUploads.ts index 59d4b0d4..adf0f8e1 100644 --- a/packages/skin-database/api/processUserUploads.ts +++ b/packages/skin-database/api/processUserUploads.ts @@ -1,32 +1,19 @@ import * as Skins from "../data/skins"; import S3 from "../s3"; -import Discord, { TextChannel } from "discord.js"; -import * as DiscordUtils from "../discord-bot/utils"; -import * as Config from "../config"; -import { addSkinFromBuffer, Result as AddResult } from "../addSkin"; +import { addSkinFromBuffer } from "../addSkin"; +import { EventHandler } from "./app"; let processing = false; -export async function processUserUploads() { +export async function processUserUploads(eventHandler: EventHandler) { // Ensure we only have one worker processing requests. if (processing) { return; } processing = true; - const client = new Discord.Client(); - await client.login(Config.discordToken); - const dest = client.channels.get( - Config.SKIN_UPLOADS_CHANNEL_ID - ) as TextChannel; - let upload = await Skins.getReportedUpload(); while (upload != null) { try { - if (upload.id == null || upload.filename == null) { - throw new Error( - `Missing value in upload: ${upload.id} ${upload.filename}` - ); - } const buffer = await S3.getUploadedSkin(upload.id); const result = await addSkinFromBuffer( buffer, @@ -34,32 +21,28 @@ export async function processUserUploads() { "Web API" ); await Skins.recordUserUploadArchived(upload.id); - await reportSkinUpload(result, dest); + if (result.status === "ADDED") { + const action = { + type: + result.skinType === "CLASSIC" + ? "CLASSIC_SKIN_UPLOADED" + : "MODERN_SKIN_UPLOADED", + md5: result.md5, + } as const; + eventHandler(action); + } } catch (e) { - dest.send( - `Encountered an error processing upload ${upload.id}: ${e.message}` - ); - console.error(e); await Skins.recordUserUploadErrored(upload.id); + const action = { + type: "SKIN_UPLOAD_ERROR", + uploadId: upload.id, + message: e.message, + } as const; + eventHandler(action); + console.error(e); } upload = await Skins.getReportedUpload(); } processing = false; } - -async function reportSkinUpload(result: AddResult, dest: TextChannel) { - if (result.status === "ADDED") { - // await new Promise((resolve) => setTimeout(resolve, 3000)); - if (result.skinType === "CLASSIC") { - // Don't await - DiscordUtils.postSkin({ - md5: result.md5, - title: (filename) => `New skin uploaded: ${filename}`, - dest, - }); - } else if (result.skinType === "MODERN") { - dest.send(`Someone uploaded a new modern skin: ${result.md5}`); - } - } -} diff --git a/packages/skin-database/api/router.ts b/packages/skin-database/api/router.ts index bc650074..ac62f3a2 100644 --- a/packages/skin-database/api/router.ts +++ b/packages/skin-database/api/router.ts @@ -231,7 +231,7 @@ router.post( // TODO: Validate md5 and id; await Skins.recordUserUploadComplete(md5, id); // Don't await, just kick off the task. - processUserUploads(); + processUserUploads(req.notify); res.json({ done: true }); }) ); diff --git a/packages/skin-database/api/server.ts b/packages/skin-database/api/server.ts index 140f669a..02b32648 100644 --- a/packages/skin-database/api/server.ts +++ b/packages/skin-database/api/server.ts @@ -8,7 +8,7 @@ const handler = new DiscordEventHandler(); // GO! const app = createApp({ - eventHandler: (action, ctx) => handler.handle(action, ctx), + eventHandler: (action) => handler.handle(action), logger: { log: (message, context) => console.log(message, context), logError: (message, context) => console.error(message, context),