import * as Hapi from "@hapi/hapi"; import Joi from "joi"; import * as Helpers from "../helpers/index.js"; import Boom from "@hapi/boom"; const getSignalService = (request) => request.services("app").signaldService; export const GetAllSignalBotsRoute = Helpers.withDefaults({ method: "get", path: "/api/signal/bots", options: { description: "Get all bots", async handler(request: Hapi.Request, _h: Hapi.ResponseToolkit) { const signalService = getSignalService(request); const bots = await signalService.findAll(); if (bots) { // with the pino logger the first arg is an object of data to log // the second arg is a message // all other args are formated args for the msg request.logger.info({ bots }, "Retrieved bot(s) at %s", new Date()); return { bots }; } return _h.response().code(204); }, }, }); export const GetBotsRoute = Helpers.noAuth({ method: "get", path: "/api/signal/bots/{token}", options: { description: "Get one bot", async handler(request: Hapi.Request, _h: Hapi.ResponseToolkit) { const { token } = request.params; const signalService = getSignalService(request); const bot = await signalService.findByToken(token); if (bot) { // with the pino logger the first arg is an object of data to log // the second arg is a message // all other args are formated args for the msg request.logger.info({ bot }, "Retrieved bot(s) at %s", new Date()); return bot; } throw Boom.notFound("Bot not found"); }, }, }); interface MessageRequest { phoneNumber: string; message: string; } export const SendBotRoute = Helpers.noAuth({ method: "post", path: "/api/signal/bots/{token}/send", options: { description: "Send a message", async handler(request: Hapi.Request, _h: Hapi.ResponseToolkit) { const { token } = request.params; const { phoneNumber, message } = request.payload as MessageRequest; const signalService = getSignalService(request); const bot = await signalService.findByToken(token); if (bot) { request.logger.info({ bot }, "Sent a message at %s", new Date()); await signalService.send(bot, phoneNumber, message as string); return _h .response({ result: { recipient: phoneNumber, timestamp: new Date().toISOString(), source: bot.phoneNumber, }, }) .code(200); // temp } throw Boom.notFound("Bot not found"); }, }, }); interface ResetSessionRequest { phoneNumber: string; } export const ResetSessionBotRoute = Helpers.noAuth({ method: "post", path: "/api/signal/bots/{token}/resetSession", options: { description: "Reset a session with another user", async handler(request: Hapi.Request, _h: Hapi.ResponseToolkit) { const { token } = request.params; const { phoneNumber } = request.payload as ResetSessionRequest; const signalService = getSignalService(request); const bot = await signalService.findByToken(token); if (bot) { await signalService.resetSession(bot, phoneNumber); return _h .response({ result: { recipient: phoneNumber, timestamp: new Date().toISOString(), source: bot.phoneNumber, }, }) .code(200); // temp } throw Boom.notFound("Bot not found"); }, }, }); export const ReceiveBotRoute = Helpers.withDefaults({ method: "get", path: "/api/signal/bots/{token}/receive", options: { description: "Receive messages", async handler(request: Hapi.Request, _h: Hapi.ResponseToolkit) { const { token } = request.params; const signalService = getSignalService(request); const bot = await signalService.findByToken(token); if (bot) { request.logger.info({ bot }, "Received messages at %s", new Date()); return signalService.receive(bot); } throw Boom.notFound("Bot not found"); }, }, }); export const RegisterBotRoute = Helpers.withDefaults({ method: "get", path: "/api/signal/bots/{id}/register", options: { description: "Register a bot", async handler(request: Hapi.Request, h: Hapi.ResponseToolkit) { const { id } = request.params; const signalService = getSignalService(request); const { code } = request.query; const bot = await signalService.findById(id); if (!bot) throw Boom.notFound("Bot not found"); try { request.logger.info({ bot }, "Create bot at %s", new Date()); await signalService.register(bot, code); return h.response(bot).code(200); } catch (error) { return h.response().code(error.code); } }, }, }); interface BotRequest { phoneNumber: string; description: string; } export const CreateBotRoute = Helpers.withDefaults({ method: "post", path: "/api/signal/bots", options: { description: "Register a bot", async handler(request: Hapi.Request, _h: Hapi.ResponseToolkit) { const { phoneNumber, description } = request.payload as BotRequest; const signalService = getSignalService(request); console.log("request.auth.credentials:", request.auth.credentials); const bot = await signalService.create( phoneNumber, description, request.auth.credentials.email as string ); if (bot) { request.logger.info({ bot }, "Create bot at %s", new Date()); return bot; } throw Boom.notFound("Bot not found"); }, }, }); export const RequestCodeRoute = Helpers.withDefaults({ method: "get", path: "/api/signal/bots/{id}/requestCode", options: { description: "Register a bot", validate: { params: Joi.object({ id: Joi.string().uuid().required(), }), query: Joi.object({ mode: Joi.string().valid("sms", "voice").required(), captcha: Joi.string(), }), }, async handler(request: Hapi.Request, h: Hapi.ResponseToolkit) { const { id } = request.params; const { mode, captcha } = request.query; const signalService = getSignalService(request); const bot = await signalService.findById(id); if (!bot) { throw Boom.notFound("Bot not found"); } try { if (mode === "sms") { await signalService.requestSMSVerification(bot, captcha); } else if (mode === "voice") { await signalService.requestVoiceVerification(bot, captcha); } return h.response().code(200); } catch (error) { console.log(error); if (error.name === "CaptchaRequiredException") { return h.response().code(402); } if (error.code) { return h.response().code(error.code); } return h.response().code(500); } }, }, });