Refactoring 3
This commit is contained in:
parent
e4b78ceec2
commit
d1fb9b4d06
20 changed files with 201 additions and 123 deletions
|
|
@ -6,16 +6,16 @@
|
|||
"license": "AGPL-3.0-or-later",
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"dev": "NODE_OPTIONS=\"--loader ts-node/esm\" graphile-worker"
|
||||
"dev": " NODE_OPTIONS=\"--loader ts-node/esm\" graphile-worker"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hapi/wreck": "^18.1.0",
|
||||
"bridge-common": "*",
|
||||
"fluent-ffmpeg": "^2.1.2",
|
||||
"graphile-worker": "^0.16.5",
|
||||
"html-to-text": "^9.0.5",
|
||||
"jest": "^29.7.0",
|
||||
"kysely": "^0.27.3",
|
||||
"bridge-common": "*",
|
||||
"pg": "^8.11.5",
|
||||
"remeda": "^1.61.0",
|
||||
"twilio": "^5.0.4"
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
"@babel/preset-env": "7.24.4",
|
||||
"@babel/preset-typescript": "7.24.1",
|
||||
"@types/fluent-ffmpeg": "^2.1.24",
|
||||
"dotenv": "^16.4.5",
|
||||
"eslint": "^9.0.0",
|
||||
"prettier": "^3.2.5",
|
||||
"ts-config": "*",
|
||||
|
|
|
|||
|
|
@ -1,57 +0,0 @@
|
|||
import Wreck from "@hapi/wreck";
|
||||
import * as R from "remeda";
|
||||
import { withDb, AppDatabase } from "../../lib/db";
|
||||
// import logger from "../logger";
|
||||
|
||||
export interface WebhookOptions {
|
||||
webhookId: string;
|
||||
payload: any;
|
||||
}
|
||||
|
||||
const notifyWebhooksTask = async (options: WebhookOptions): Promise<void> =>
|
||||
withDb(async (db: AppDatabase) => {
|
||||
const { webhookId, payload } = options;
|
||||
|
||||
const webhook = await db.webhooks.findById({ id: webhookId });
|
||||
if (!webhook) {
|
||||
// logger.debug(
|
||||
// { webhookId },
|
||||
// "notify-webhook: no webhook registered with id",
|
||||
// );
|
||||
return;
|
||||
}
|
||||
|
||||
const { endpointUrl, httpMethod, headers } = webhook;
|
||||
const headersFormatted = R.reduce(
|
||||
headers || [],
|
||||
(acc: any, h: any) => {
|
||||
acc[h.header] = h.value;
|
||||
return acc;
|
||||
},
|
||||
{},
|
||||
);
|
||||
|
||||
const wreck = Wreck.defaults({
|
||||
json: true,
|
||||
headers: headersFormatted,
|
||||
});
|
||||
|
||||
// http errors will bubble up and cause the job to fail and be retried
|
||||
try {
|
||||
// logger.debug(
|
||||
// { webhookId, endpointUrl, httpMethod },
|
||||
// "notify-webhook: notifying",
|
||||
// );
|
||||
await (httpMethod === "post"
|
||||
? wreck.post(endpointUrl, { payload })
|
||||
: wreck.put(endpointUrl, { payload }));
|
||||
} catch (error: any) {
|
||||
// logger.error(
|
||||
// { webhookId, error: error.output },
|
||||
// "notify-webhook failed with this error",
|
||||
// );
|
||||
throw new Error(`webhook failed webhookId=${webhookId}`);
|
||||
}
|
||||
});
|
||||
|
||||
export default notifyWebhooksTask;
|
||||
31
apps/bridge-worker/tasks/common/notify-webhooks.ts
Normal file
31
apps/bridge-worker/tasks/common/notify-webhooks.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import { db } from "bridge-common";
|
||||
|
||||
export interface NotifyWebhooksOptions {
|
||||
backendId: string;
|
||||
payload: any;
|
||||
}
|
||||
|
||||
const notifyWebhooksTask = async (
|
||||
options: NotifyWebhooksOptions,
|
||||
): Promise<void> => {
|
||||
const { backendId, payload } = options;
|
||||
|
||||
const webhooks = await db
|
||||
.selectFrom("Webhook")
|
||||
.selectAll()
|
||||
.where("backendId", "=", backendId)
|
||||
.execute();
|
||||
|
||||
for (const webhook of webhooks) {
|
||||
const { endpointUrl, httpMethod, headers } = webhook;
|
||||
const finalHeaders = { "Content-Type": "application/json", ...headers };
|
||||
|
||||
await fetch(endpointUrl, {
|
||||
method: httpMethod,
|
||||
headers: finalHeaders,
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default notifyWebhooksTask;
|
||||
|
|
@ -17,9 +17,13 @@ const receiveFacebookMessageTask = async ({
|
|||
.selectAll()
|
||||
.where("pageId", "=", pageId)
|
||||
.executeTakeFirstOrThrow();
|
||||
const backendId = row.id;
|
||||
const payload = {
|
||||
text: messaging.message.text,
|
||||
recipient: messaging.sender.id,
|
||||
};
|
||||
|
||||
console.log({ row });
|
||||
await worker.addJob("notify_webhooks", messaging);
|
||||
await worker.addJob("common/notify-webhooks", { backendId, payload });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,64 +1,34 @@
|
|||
interface SendFacebookMessageTaskOptions {}
|
||||
import { db } from "bridge-common";
|
||||
|
||||
interface SendFacebookMessageTaskOptions {
|
||||
token: string;
|
||||
message: any;
|
||||
}
|
||||
|
||||
const sendFacebookMessageTask = async (
|
||||
options: SendFacebookMessageTaskOptions,
|
||||
): Promise<void> => {
|
||||
console.log(options);
|
||||
|
||||
|
||||
const message = await req.json();
|
||||
|
||||
const message = await req.json();
|
||||
for (const entry of message.entry) {
|
||||
for (const messaging of entry.messaging) {
|
||||
const pageId = messaging.recipient.id;
|
||||
const row = await db
|
||||
.selectFrom("FacebookBot")
|
||||
.selectAll()
|
||||
.where("pageId", "=", pageId)
|
||||
.executeTakeFirst();
|
||||
|
||||
console.log({ message });
|
||||
const entry = message.entry[0];
|
||||
console.log({ entry });
|
||||
const messaging = entry?.messaging[0];
|
||||
const pageId = messaging?.recipient?.id;
|
||||
console.log({ pageId });
|
||||
const row = await db
|
||||
const { token, message } = options;
|
||||
const { pageId, pageAccessToken } = await db
|
||||
.selectFrom("FacebookBot")
|
||||
.selectAll()
|
||||
.where("pageId", "=", pageId)
|
||||
.executeTakeFirst();
|
||||
|
||||
console.log({ row });
|
||||
.where("token", "=", token)
|
||||
.executeTakeFirstOrThrow();
|
||||
|
||||
const endpoint = `https://graph.facebook.com/v19.0/${pageId}/messages`;
|
||||
const inMessage = messaging?.message?.text;
|
||||
|
||||
const outgoingMessage = {
|
||||
recipient: { id: messaging?.sender?.id },
|
||||
message: { text: `"${inMessage}", right back at you!` },
|
||||
recipient: { id: message.recipient },
|
||||
message: { text: `"${message.text}", right back at you!` },
|
||||
messaging_type: "RESPONSE",
|
||||
access_token: row?.pageAccessToken,
|
||||
access_token: pageAccessToken,
|
||||
};
|
||||
console.log({ outgoingMessage });
|
||||
const response = await fetch(endpoint, {
|
||||
|
||||
await fetch(endpoint, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(outgoingMessage),
|
||||
});
|
||||
|
||||
console.log({ response });
|
||||
|
||||
console.log(message);
|
||||
const wu = await getWorkerUtils();
|
||||
|
||||
await wu.addJob("receive_facebook_message", message);
|
||||
|
||||
return NextResponse.json({ response: "ok" });
|
||||
|
||||
// withDb(async (db: AppDatabase) => {
|
||||
// await notifyWebhooks(db, options);
|
||||
// });
|
||||
};
|
||||
|
||||
export default sendFacebookMessageTask;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
import { db, getWorkerUtils } from "bridge-common";
|
||||
|
||||
interface ReceiveSignalMessageTaskOptions {
|
||||
message: any;
|
||||
}
|
||||
|
||||
const receiveSignalMessageTask = async ({
|
||||
message,
|
||||
}: ReceiveSignalMessageTaskOptions): Promise<void> => {};
|
||||
|
||||
export default receiveSignalMessageTask;
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import { db, getWorkerUtils } from "bridge-common";
|
||||
|
||||
interface SendSignalMessageTaskOptions {
|
||||
message: any;
|
||||
}
|
||||
|
||||
const sendSignalMessageTask = async ({
|
||||
message,
|
||||
}: SendSignalMessageTaskOptions): Promise<void> => {};
|
||||
|
||||
export default sendSignalMessageTask;
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import { db, getWorkerUtils } from "bridge-common";
|
||||
|
||||
interface ReceiveVoiceMessageTaskOptions {
|
||||
message: any;
|
||||
}
|
||||
|
||||
const receiveVoiceMessageTask = async ({
|
||||
message,
|
||||
}: ReceiveVoiceMessageTaskOptions): Promise<void> => {};
|
||||
|
||||
export default receiveVoiceMessageTask;
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import { db, getWorkerUtils } from "bridge-common";
|
||||
|
||||
interface SendVoiceMessageTaskOptions {
|
||||
message: any;
|
||||
}
|
||||
|
||||
const sendVoiceMessageTask = async ({
|
||||
message,
|
||||
}: SendVoiceMessageTaskOptions): Promise<void> => {};
|
||||
|
||||
export default sendVoiceMessageTask;
|
||||
|
|
@ -1,4 +1,17 @@
|
|||
import { db, getWorkerUtils } from "bridge-common";
|
||||
|
||||
interface ReceiveWhatsappMessageTaskOptions {
|
||||
message: any;
|
||||
}
|
||||
|
||||
const receiveWhatsappMessageTask = async ({
|
||||
message,
|
||||
}: ReceiveWhatsappMessageTaskOptions): Promise<void> => {};
|
||||
|
||||
export default receiveWhatsappMessageTask;
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
/*
|
||||
import { withDb, AppDatabase } from "../../lib/db";
|
||||
import workerUtils from "../../lib/utils";
|
||||
|
||||
|
|
@ -93,3 +106,4 @@ const whatsappMessageTask = async (
|
|||
};
|
||||
|
||||
export default whatsappMessageTask;
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
import { db, getWorkerUtils } from "bridge-common";
|
||||
|
||||
interface SendWhatsappMessageTaskOptions {
|
||||
message: any;
|
||||
}
|
||||
|
||||
const sendWhatsappMessageTask = async ({
|
||||
message,
|
||||
}: SendWhatsappMessageTaskOptions): Promise<void> => {};
|
||||
|
||||
export default sendWhatsappMessageTask;
|
||||
57
package-lock.json
generated
57
package-lock.json
generated
|
|
@ -36,6 +36,8 @@
|
|||
"@mui/x-data-grid-pro": "^7.3.1",
|
||||
"@mui/x-date-pickers-pro": "^7.3.1",
|
||||
"@mui/x-license": "^7.2.0",
|
||||
"bridge-common": "*",
|
||||
"bridge-ui": "*",
|
||||
"date-fns": "^3.6.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"graphile-worker": "^0.16.6",
|
||||
|
|
@ -152,6 +154,7 @@
|
|||
"@babel/preset-env": "7.24.4",
|
||||
"@babel/preset-typescript": "7.24.1",
|
||||
"@types/fluent-ffmpeg": "^2.1.24",
|
||||
"dotenv": "^16.4.5",
|
||||
"eslint": "^9.0.0",
|
||||
"prettier": "^3.2.5",
|
||||
"ts-config": "*",
|
||||
|
|
@ -16430,8 +16433,58 @@
|
|||
}
|
||||
},
|
||||
"packages/bridge-ui": {
|
||||
"version": "1.0.0",
|
||||
"license": "ISC"
|
||||
"version": "0.2.0",
|
||||
"dependencies": {
|
||||
"@emotion/cache": "^11.11.0",
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/server": "^11.11.0",
|
||||
"@emotion/styled": "^11.11.5",
|
||||
"@mui/icons-material": "^5",
|
||||
"@mui/lab": "^5.0.0-alpha.170",
|
||||
"@mui/material": "^5",
|
||||
"@mui/x-data-grid-pro": "^7.3.1",
|
||||
"@mui/x-date-pickers-pro": "^7.3.1",
|
||||
"date-fns": "^3.6.0",
|
||||
"material-ui-popup-state": "^5.1.0",
|
||||
"next": "14.2.3",
|
||||
"react": "18.3.0",
|
||||
"react-cookie": "^7.1.4",
|
||||
"react-cookie-consent": "^9.0.0",
|
||||
"react-dom": "18.3.0",
|
||||
"react-iframe": "^1.8.5",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-polyglot": "^0.7.2",
|
||||
"tss-react": "^4.9.7",
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.24.4",
|
||||
"@types/node": "^20.12.7",
|
||||
"@types/react": "18.3.0",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"babel-loader": "^9.1.3",
|
||||
"eslint": "^8.0.0",
|
||||
"eslint-config-next": "^14.2.3",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-react": "^7.34.1",
|
||||
"file-loader": "^6.2.0",
|
||||
"typescript": "5.4.5"
|
||||
}
|
||||
},
|
||||
"packages/bridge-ui/node_modules/uuid": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
||||
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"packages/eslint-config": {
|
||||
"version": "0.3.10",
|
||||
|
|
|
|||
|
|
@ -7,8 +7,9 @@ import type {
|
|||
Insertable,
|
||||
Updateable,
|
||||
} from "kysely";
|
||||
import { Pool, types } from "pg";
|
||||
import pg from "pg";
|
||||
import { KyselyAuth } from "@auth/kysely-adapter";
|
||||
const { Pool, types } = pg;
|
||||
|
||||
type Timestamp = ColumnType<Date, Date | string>;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@
|
|||
"author": "Darren Clarke <darren@redaranj.com>",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"dev": "NODE_OPTIONS=\"--loader ts-node/esm\" graphile-worker"
|
||||
"build": "tsc -p tsconfig.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@auth/kysely-adapter": "^1.0.0",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"target": "esnext",
|
||||
"lib": ["esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -25,7 +25,7 @@ export class Facebook extends Service {
|
|||
|
||||
const message = await req.json();
|
||||
const worker = await getWorkerUtils();
|
||||
await worker.addJob("receive_facebook_message", message);
|
||||
await worker.addJob("facebook/receive-facebook-message", { message });
|
||||
|
||||
return NextResponse.json({ response: "ok" });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,12 +48,16 @@ export type ServiceConfig = {
|
|||
};
|
||||
|
||||
export type ServiceParams = {
|
||||
service: string;
|
||||
token?: string;
|
||||
params: {
|
||||
service: string;
|
||||
token?: string;
|
||||
};
|
||||
};
|
||||
|
||||
export class Service {
|
||||
async getBot({ service, token }: ServiceParams): Promise<NextResponse> {
|
||||
async getBot({
|
||||
params: { service, token },
|
||||
}: ServiceParams): Promise<NextResponse> {
|
||||
const table = getServiceTable(service);
|
||||
const row = await db
|
||||
.selectFrom(table)
|
||||
|
|
@ -66,11 +70,14 @@ export class Service {
|
|||
|
||||
async sendMessage(
|
||||
req: NextRequest,
|
||||
{ service, token }: ServiceParams,
|
||||
{ params: { service, token } }: ServiceParams,
|
||||
): Promise<NextResponse> {
|
||||
const message = await req.json();
|
||||
const worker = await getWorkerUtils();
|
||||
await worker.addJob(`send_${service}_message`, { token, message });
|
||||
await worker.addJob(`${service}/send-${service}-message`, {
|
||||
token,
|
||||
message,
|
||||
});
|
||||
|
||||
return NextResponse.json({ response: "ok" });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { Facebook } from "./facebook";
|
|||
import { Signal } from "./signal";
|
||||
import { Whatsapp } from "./whatsapp";
|
||||
|
||||
export const getService = ({ service }: ServiceParams): Service => {
|
||||
export const getService = ({ params: { service } }: ServiceParams): Service => {
|
||||
if (service === "facebook") {
|
||||
return new Facebook();
|
||||
} else if (service === "signal") {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue