link-stack/apps/metamigo-api/src/app/routes/signal/index.ts
Abel Luck 696ba16cb7 metamigo-api: runs in docker now
* great typescript module import refactor
* refactor metamigo-cli so it is the entrypoint for the db, api, and
  worker
2023-06-02 15:26:30 +00:00

250 lines
6.8 KiB
TypeScript

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);
}
},
},
});