From 6305a8b0bcdeb4e6013da97859741bf264b6243c Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Wed, 15 May 2024 10:27:14 +0200 Subject: [PATCH] Add Signal and Whatsapp Docker CI --- .gitignore | 2 +- .gitlab-ci.yml | 22 +++++++++++ .../[service]/bots/[token]/receive/route.ts | 1 + apps/bridge-whatsapp/Dockerfile | 38 +++++++++++++++++++ apps/bridge-whatsapp/docker-entrypoint.sh | 5 +++ apps/bridge-whatsapp/package.json | 5 ++- apps/bridge-whatsapp/src/index.ts | 4 +- apps/bridge-whatsapp/src/routes.ts | 2 +- apps/bridge-whatsapp/src/types.ts | 2 +- packages/bridge-ui/index.ts | 7 +++- packages/bridge-ui/lib/routing.ts | 5 +++ packages/bridge-ui/lib/service.ts | 14 +++++++ 12 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 apps/bridge-frontend/app/api/[service]/bots/[token]/receive/route.ts create mode 100644 apps/bridge-whatsapp/Dockerfile create mode 100644 apps/bridge-whatsapp/docker-entrypoint.sh diff --git a/.gitignore b/.gitignore index e339901..d8c91d3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ node_modules .env .turbo -.tsbuildinfo +*.tsbuildinfo build/** **/dist/** .next/** diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6505b93..7f81d4c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -106,6 +106,28 @@ bridge-worker-docker-release: variables: DOCKER_NS: ${CI_REGISTRY}/digiresilience/link/link-stack/bridge-worker +bridge-whatsapp-docker-build: + extends: .docker-build + variables: + DOCKER_NS: ${CI_REGISTRY}/digiresilience/link/link-stack/bridge-whatsapp + DOCKERFILE_PATH: ./apps/bridge-whatsapp/Dockerfile + +bridge-whatsapp-docker-release: + extends: .docker-release + variables: + DOCKER_NS: ${CI_REGISTRY}/digiresilience/link/link-stack/bridge-whatsapp + +signal-cli-rest-api-docker-build: + extends: .docker-build + variables: + DOCKER_NS: ${CI_REGISTRY}/digiresilience/link/link-stack/signal-cli-rest-api + DOCKERFILE_PATH: ./docker/signal-cli-rest-api/Dockerfile + +signal-cli-rest-api-docker-release: + extends: .docker-release + variables: + DOCKER_NS: ${CI_REGISTRY}/digiresilience/link/link-stack/signal-cli-rest-api + memcached-docker-build: extends: .docker-build variables: diff --git a/apps/bridge-frontend/app/api/[service]/bots/[token]/receive/route.ts b/apps/bridge-frontend/app/api/[service]/bots/[token]/receive/route.ts new file mode 100644 index 0000000..c1d8867 --- /dev/null +++ b/apps/bridge-frontend/app/api/[service]/bots/[token]/receive/route.ts @@ -0,0 +1 @@ +export { receiveMessage as POST } from "bridge-ui"; diff --git a/apps/bridge-whatsapp/Dockerfile b/apps/bridge-whatsapp/Dockerfile new file mode 100644 index 0000000..c074784 --- /dev/null +++ b/apps/bridge-whatsapp/Dockerfile @@ -0,0 +1,38 @@ +FROM node:20-bookworm AS base + +FROM base AS builder +ARG APP_DIR=/opt/bridge-whatsapp +RUN mkdir -p ${APP_DIR}/ +RUN npm i -g turbo +WORKDIR ${APP_DIR} +COPY . . +RUN turbo prune --scope=bridge-whatsapp --docker + +FROM base AS installer +ARG APP_DIR=/opt/bridge-whatsapp +WORKDIR ${APP_DIR} +COPY --from=builder ${APP_DIR}/out/json/ . +COPY --from=builder ${APP_DIR}/out/full/ . +COPY --from=builder ${APP_DIR}/out/package-lock.json ./package-lock.json +RUN npm ci +RUN npm i -g turbo +RUN turbo run build --filter=bridge-whatsapp + +FROM base as runner +ARG BUILD_DATE +ARG VERSION +ARG APP_DIR=/opt/bridge-whatsapp +RUN mkdir -p ${APP_DIR}/ +RUN DEBIAN_FRONTEND=noninteractive apt-get update && \ + apt-get install -y --no-install-recommends \ + dumb-init +WORKDIR ${APP_DIR} +COPY --from=installer ${APP_DIR} ./ +RUN chown -R node:node ${APP_DIR} +WORKDIR ${APP_DIR}/apps/bridge-whatsapp/ +RUN chmod +x docker-entrypoint.sh +USER node +EXPOSE 5000 +ENV PORT 5000 +ENV NODE_ENV production +ENTRYPOINT ["/opt/bridge-whatsapp/apps/bridge-whatsapp/docker-entrypoint.sh"] diff --git a/apps/bridge-whatsapp/docker-entrypoint.sh b/apps/bridge-whatsapp/docker-entrypoint.sh new file mode 100644 index 0000000..866302b --- /dev/null +++ b/apps/bridge-whatsapp/docker-entrypoint.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +set -e +echo "starting bridge-whatsapp" +exec dumb-init npm run start diff --git a/apps/bridge-whatsapp/package.json b/apps/bridge-whatsapp/package.json index a03bb1d..ffdadff 100644 --- a/apps/bridge-whatsapp/package.json +++ b/apps/bridge-whatsapp/package.json @@ -2,7 +2,7 @@ "name": "bridge-whatsapp", "version": "0.3.0", "type": "module", - "main": "build/main/main.js", + "main": "build/main/index.js", "author": "Darren Clarke ", "license": "AGPL-3.0-or-later", "dependencies": { @@ -28,6 +28,7 @@ }, "scripts": { "build": "tsc -p tsconfig.json", - "dev": "tsx src/index.ts" + "dev": "tsx src/index.ts", + "start": "node build/main/index.js" } } diff --git a/apps/bridge-whatsapp/src/index.ts b/apps/bridge-whatsapp/src/index.ts index 814e51a..c60ebad 100644 --- a/apps/bridge-whatsapp/src/index.ts +++ b/apps/bridge-whatsapp/src/index.ts @@ -2,7 +2,7 @@ import * as Hapi from "@hapi/hapi"; import * as AuthBearer from "hapi-auth-bearer-token"; import hapiPino from "hapi-pino"; import Schmervice from "@hapipal/schmervice"; -import WhatsappService from "./service"; +import WhatsappService from "./service.js"; import { GetAllWhatsappBotsRoute, GetBotsRoute, @@ -12,7 +12,7 @@ import { UnverifyBotRoute, RefreshBotRoute, CreateBotRoute, -} from "./routes"; +} from "./routes.js"; const server = Hapi.server({ host: "localhost", port: 5000 }); diff --git a/apps/bridge-whatsapp/src/routes.ts b/apps/bridge-whatsapp/src/routes.ts index 1e3cc5e..bac7a4e 100644 --- a/apps/bridge-whatsapp/src/routes.ts +++ b/apps/bridge-whatsapp/src/routes.ts @@ -1,6 +1,6 @@ import * as Hapi from "@hapi/hapi"; -import * as Helpers from "./helpers"; import Boom from "@hapi/boom"; +import * as Helpers from "./helpers.js"; export const GetAllWhatsappBotsRoute = Helpers.withDefaults({ method: "get", diff --git a/apps/bridge-whatsapp/src/types.ts b/apps/bridge-whatsapp/src/types.ts index a52bd20..231a804 100644 --- a/apps/bridge-whatsapp/src/types.ts +++ b/apps/bridge-whatsapp/src/types.ts @@ -1,4 +1,4 @@ -import type WhatsappService from "./service"; +import type WhatsappService from "./service.js"; declare module "@hapipal/schmervice" { interface SchmerviceDecorator { diff --git a/packages/bridge-ui/index.ts b/packages/bridge-ui/index.ts index 8dfece4..1735861 100644 --- a/packages/bridge-ui/index.ts +++ b/packages/bridge-ui/index.ts @@ -5,4 +5,9 @@ export { Edit } from "./components/Edit"; export { Detail } from "./components/Detail"; export { ServiceLayout } from "./components/ServiceLayout"; export { serviceConfig, getServiceTable } from "./config/config"; -export { getBot, sendMessage, handleWebhook } from "./lib/routing"; +export { + getBot, + sendMessage, + receiveMessage, + handleWebhook, +} from "./lib/routing"; diff --git a/packages/bridge-ui/lib/routing.ts b/packages/bridge-ui/lib/routing.ts index 408a557..478dcab 100644 --- a/packages/bridge-ui/lib/routing.ts +++ b/packages/bridge-ui/lib/routing.ts @@ -12,6 +12,11 @@ export const sendMessage = async ( params: ServiceParams, ): Promise => getService(params)?.sendMessage(req, params); +export const receiveMessage = async ( + req: NextRequest, + params: ServiceParams, +): Promise => getService(params)?.receiveMessage(req, params); + export const handleWebhook = async ( req: NextRequest, params: ServiceParams, diff --git a/packages/bridge-ui/lib/service.ts b/packages/bridge-ui/lib/service.ts index 0070f04..915c036 100644 --- a/packages/bridge-ui/lib/service.ts +++ b/packages/bridge-ui/lib/service.ts @@ -82,6 +82,20 @@ export class Service { return NextResponse.json({ response: "ok" }); } + async receiveMessage( + req: NextRequest, + { params: { service, token } }: ServiceParams, + ): Promise { + const message = await req.json(); + const worker = await getWorkerUtils(); + await worker.addJob(`${service}/receive-${service}-message`, { + token, + message, + }); + + return NextResponse.json({ response: "ok" }); + } + async handleWebhook(_req: NextRequest): Promise { return NextResponse.error() as any; }