Repo cleanup

This commit is contained in:
Darren Clarke 2026-02-10 08:36:04 +01:00
parent 59872f579a
commit e941353b64
444 changed files with 1485 additions and 21978 deletions

View file

@ -9,16 +9,13 @@
"@hapi/hapi": "^21.4.3",
"@hapipal/schmervice": "^3.0.0",
"@hapipal/toys": "^4.0.0",
"@link-stack/bridge-common": "workspace:*",
"@link-stack/logger": "workspace:*",
"@whiskeysockets/baileys": "6.7.21",
"hapi-pino": "^13.0.0",
"link-preview-js": "^3.1.0"
"link-preview-js": "^3.1.0",
"pino": "^9.6.0",
"pino-pretty": "^13.0.0"
},
"devDependencies": {
"@link-stack/eslint-config": "workspace:*",
"@link-stack/jest-config": "workspace:*",
"@link-stack/typescript-config": "workspace:*",
"@types/long": "^5",
"@types/node": "*",
"dotenv-cli": "^10.0.0",

View file

@ -0,0 +1,36 @@
/**
* Attachment size configuration for messaging channels
*
* Environment variables:
* - BRIDGE_MAX_ATTACHMENT_SIZE_MB: Maximum size for a single attachment in MB (default: 50)
*/
/**
* Get the maximum attachment size in bytes from environment variable
* Defaults to 50MB if not set
*/
export function getMaxAttachmentSize(): number {
const envValue = process.env.BRIDGE_MAX_ATTACHMENT_SIZE_MB;
const sizeInMB = envValue ? parseInt(envValue, 10) : 50;
// Validate the value
if (isNaN(sizeInMB) || sizeInMB <= 0) {
console.warn(`Invalid BRIDGE_MAX_ATTACHMENT_SIZE_MB value: ${envValue}, using default 50MB`);
return 50 * 1024 * 1024;
}
return sizeInMB * 1024 * 1024;
}
/**
* Get the maximum total size for all attachments in a message
* This is 4x the single attachment size
*/
export function getMaxTotalAttachmentSize(): number {
return getMaxAttachmentSize() * 4;
}
/**
* Maximum number of attachments per message
*/
export const MAX_ATTACHMENTS = 10;

View file

@ -9,7 +9,7 @@ import {
SendMessageRoute,
ReceiveMessageRoute,
} from "./routes.ts";
import { createLogger } from "@link-stack/logger";
import { createLogger } from "./lib/logger";
const logger = createLogger("bridge-whatsapp-index");

View file

@ -0,0 +1,77 @@
import pino, { Logger as PinoLogger, LoggerOptions } from 'pino';
export type Logger = PinoLogger;
const getLogLevel = (): string => {
return process.env.LOG_LEVEL || (process.env.NODE_ENV === 'production' ? 'info' : 'debug');
};
const getPinoConfig = (): LoggerOptions => {
const isDevelopment = process.env.NODE_ENV !== 'production';
const baseConfig: LoggerOptions = {
level: getLogLevel(),
formatters: {
level: (label) => {
return { level: label.toUpperCase() };
},
},
timestamp: () => `,"timestamp":"${new Date(Date.now()).toISOString()}"`,
redact: {
paths: [
'password',
'token',
'secret',
'api_key',
'apiKey',
'authorization',
'cookie',
'access_token',
'refresh_token',
'*.password',
'*.token',
'*.secret',
'*.api_key',
'*.apiKey',
'*.authorization',
'*.cookie',
'*.access_token',
'*.refresh_token',
'headers.authorization',
'headers.cookie',
'headers.Authorization',
'headers.Cookie',
'credentials.password',
'credentials.secret',
'credentials.token',
],
censor: '[REDACTED]',
},
};
if (isDevelopment) {
return {
...baseConfig,
transport: {
target: 'pino-pretty',
options: {
colorize: true,
translateTime: 'SYS:standard',
ignore: 'pid,hostname',
singleLine: false,
messageFormat: '{msg}',
},
},
};
}
return baseConfig;
};
export const logger: Logger = pino(getPinoConfig());
export const createLogger = (name: string, context?: Record<string, any>): Logger => {
return logger.child({ name, ...context });
};
export default logger;

View file

@ -12,12 +12,12 @@ import makeWASocket, {
type MediaType = "audio" | "document" | "image" | "video" | "sticker";
import fs from "fs";
import { createLogger } from "@link-stack/logger";
import { createLogger } from "./lib/logger";
import {
getMaxAttachmentSize,
getMaxTotalAttachmentSize,
MAX_ATTACHMENTS,
} from "@link-stack/bridge-common";
} from "./attachments";
const logger = createLogger("bridge-whatsapp-service");
@ -287,8 +287,10 @@ export default class WhatsappService extends Service {
mimeType,
};
await fetch(
`${process.env.BRIDGE_FRONTEND_URL}/api/whatsapp/bots/${botID}/receive`,
// Send directly to Zammad's WhatsApp webhook
const zammadUrl = process.env.ZAMMAD_URL || 'http://zammad-nginx:8080';
const response = await fetch(
`${zammadUrl}/api/v1/channels_cdr_whatsapp_bot_webhook/${botID}`,
{
method: "POST",
headers: {
@ -297,6 +299,11 @@ export default class WhatsappService extends Service {
body: JSON.stringify(payload),
},
);
if (!response.ok) {
const errorText = await response.text();
logger.error({ status: response.status, error: errorText, botID }, "Failed to send message to Zammad");
}
}
}
}
@ -452,7 +459,7 @@ export default class WhatsappService extends Service {
throw new Error(
"Message polling is no longer supported in Baileys 7.x. " +
"Please configure a webhook to receive messages instead. " +
"Messages are automatically forwarded to BRIDGE_FRONTEND_URL/api/whatsapp/bots/{id}/receive"
"Messages are automatically forwarded to Zammad via ZAMMAD_URL/api/v1/channels_cdr_whatsapp_bot_webhook/{id}"
);
}
}

View file

@ -1,17 +1,26 @@
{
"extends": "@link-stack/typescript-config/tsconfig.node.json",
"compilerOptions": {
"module": "NodeNext",
"target": "es2022",
"esModuleInterop": true,
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "build/main",
"rootDir": "src",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"inlineSources": true,
"skipLibCheck": true,
"types": ["node"],
"lib": ["es2022", "DOM"],
"strict": true,
"allowJs": true,
"forceConsistentCasingInFileNames": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"isolatedModules": true,
"incremental": true,
"composite": true,
"rewriteRelativeImportExtensions": true
"rewriteRelativeImportExtensions": true,
"types": ["node"],
"lib": ["es2022", "DOM"]
},
"include": ["src/**/*.ts", "src/**/.*.ts"],
"exclude": ["node_modules/**"]