All files / api/routes bugReportEndpoint.ts

0% Statements 0/76
0% Branches 0/1
0% Functions 0/1
0% Lines 0/76

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77                                                                                                                                                         
import Koa from 'koa';

import { hasCaptcha } from '@api/guard/hasCaptcha';
import { errorResponse } from '@api/misc/httpResponse/errorResponse';
import { successResponse } from '@api/misc/httpResponse/successResponse';
import { ApiStatusErrorCode } from '@constants/api';
import { BugReportDto } from '@contracts/dto/forms/bugReportDto';
import { baseSubmissionMessageBuilder } from '@helpers/discordMessageHelper';
import { uuidv4 } from '@helpers/guidHelper';
import { anyObject } from '@helpers/typescriptHacks';
import { getDiscordService } from '@services/external/discord/discordService';
import { getConfig } from '@services/internal/configService';
import { getLog } from '@services/internal/logService';

export const bugReportEndpoint = async (
  ctx: Koa.DefaultContext,
  next: () => Promise<Koa.BaseResponse>,
) => {
  const handlerName = `bugReport-${uuidv4()}`;
  getLog().i(handlerName);

  const bodyParams: BugReportDto = ctx.request.body;
  const isCaptchaEnabled = getConfig().getCaptchaEnabled();
  if (isCaptchaEnabled === true) {
    const captchaString = bodyParams.captcha ?? '';
    const captchaTest = hasCaptcha(captchaString);
    const captchaIsValid = await captchaTest(ctx, next);
    if (captchaIsValid === false) {
      const errMsg = `${handlerName} - Captcha test: could not verify result`;
      getLog().i(errMsg);
      await errorResponse({
        ctx,
        next,
        statusCode: ApiStatusErrorCode.badCaptcha.code,
        message: errMsg,
      });
      return;
    }
  }

  const descripLines: Array<string> = [
    `Contact details: ${bodyParams.contactDetails}`,
    `Description: ${bodyParams.description}`,
  ];
  if ((bodyParams.logs?.length ?? 0) > 0) {
    descripLines.push('Logs attached');
  }

  const discordUrl = getConfig().getDiscordWebhookUrl();
  const webhookPayload = baseSubmissionMessageBuilder({
    content: '',
    authorName: 'Bug Report',
    colour: 13369858,
    descripLines,
    fields: (bodyParams.logs ?? []).map((l) => ({
      name: l.type,
      value: l.message ?? '---',
    })),
    additionalEmbeds: [],
  });

  const discordResponse = await getDiscordService().sendDiscordMessage(discordUrl, webhookPayload);
  if (!discordResponse.isSuccess) {
    const errMsg = `${handlerName} - Send discord message - ${discordResponse.errorMessage}`;
    getLog().e(errMsg);
    await errorResponse({
      ctx,
      next,
      statusCode: ApiStatusErrorCode.couldNotPersistData.code,
      message: errMsg,
    });
    return;
  }

  await successResponse({ ctx, body: anyObject, next });
};