@gamastudio/sendwave-provider 1.0.3 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/build.yml +31 -31
- package/README.md +267 -25
- package/build/application/connection/connection-polling.service.d.ts +16 -0
- package/build/application/connection/connection-polling.service.js +49 -0
- package/build/application/message-buffer/message-buffer.service.d.ts +11 -0
- package/build/application/message-buffer/message-buffer.service.js +79 -0
- package/build/application/messaging/message-sender.service.d.ts +40 -0
- package/build/application/messaging/message-sender.service.js +101 -0
- package/build/application/messaging/strategies/interactive.strategy.d.ts +14 -0
- package/build/application/messaging/strategies/interactive.strategy.js +88 -0
- package/build/application/messaging/strategies/list.strategy.d.ts +8 -0
- package/build/application/messaging/strategies/list.strategy.js +61 -0
- package/build/application/messaging/strategies/media.strategy.d.ts +32 -0
- package/build/application/messaging/strategies/media.strategy.js +97 -0
- package/build/application/messaging/strategies/misc.strategy.d.ts +23 -0
- package/build/application/messaging/strategies/misc.strategy.js +95 -0
- package/build/application/messaging/strategies/presence.strategy.d.ts +8 -0
- package/build/application/messaging/strategies/presence.strategy.js +24 -0
- package/build/application/messaging/strategies/send-strategy.interface.d.ts +4 -0
- package/build/application/messaging/strategies/send-strategy.interface.js +2 -0
- package/build/application/messaging/strategies/text.strategy.d.ts +8 -0
- package/build/application/messaging/strategies/text.strategy.js +22 -0
- package/build/application/messaging/strategies/voice.strategy.d.ts +8 -0
- package/build/application/messaging/strategies/voice.strategy.js +37 -0
- package/build/application/queue-flow/queue-flow.service.d.ts +34 -0
- package/build/application/queue-flow/queue-flow.service.js +68 -0
- package/build/config/constants.d.ts +14 -0
- package/build/config/constants.js +17 -0
- package/build/config/defaults.d.ts +8 -0
- package/build/config/defaults.js +110 -0
- package/build/constants/html/error.js +34 -34
- package/build/constants/html/home.js +23 -23
- package/build/constants/svg/wave-error.js +88 -88
- package/build/constants/svg/wave.js +88 -88
- package/build/core/interface/provider.interface.d.ts +2 -1
- package/build/core/interface/types.d.ts +12 -0
- package/build/domain/interfaces/index.d.ts +2 -0
- package/build/domain/interfaces/index.js +18 -0
- package/build/domain/interfaces/parsed-message.interface.d.ts +16 -0
- package/build/domain/interfaces/parsed-message.interface.js +2 -0
- package/build/domain/interfaces/provider.interface.d.ts +21 -0
- package/build/domain/interfaces/provider.interface.js +2 -0
- package/build/domain/types/config.types.d.ts +43 -0
- package/build/domain/types/config.types.js +2 -0
- package/build/domain/types/index.d.ts +2 -0
- package/build/domain/types/index.js +18 -0
- package/build/domain/types/message.types.d.ts +134 -0
- package/build/domain/types/message.types.js +2 -0
- package/build/index.d.ts +5 -4
- package/build/index.js +7 -6
- package/build/infrastructure/http/axios/retry.interceptor.d.ts +2 -0
- package/build/infrastructure/http/axios/retry.interceptor.js +21 -0
- package/build/infrastructure/http/axios/sendwave-api.factory.d.ts +15 -0
- package/build/infrastructure/http/axios/sendwave-api.factory.js +50 -0
- package/build/infrastructure/http/middleware/body-parser.middleware.d.ts +2 -0
- package/build/infrastructure/http/middleware/body-parser.middleware.js +28 -0
- package/build/infrastructure/http/middleware/cors.middleware.d.ts +6 -0
- package/build/infrastructure/http/middleware/cors.middleware.js +8 -0
- package/build/infrastructure/http/middleware/global-args.middleware.d.ts +2 -0
- package/build/infrastructure/http/middleware/global-args.middleware.js +9 -0
- package/build/infrastructure/http/middleware/rate-limiter.middleware.d.ts +4 -0
- package/build/infrastructure/http/middleware/rate-limiter.middleware.js +31 -0
- package/build/infrastructure/http/middleware/static-assets.middleware.d.ts +2 -0
- package/build/infrastructure/http/middleware/static-assets.middleware.js +8 -0
- package/build/infrastructure/http/routes/routes.d.ts +4 -0
- package/build/infrastructure/http/routes/routes.js +56 -0
- package/build/infrastructure/media/media-detector.service.d.ts +27 -0
- package/build/infrastructure/media/media-detector.service.js +123 -0
- package/build/infrastructure/parser/incoming-message.parser.d.ts +2 -0
- package/build/infrastructure/parser/incoming-message.parser.js +41 -0
- package/build/infrastructure/persistence/instance.registry.d.ts +21 -0
- package/build/infrastructure/persistence/instance.registry.js +44 -0
- package/build/infrastructure/persistence/sendwave-api.repository.d.ts +21 -0
- package/build/infrastructure/persistence/sendwave-api.repository.js +64 -0
- package/build/package.json +48 -48
- package/build/presentation/pages/assets/logo.svg.d.ts +1 -0
- package/build/presentation/pages/assets/logo.svg.js +4 -0
- package/build/presentation/pages/assets/wave-error.svg.d.ts +1 -0
- package/build/presentation/pages/assets/wave-error.svg.js +92 -0
- package/build/presentation/pages/assets/wave.svg.d.ts +1 -0
- package/build/presentation/pages/assets/wave.svg.js +92 -0
- package/build/presentation/pages/connect.page.d.ts +1 -0
- package/build/presentation/pages/connect.page.js +182 -0
- package/build/presentation/pages/error.page.d.ts +1 -0
- package/build/presentation/pages/error.page.js +42 -0
- package/build/presentation/pages/home.page.d.ts +1 -0
- package/build/presentation/pages/home.page.js +29 -0
- package/build/presentation/provider/index.d.ts +2 -0
- package/build/presentation/provider/index.js +18 -0
- package/build/presentation/provider/sendwave-core.d.ts +25 -0
- package/build/presentation/provider/sendwave-core.js +125 -0
- package/build/presentation/provider/sendwave.provider.d.ts +76 -0
- package/build/presentation/provider/sendwave.provider.js +359 -0
- package/build/provider/sender.d.ts +3 -1
- package/build/provider/sender.js +52 -34
- package/build/shared/exceptions/payload-too-large.exception.d.ts +4 -0
- package/build/shared/exceptions/payload-too-large.exception.js +11 -0
- package/build/shared/utils/error-extractor.d.ts +1 -0
- package/build/shared/utils/error-extractor.js +7 -0
- package/build/shared/utils/size-parser.d.ts +1 -0
- package/build/shared/utils/size-parser.js +17 -0
- package/package.json +48 -48
- package/tsconfig.json +7 -5
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SendWaveApiFactory = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const https_1 = require("https");
|
|
9
|
+
const size_parser_1 = require("../../../shared/utils/size-parser");
|
|
10
|
+
const constants_1 = require("../../../config/constants");
|
|
11
|
+
const retry_interceptor_1 = require("./retry.interceptor");
|
|
12
|
+
class SendWaveApiFactory {
|
|
13
|
+
constructor(config) {
|
|
14
|
+
this.config = config;
|
|
15
|
+
}
|
|
16
|
+
create() {
|
|
17
|
+
const url = this.resolveUrl();
|
|
18
|
+
const payloadLimits = this.config.payloadLimits || {};
|
|
19
|
+
const maxContentLength = (0, size_parser_1.parseSize)(payloadLimits.json || "50mb");
|
|
20
|
+
const instance = axios_1.default.create({
|
|
21
|
+
baseURL: url,
|
|
22
|
+
httpsAgent: new https_1.Agent({ rejectUnauthorized: false }),
|
|
23
|
+
headers: {
|
|
24
|
+
"Content-Type": "application/json",
|
|
25
|
+
apikey: this.config.apiKey,
|
|
26
|
+
},
|
|
27
|
+
maxContentLength,
|
|
28
|
+
maxBodyLength: maxContentLength,
|
|
29
|
+
timeout: constants_1.API_TIMEOUT_MS,
|
|
30
|
+
});
|
|
31
|
+
instance.interceptors.request.use((config) => {
|
|
32
|
+
const contentLength = (config.headers && config.headers["content-length"]) ||
|
|
33
|
+
(config.data ? JSON.stringify(config.data).length : 0);
|
|
34
|
+
if (contentLength > constants_1.LARGE_REQUEST_THRESHOLD) {
|
|
35
|
+
console.log(`[LargeRequest] Sending ${Math.round((contentLength / 1024 / 1024) * 100) / 100}MB to ${config.url}`);
|
|
36
|
+
}
|
|
37
|
+
return config;
|
|
38
|
+
}, (error) => Promise.reject(error));
|
|
39
|
+
(0, retry_interceptor_1.attachRetryInterceptor)(instance);
|
|
40
|
+
return instance;
|
|
41
|
+
}
|
|
42
|
+
resolveUrl() {
|
|
43
|
+
var _a;
|
|
44
|
+
const candidate = (_a = this.config.url) === null || _a === void 0 ? void 0 : _a.trim();
|
|
45
|
+
if (candidate)
|
|
46
|
+
return candidate;
|
|
47
|
+
return constants_1.DEFAULT_FALLBACK_URL;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.SendWaveApiFactory = SendWaveApiFactory;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.bodyParserMiddleware = bodyParserMiddleware;
|
|
7
|
+
const body_parser_1 = __importDefault(require("body-parser"));
|
|
8
|
+
function bodyParserMiddleware(globalVendorArgs) {
|
|
9
|
+
const payloadLimits = globalVendorArgs.payloadLimits || {};
|
|
10
|
+
return [
|
|
11
|
+
body_parser_1.default.json({
|
|
12
|
+
limit: payloadLimits.json || "50mb",
|
|
13
|
+
type: "application/json",
|
|
14
|
+
}),
|
|
15
|
+
body_parser_1.default.urlencoded({
|
|
16
|
+
limit: payloadLimits.urlencoded || "50mb",
|
|
17
|
+
extended: true,
|
|
18
|
+
}),
|
|
19
|
+
body_parser_1.default.text({
|
|
20
|
+
limit: payloadLimits.text || "10mb",
|
|
21
|
+
type: "text/*",
|
|
22
|
+
}),
|
|
23
|
+
body_parser_1.default.raw({
|
|
24
|
+
limit: payloadLimits.json || "50mb",
|
|
25
|
+
type: "application/octet-stream",
|
|
26
|
+
}),
|
|
27
|
+
];
|
|
28
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.corsMiddleware = void 0;
|
|
7
|
+
const cors_1 = __importDefault(require("cors"));
|
|
8
|
+
exports.corsMiddleware = (0, cors_1.default)({ origin: "*", methods: "GET,POST" });
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.globalArgsMiddleware = globalArgsMiddleware;
|
|
4
|
+
function globalArgsMiddleware(globalVendorArgs) {
|
|
5
|
+
return (req, _, next) => {
|
|
6
|
+
req["globalVendorArgs"] = globalVendorArgs;
|
|
7
|
+
return next();
|
|
8
|
+
};
|
|
9
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RateLimiterMiddleware = void 0;
|
|
4
|
+
const constants_1 = require("../../../config/constants");
|
|
5
|
+
class RateLimiterMiddleware {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.limits = new Map();
|
|
8
|
+
this.handle = (req, res, next) => {
|
|
9
|
+
var _a;
|
|
10
|
+
const ip = (req.ip ||
|
|
11
|
+
req.headers["x-forwarded-for"] ||
|
|
12
|
+
((_a = req.connection) === null || _a === void 0 ? void 0 : _a.remoteAddress) ||
|
|
13
|
+
"unknown").toString();
|
|
14
|
+
const now = Date.now();
|
|
15
|
+
const rec = this.limits.get(ip) || { count: 0, windowStart: now };
|
|
16
|
+
if (now - rec.windowStart > constants_1.RATE_LIMIT_CONFIG.windowMs) {
|
|
17
|
+
rec.count = 0;
|
|
18
|
+
rec.windowStart = now;
|
|
19
|
+
}
|
|
20
|
+
rec.count += 1;
|
|
21
|
+
this.limits.set(ip, rec);
|
|
22
|
+
if (rec.count > constants_1.RATE_LIMIT_CONFIG.max) {
|
|
23
|
+
res.statusCode = 429;
|
|
24
|
+
res.setHeader("Content-Type", "application/json");
|
|
25
|
+
return res.end(JSON.stringify({ error: "Too Many Requests" }));
|
|
26
|
+
}
|
|
27
|
+
next();
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.RateLimiterMiddleware = RateLimiterMiddleware;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.staticAssetsMiddleware = void 0;
|
|
7
|
+
const sirv_1 = __importDefault(require("sirv"));
|
|
8
|
+
exports.staticAssetsMiddleware = (0, sirv_1.default)("public/assets", { dev: true });
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { InstanceRegistry } from "../../persistence/instance.registry";
|
|
2
|
+
export declare function createQrRouteHandler(registry: InstanceRegistry): (req: any, res: any) => Promise<any>;
|
|
3
|
+
export declare function createConnectionStateRouteHandler(registry: InstanceRegistry): (req: any, res: any) => Promise<any>;
|
|
4
|
+
export declare function createWebhookRouteHandler(vendor: any): any;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createQrRouteHandler = createQrRouteHandler;
|
|
4
|
+
exports.createConnectionStateRouteHandler = createConnectionStateRouteHandler;
|
|
5
|
+
exports.createWebhookRouteHandler = createWebhookRouteHandler;
|
|
6
|
+
function createQrRouteHandler(registry) {
|
|
7
|
+
return async (req, res) => {
|
|
8
|
+
var _a, _b;
|
|
9
|
+
const instanceName = (_a = req.params) === null || _a === void 0 ? void 0 : _a.instanceName;
|
|
10
|
+
const instance = instanceName
|
|
11
|
+
? registry.get(instanceName)
|
|
12
|
+
: registry.getDefault();
|
|
13
|
+
if (!instance) {
|
|
14
|
+
res.statusCode = 404;
|
|
15
|
+
res.setHeader("Content-Type", "application/json");
|
|
16
|
+
return res.end(JSON.stringify({ error: "Instance not found" }));
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
const response = await instance.api.getQrCode();
|
|
20
|
+
res.setHeader("Content-Type", "application/json");
|
|
21
|
+
res.end(JSON.stringify((_b = response === null || response === void 0 ? void 0 : response.data) !== null && _b !== void 0 ? _b : {}));
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
res.statusCode = 502;
|
|
25
|
+
res.setHeader("Content-Type", "application/json");
|
|
26
|
+
res.end(JSON.stringify({ error: "No se pudo obtener el código de conexión" }));
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function createConnectionStateRouteHandler(registry) {
|
|
31
|
+
return async (req, res) => {
|
|
32
|
+
var _a, _b;
|
|
33
|
+
const instanceName = (_a = req.params) === null || _a === void 0 ? void 0 : _a.instanceName;
|
|
34
|
+
const instance = instanceName
|
|
35
|
+
? registry.get(instanceName)
|
|
36
|
+
: registry.getDefault();
|
|
37
|
+
if (!instance) {
|
|
38
|
+
res.statusCode = 404;
|
|
39
|
+
res.setHeader("Content-Type", "application/json");
|
|
40
|
+
return res.end(JSON.stringify({ error: "Instance not found" }));
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
const response = await instance.api.getConnectionState();
|
|
44
|
+
res.setHeader("Content-Type", "application/json");
|
|
45
|
+
res.end(JSON.stringify((_b = response === null || response === void 0 ? void 0 : response.data) !== null && _b !== void 0 ? _b : {}));
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
res.statusCode = 502;
|
|
49
|
+
res.setHeader("Content-Type", "application/json");
|
|
50
|
+
res.end(JSON.stringify({ error: "No se pudo obtener el estado" }));
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function createWebhookRouteHandler(vendor) {
|
|
55
|
+
return vendor.incomingMsg.bind(vendor);
|
|
56
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { MediaLimits } from "../../domain/types";
|
|
2
|
+
export interface MediaDetectionResult {
|
|
3
|
+
media?: string;
|
|
4
|
+
mimeType?: string;
|
|
5
|
+
mediaType?: string;
|
|
6
|
+
fileName?: string;
|
|
7
|
+
size?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare class MediaDetector {
|
|
10
|
+
static instance: MediaDetector;
|
|
11
|
+
private mediaLimits;
|
|
12
|
+
constructor(limits?: MediaLimits);
|
|
13
|
+
static getInstance(limits?: MediaLimits): MediaDetector;
|
|
14
|
+
updateLimits(limits: MediaLimits): void;
|
|
15
|
+
isRemoteUrl(url: string): boolean;
|
|
16
|
+
processMedia(input: string): Promise<MediaDetectionResult>;
|
|
17
|
+
validateUrlSize(url: string, mediaType: string): Promise<number>;
|
|
18
|
+
convertPathToBase64(filePath: string): Promise<MediaDetectionResult>;
|
|
19
|
+
getMimeTypeFromUrl(url: string): Promise<{
|
|
20
|
+
mediaType: string | null;
|
|
21
|
+
mimeType: string | null;
|
|
22
|
+
}>;
|
|
23
|
+
mapMimeToCategory(mimeType: string): "image" | "video" | "audio" | "document" | "unknown";
|
|
24
|
+
private validateSize;
|
|
25
|
+
private extractFileNameFromUrl;
|
|
26
|
+
}
|
|
27
|
+
export declare const mediaDetector: MediaDetector;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.mediaDetector = exports.MediaDetector = void 0;
|
|
7
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const mime_types_1 = __importDefault(require("mime-types"));
|
|
10
|
+
const axios_1 = __importDefault(require("axios"));
|
|
11
|
+
const size_parser_1 = require("../../shared/utils/size-parser");
|
|
12
|
+
class MediaDetector {
|
|
13
|
+
constructor(limits) {
|
|
14
|
+
this.mediaLimits = {
|
|
15
|
+
image: "10mb",
|
|
16
|
+
video: "100mb",
|
|
17
|
+
audio: "50mb",
|
|
18
|
+
document: "25mb",
|
|
19
|
+
...limits,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
static getInstance(limits) {
|
|
23
|
+
if (!MediaDetector.instance) {
|
|
24
|
+
MediaDetector.instance = new MediaDetector(limits);
|
|
25
|
+
}
|
|
26
|
+
return MediaDetector.instance;
|
|
27
|
+
}
|
|
28
|
+
updateLimits(limits) {
|
|
29
|
+
this.mediaLimits = { ...this.mediaLimits, ...limits };
|
|
30
|
+
}
|
|
31
|
+
isRemoteUrl(url) {
|
|
32
|
+
try {
|
|
33
|
+
const u = new URL(url);
|
|
34
|
+
return u.protocol === "http:" || u.protocol === "https:";
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async processMedia(input) {
|
|
41
|
+
if (this.isRemoteUrl(input)) {
|
|
42
|
+
const { mediaType, mimeType } = await this.getMimeTypeFromUrl(input);
|
|
43
|
+
if (!mediaType || !mimeType)
|
|
44
|
+
throw new Error("No se pudo determinar el tipo MIME de la URL remota");
|
|
45
|
+
const size = await this.validateUrlSize(input, mediaType);
|
|
46
|
+
const fileName = this.extractFileNameFromUrl(input);
|
|
47
|
+
return { media: input, mimeType, fileName, mediaType, size };
|
|
48
|
+
}
|
|
49
|
+
return this.convertPathToBase64(input);
|
|
50
|
+
}
|
|
51
|
+
async validateUrlSize(url, mediaType) {
|
|
52
|
+
var _a;
|
|
53
|
+
try {
|
|
54
|
+
const response = await axios_1.default.head(url);
|
|
55
|
+
const contentLength = parseInt(String((_a = response.headers["content-length"]) !== null && _a !== void 0 ? _a : "0"));
|
|
56
|
+
if (contentLength > 0) {
|
|
57
|
+
this.validateSize(contentLength, mediaType);
|
|
58
|
+
}
|
|
59
|
+
return contentLength;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
if (error.message.includes("exceeds limit"))
|
|
63
|
+
throw error;
|
|
64
|
+
return 0;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async convertPathToBase64(filePath) {
|
|
68
|
+
const mimeType = mime_types_1.default.lookup(filePath).toString();
|
|
69
|
+
const mediaType = this.mapMimeToCategory(mimeType);
|
|
70
|
+
if (!mediaType)
|
|
71
|
+
throw new Error("No se pudo determinar el tipo MIME del archivo");
|
|
72
|
+
const stats = await promises_1.default.stat(filePath);
|
|
73
|
+
this.validateSize(stats.size, mediaType);
|
|
74
|
+
const fileBuffer = await promises_1.default.readFile(filePath);
|
|
75
|
+
const media = fileBuffer.toString("base64");
|
|
76
|
+
const fileName = path_1.default.basename(filePath);
|
|
77
|
+
return { media, mediaType, fileName, mimeType, size: stats.size };
|
|
78
|
+
}
|
|
79
|
+
async getMimeTypeFromUrl(url) {
|
|
80
|
+
try {
|
|
81
|
+
const res = await axios_1.default.head(url);
|
|
82
|
+
const contentType = res.headers["content-type"];
|
|
83
|
+
const contentTypeStr = contentType ? String(contentType) : null;
|
|
84
|
+
const mediaType = this.mapMimeToCategory(contentTypeStr !== null && contentTypeStr !== void 0 ? contentTypeStr : "unknown");
|
|
85
|
+
return { mediaType: mediaType || null, mimeType: contentTypeStr };
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return { mediaType: null, mimeType: null };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
mapMimeToCategory(mimeType) {
|
|
92
|
+
if (!mimeType)
|
|
93
|
+
return "unknown";
|
|
94
|
+
const normalized = mimeType.toLowerCase().split(";")[0].trim();
|
|
95
|
+
if (normalized.startsWith("image/"))
|
|
96
|
+
return "image";
|
|
97
|
+
if (normalized.startsWith("video/"))
|
|
98
|
+
return "video";
|
|
99
|
+
if (normalized.startsWith("audio/"))
|
|
100
|
+
return "audio";
|
|
101
|
+
if (normalized.startsWith("application/") ||
|
|
102
|
+
normalized.startsWith("text/")) {
|
|
103
|
+
return "document";
|
|
104
|
+
}
|
|
105
|
+
return "document";
|
|
106
|
+
}
|
|
107
|
+
validateSize(size, mediaType) {
|
|
108
|
+
const limitStr = this.mediaLimits[mediaType] || "10mb";
|
|
109
|
+
const limit = (0, size_parser_1.parseSize)(limitStr, 10 * 1024 * 1024);
|
|
110
|
+
if (size > limit) {
|
|
111
|
+
const sizeMB = Math.round((size / 1024 / 1024) * 100) / 100;
|
|
112
|
+
const limitMB = Math.round((limit / 1024 / 1024) * 100) / 100;
|
|
113
|
+
throw new Error(`File size ${sizeMB}MB exceeds limit of ${limitMB}MB for ${mediaType} files`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
extractFileNameFromUrl(url) {
|
|
117
|
+
const urlObj = new URL(url);
|
|
118
|
+
const name = urlObj.pathname.split("/").pop();
|
|
119
|
+
return name || `file_${Date.now()}`;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
exports.MediaDetector = MediaDetector;
|
|
123
|
+
exports.mediaDetector = MediaDetector.getInstance();
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseIncomingMsg = parseIncomingMsg;
|
|
4
|
+
function parseIncomingMsg(payload) {
|
|
5
|
+
var _a, _b;
|
|
6
|
+
try {
|
|
7
|
+
const msg = payload;
|
|
8
|
+
if (msg.type === "reactionMessage")
|
|
9
|
+
return null;
|
|
10
|
+
if (!msg)
|
|
11
|
+
return null;
|
|
12
|
+
const messageId = msg.messageId || "";
|
|
13
|
+
const fromMe = msg.fromMe;
|
|
14
|
+
const remoteJid = msg.remoteJid || "";
|
|
15
|
+
const from = msg.from;
|
|
16
|
+
const to = ((_a = payload.inputs) === null || _a === void 0 ? void 0 : _a.instanceName) || "";
|
|
17
|
+
const name = msg.name;
|
|
18
|
+
const body = msg.body;
|
|
19
|
+
const type = msg.type;
|
|
20
|
+
const media = msg.media;
|
|
21
|
+
const caption = msg.caption;
|
|
22
|
+
return {
|
|
23
|
+
fromMe,
|
|
24
|
+
remoteJid,
|
|
25
|
+
messageId,
|
|
26
|
+
from,
|
|
27
|
+
to,
|
|
28
|
+
name,
|
|
29
|
+
body,
|
|
30
|
+
type,
|
|
31
|
+
media,
|
|
32
|
+
caption,
|
|
33
|
+
sessionId: (_b = payload.inputs) === null || _b === void 0 ? void 0 : _b.sessionId,
|
|
34
|
+
originalPayload: payload.originalPayload,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
console.error("[parseIncomingMsg] Error:", error);
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { GlobalVendorArgs, InstanceConfig } from "../../domain/types";
|
|
2
|
+
import { SendWaveApiRepository } from "./sendwave-api.repository";
|
|
3
|
+
import { MessageSenderService } from "../../application/messaging/message-sender.service";
|
|
4
|
+
export interface RegisteredInstance {
|
|
5
|
+
name: string;
|
|
6
|
+
apiKey: string;
|
|
7
|
+
api: SendWaveApiRepository;
|
|
8
|
+
sender: MessageSenderService;
|
|
9
|
+
}
|
|
10
|
+
export declare class InstanceRegistry {
|
|
11
|
+
private readonly sharedConfig;
|
|
12
|
+
private instances;
|
|
13
|
+
constructor(sharedConfig: Partial<GlobalVendorArgs>);
|
|
14
|
+
register(config: InstanceConfig): RegisteredInstance;
|
|
15
|
+
registerMany(configs: InstanceConfig[]): void;
|
|
16
|
+
get(name: string): RegisteredInstance | undefined;
|
|
17
|
+
has(name: string): boolean;
|
|
18
|
+
getAll(): RegisteredInstance[];
|
|
19
|
+
getDefault(): RegisteredInstance | undefined;
|
|
20
|
+
get names(): string[];
|
|
21
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InstanceRegistry = void 0;
|
|
4
|
+
const sendwave_api_repository_1 = require("./sendwave-api.repository");
|
|
5
|
+
const message_sender_service_1 = require("../../application/messaging/message-sender.service");
|
|
6
|
+
class InstanceRegistry {
|
|
7
|
+
constructor(sharedConfig) {
|
|
8
|
+
this.sharedConfig = sharedConfig;
|
|
9
|
+
this.instances = new Map();
|
|
10
|
+
}
|
|
11
|
+
register(config) {
|
|
12
|
+
const api = sendwave_api_repository_1.SendWaveApiRepository.forInstance(this.sharedConfig, config);
|
|
13
|
+
const sender = new message_sender_service_1.MessageSenderService(api);
|
|
14
|
+
const instance = {
|
|
15
|
+
name: config.name,
|
|
16
|
+
apiKey: config.apiKey,
|
|
17
|
+
api,
|
|
18
|
+
sender,
|
|
19
|
+
};
|
|
20
|
+
this.instances.set(config.name, instance);
|
|
21
|
+
return instance;
|
|
22
|
+
}
|
|
23
|
+
registerMany(configs) {
|
|
24
|
+
for (const config of configs) {
|
|
25
|
+
this.register(config);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
get(name) {
|
|
29
|
+
return this.instances.get(name);
|
|
30
|
+
}
|
|
31
|
+
has(name) {
|
|
32
|
+
return this.instances.has(name);
|
|
33
|
+
}
|
|
34
|
+
getAll() {
|
|
35
|
+
return Array.from(this.instances.values());
|
|
36
|
+
}
|
|
37
|
+
getDefault() {
|
|
38
|
+
return this.getAll()[0];
|
|
39
|
+
}
|
|
40
|
+
get names() {
|
|
41
|
+
return Array.from(this.instances.keys());
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.InstanceRegistry = InstanceRegistry;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { GlobalVendorArgs, InstanceConfig } from "../../domain/types";
|
|
2
|
+
import { AxiosResponse } from "axios";
|
|
3
|
+
export declare class SendWaveApiRepository {
|
|
4
|
+
private readonly api;
|
|
5
|
+
private readonly instanceName;
|
|
6
|
+
constructor(globalVendorArgs: GlobalVendorArgs);
|
|
7
|
+
static forInstance(sharedConfig: Partial<GlobalVendorArgs>, instance: InstanceConfig): SendWaveApiRepository;
|
|
8
|
+
getConnectionState(): Promise<AxiosResponse>;
|
|
9
|
+
getQrCode(): Promise<AxiosResponse>;
|
|
10
|
+
sendPresence(payload: any): Promise<AxiosResponse>;
|
|
11
|
+
sendText(payload: any): Promise<AxiosResponse>;
|
|
12
|
+
sendMedia(payload: any): Promise<AxiosResponse>;
|
|
13
|
+
sendWhatsAppAudio(payload: any): Promise<AxiosResponse>;
|
|
14
|
+
sendList(payload: any): Promise<AxiosResponse>;
|
|
15
|
+
sendButtons(payload: any): Promise<AxiosResponse>;
|
|
16
|
+
sendCarousel(payload: any): Promise<AxiosResponse>;
|
|
17
|
+
sendPoll(payload: any): Promise<AxiosResponse>;
|
|
18
|
+
sendLocation(payload: any): Promise<AxiosResponse>;
|
|
19
|
+
sendReaction(payload: any): Promise<AxiosResponse>;
|
|
20
|
+
markMessagesAsRead(payload: any): Promise<AxiosResponse>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SendWaveApiRepository = void 0;
|
|
4
|
+
const sendwave_api_factory_1 = require("../http/axios/sendwave-api.factory");
|
|
5
|
+
class SendWaveApiRepository {
|
|
6
|
+
constructor(globalVendorArgs) {
|
|
7
|
+
const name = globalVendorArgs.name || "bot";
|
|
8
|
+
const apiKey = globalVendorArgs.apiKey || "";
|
|
9
|
+
this.api = new sendwave_api_factory_1.SendWaveApiFactory({
|
|
10
|
+
name,
|
|
11
|
+
apiKey,
|
|
12
|
+
url: globalVendorArgs.url,
|
|
13
|
+
payloadLimits: globalVendorArgs.payloadLimits,
|
|
14
|
+
}).create();
|
|
15
|
+
this.instanceName = name;
|
|
16
|
+
}
|
|
17
|
+
static forInstance(sharedConfig, instance) {
|
|
18
|
+
return new SendWaveApiRepository({
|
|
19
|
+
...sharedConfig,
|
|
20
|
+
name: instance.name,
|
|
21
|
+
apiKey: instance.apiKey,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
getConnectionState() {
|
|
25
|
+
return this.api.get(`/instance/connectionState/${this.instanceName}`);
|
|
26
|
+
}
|
|
27
|
+
getQrCode() {
|
|
28
|
+
return this.api.get(`/instance/connect/${this.instanceName}`);
|
|
29
|
+
}
|
|
30
|
+
sendPresence(payload) {
|
|
31
|
+
return this.api.post(`/chat/sendPresence/${this.instanceName}`, payload);
|
|
32
|
+
}
|
|
33
|
+
sendText(payload) {
|
|
34
|
+
return this.api.post(`/message/sendText/${this.instanceName}`, payload);
|
|
35
|
+
}
|
|
36
|
+
sendMedia(payload) {
|
|
37
|
+
return this.api.post(`/message/sendMedia/${this.instanceName}`, payload);
|
|
38
|
+
}
|
|
39
|
+
sendWhatsAppAudio(payload) {
|
|
40
|
+
return this.api.post(`/message/sendWhatsAppAudio/${this.instanceName}`, payload);
|
|
41
|
+
}
|
|
42
|
+
sendList(payload) {
|
|
43
|
+
return this.api.post(`/message/sendList/${this.instanceName}`, payload);
|
|
44
|
+
}
|
|
45
|
+
sendButtons(payload) {
|
|
46
|
+
return this.api.post(`/message/sendButtons/${this.instanceName}`, payload);
|
|
47
|
+
}
|
|
48
|
+
sendCarousel(payload) {
|
|
49
|
+
return this.api.post(`/message/sendCarousel/${this.instanceName}`, payload);
|
|
50
|
+
}
|
|
51
|
+
sendPoll(payload) {
|
|
52
|
+
return this.api.post(`/message/sendPoll/${this.instanceName}`, payload);
|
|
53
|
+
}
|
|
54
|
+
sendLocation(payload) {
|
|
55
|
+
return this.api.post(`/message/sendLocation/${this.instanceName}`, payload);
|
|
56
|
+
}
|
|
57
|
+
sendReaction(payload) {
|
|
58
|
+
return this.api.post(`/message/sendReaction/${this.instanceName}`, payload);
|
|
59
|
+
}
|
|
60
|
+
markMessagesAsRead(payload) {
|
|
61
|
+
return this.api.post(`/chat/markMessageAsRead/${this.instanceName}`, payload);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.SendWaveApiRepository = SendWaveApiRepository;
|