@gamastudio/sendwave-provider 0.0.2

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.
Files changed (44) hide show
  1. package/.claude/settings.local.json +9 -0
  2. package/.github/workflows/build.yml +31 -0
  3. package/README.md +374 -0
  4. package/build/constants/html/connect.d.ts +1 -0
  5. package/build/constants/html/connect.js +37 -0
  6. package/build/constants/html/error.d.ts +1 -0
  7. package/build/constants/html/error.js +42 -0
  8. package/build/constants/html/home.d.ts +1 -0
  9. package/build/constants/html/home.js +30 -0
  10. package/build/constants/svg/logo.d.ts +1 -0
  11. package/build/constants/svg/logo.js +4 -0
  12. package/build/constants/svg/wave-error.d.ts +1 -0
  13. package/build/constants/svg/wave-error.js +92 -0
  14. package/build/constants/svg/wave.d.ts +1 -0
  15. package/build/constants/svg/wave.js +92 -0
  16. package/build/core/interface/index.d.ts +3 -0
  17. package/build/core/interface/index.js +19 -0
  18. package/build/core/interface/parser.interface.d.ts +10 -0
  19. package/build/core/interface/parser.interface.js +2 -0
  20. package/build/core/interface/provider.interface.d.ts +16 -0
  21. package/build/core/interface/provider.interface.js +2 -0
  22. package/build/core/interface/types.d.ts +86 -0
  23. package/build/core/interface/types.js +2 -0
  24. package/build/index.d.ts +5 -0
  25. package/build/index.js +12 -0
  26. package/build/package.json +48 -0
  27. package/build/provider/core.d.ts +20 -0
  28. package/build/provider/core.js +112 -0
  29. package/build/provider/index.d.ts +1 -0
  30. package/build/provider/index.js +17 -0
  31. package/build/provider/provider.d.ts +85 -0
  32. package/build/provider/provider.js +375 -0
  33. package/build/provider/sender.d.ts +16 -0
  34. package/build/provider/sender.js +203 -0
  35. package/build/utils/detectorMedia.d.ts +24 -0
  36. package/build/utils/detectorMedia.js +92 -0
  37. package/build/utils/parserMsg.d.ts +2 -0
  38. package/build/utils/parserMsg.js +104 -0
  39. package/build/utils/queueFlow.d.ts +36 -0
  40. package/build/utils/queueFlow.js +82 -0
  41. package/package.json +48 -0
  42. package/public/assets/logo.png +0 -0
  43. package/queue.class.log +0 -0
  44. package/tsconfig.json +19 -0
@@ -0,0 +1,203 @@
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.SenderMessage = void 0;
7
+ const https_1 = require("https");
8
+ const axios_1 = __importDefault(require("axios"));
9
+ const detectorMedia_1 = require("../utils/detectorMedia");
10
+ class SenderMessage {
11
+ constructor(args) {
12
+ this.sendwaveApi = axios_1.default.create({
13
+ baseURL: args.url,
14
+ httpsAgent: new https_1.Agent({ rejectUnauthorized: false }),
15
+ headers: {
16
+ "Content-Type": "application/json",
17
+ apikey: args.apiKey,
18
+ },
19
+ });
20
+ this.globalVendorArgs = args;
21
+ }
22
+ async sendPresence(data) {
23
+ var _a, _b;
24
+ try {
25
+ return await ((_a = this.sendwaveApi) === null || _a === void 0 ? void 0 : _a.post(`/chat/sendPresence/${(_b = this.globalVendorArgs) === null || _b === void 0 ? void 0 : _b.name}`, {
26
+ number: data.from,
27
+ delay: data.delay || 2000,
28
+ presence: data.presence || "composing",
29
+ }));
30
+ }
31
+ catch (e) {
32
+ console.error(e.response.data.response.message);
33
+ }
34
+ }
35
+ async sendText(data) {
36
+ var _a, _b, _c;
37
+ try {
38
+ await this.sendPresence({
39
+ from: data.from,
40
+ presence: "composing",
41
+ delay: data.delay || 2000,
42
+ });
43
+ return await ((_a = this.sendwaveApi) === null || _a === void 0 ? void 0 : _a.post(`/message/sendText/${(_b = this.globalVendorArgs) === null || _b === void 0 ? void 0 : _b.name}`, {
44
+ number: data.from.split("@")[0],
45
+ text: data.text,
46
+ ...this.globalVendorArgs,
47
+ }));
48
+ }
49
+ catch (e) {
50
+ console.error((_c = e === null || e === void 0 ? void 0 : e.response) === null || _c === void 0 ? void 0 : _c.data);
51
+ }
52
+ }
53
+ async sendList(data) {
54
+ var _a, _b, _c, _d, _e;
55
+ try {
56
+ if (!(data === null || data === void 0 ? void 0 : data.from))
57
+ throw new Error("sendList: falta 'from'");
58
+ if (!(data === null || data === void 0 ? void 0 : data.list))
59
+ throw new Error("sendList: falta 'list'");
60
+ const { title, description = "", footerText = "", button, content = [], } = data.list;
61
+ if (!Array.isArray(content) || content.length === 0)
62
+ throw new Error("sendList: 'content' debe ser un array no vacío");
63
+ const isSimple = typeof content[0] === "string";
64
+ const sections = isSimple
65
+ ? [
66
+ {
67
+ title: "",
68
+ rows: content.map((t, i) => ({
69
+ rowId: `${i + 1}`,
70
+ title: t,
71
+ })),
72
+ },
73
+ ]
74
+ : content.map((sec) => ({
75
+ title: sec.title || "",
76
+ rows: (sec.rows || []).map((r, i) => ({
77
+ rowId: `${i + 1}`,
78
+ title: r.title || "",
79
+ ...(r.description && r.description.trim()
80
+ ? { description: r.description.trim() }
81
+ : {}),
82
+ })),
83
+ }));
84
+ return await ((_a = this.sendwaveApi) === null || _a === void 0 ? void 0 : _a.post(`/message/sendList/${(_b = this.globalVendorArgs) === null || _b === void 0 ? void 0 : _b.name}`, {
85
+ number: data.from.split("@")[0],
86
+ title,
87
+ description,
88
+ footerText,
89
+ buttonText: button,
90
+ sections,
91
+ ...this.globalVendorArgs,
92
+ }));
93
+ }
94
+ catch (err) {
95
+ console.error("[sendList Error]", ((_e = (_d = (_c = err.response) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.response) === null || _e === void 0 ? void 0 : _e.message) || err.message);
96
+ }
97
+ }
98
+ async sendMedia(data) {
99
+ var _a, _b;
100
+ try {
101
+ const { media, mimeType, mediaType } = await detectorMedia_1.detectorMedia.processMedia(data.url);
102
+ return await ((_a = this.sendwaveApi) === null || _a === void 0 ? void 0 : _a.post(`/message/sendMedia/${(_b = this.globalVendorArgs) === null || _b === void 0 ? void 0 : _b.name}`, {
103
+ number: data.from.split("@")[0],
104
+ caption: data.text,
105
+ mediatype: mediaType,
106
+ mimetype: mimeType,
107
+ media: media,
108
+ fileName: data.fileName || crypto.randomUUID(),
109
+ ...this.globalVendorArgs,
110
+ }));
111
+ }
112
+ catch (e) {
113
+ console.error(e.response.data.response.message);
114
+ }
115
+ }
116
+ async sendFile(data) {
117
+ try {
118
+ return await this.sendMedia({
119
+ ...data,
120
+ fileName: data.fileName || crypto.randomUUID(),
121
+ mediaType: "document",
122
+ });
123
+ }
124
+ catch (e) {
125
+ console.error(e.response.data.response.message);
126
+ }
127
+ }
128
+ async sendImage(data) {
129
+ try {
130
+ return await this.sendMedia({
131
+ ...data,
132
+ mediaType: "image",
133
+ });
134
+ }
135
+ catch (e) {
136
+ console.error(e.response.data.response.message);
137
+ }
138
+ }
139
+ async sendAudio(data) {
140
+ try {
141
+ return await this.sendMedia({
142
+ ...data,
143
+ mediaType: "audio",
144
+ });
145
+ }
146
+ catch (e) {
147
+ console.error(e.response.data.response.message);
148
+ }
149
+ }
150
+ async sendVideo(data) {
151
+ try {
152
+ return await this.sendMedia({
153
+ ...data,
154
+ mediaType: "video",
155
+ });
156
+ }
157
+ catch (e) {
158
+ console.error(e.response.data.response.message);
159
+ }
160
+ }
161
+ async sendVoice(data) {
162
+ var _a, _b;
163
+ try {
164
+ const { media } = await detectorMedia_1.detectorMedia.processMedia(data.url);
165
+ await this.sendPresence({
166
+ from: data.from,
167
+ presence: "recording",
168
+ delay: data.delay || 2000,
169
+ });
170
+ return await ((_a = this.sendwaveApi) === null || _a === void 0 ? void 0 : _a.post(`/message/sendWhatsAppAudio/${(_b = this.globalVendorArgs) === null || _b === void 0 ? void 0 : _b.name}`, {
171
+ number: data.from,
172
+ audio: media,
173
+ ...this.globalVendorArgs,
174
+ }));
175
+ }
176
+ catch (e) {
177
+ console.error(e.response.data.response.message);
178
+ }
179
+ }
180
+ async sendButton(data) {
181
+ var _a, _b;
182
+ try {
183
+ return await ((_a = this.sendwaveApi) === null || _a === void 0 ? void 0 : _a.post(`/message/sendButtons/${(_b = this.globalVendorArgs) === null || _b === void 0 ? void 0 : _b.name}`, {
184
+ number: data.from.split("@")[0],
185
+ title: data.title,
186
+ body: data.body,
187
+ description: data.description,
188
+ footer: data.footer,
189
+ buttons: data.buttons.map((button, index) => ({
190
+ type: button.type,
191
+ title: button.text,
192
+ displayText: button.text,
193
+ id: `${index + 1}`,
194
+ })),
195
+ ...this.globalVendorArgs,
196
+ }));
197
+ }
198
+ catch (error) {
199
+ console.error(error.response.data.response.message);
200
+ }
201
+ }
202
+ }
203
+ exports.SenderMessage = SenderMessage;
@@ -0,0 +1,24 @@
1
+ interface DetectorMediaProps {
2
+ media?: string;
3
+ mimeType?: string;
4
+ mediaType?: string;
5
+ fileName?: string;
6
+ }
7
+ export declare class DetectorMedia {
8
+ static instance: DetectorMedia;
9
+ static getInstance(): DetectorMedia;
10
+ isRemoteUrl(url: string): boolean;
11
+ convertPathToBase64(filePath: string): Promise<DetectorMediaProps>;
12
+ getMimeTypeFromUrl(url: string): Promise<string | null>;
13
+ extractFileNameFromUrl(url: string): Promise<string>;
14
+ /**
15
+ * Método unificado que acepta path o url y devuelve:
16
+ * - media (base64 si es path, url si es remota)
17
+ * - mimeType
18
+ * - fileName
19
+ */
20
+ processMedia(input: string): Promise<DetectorMediaProps>;
21
+ mapMimeToCategory(mimeType: string): "image" | "video" | "audio" | "document" | "unknown";
22
+ }
23
+ export declare const detectorMedia: DetectorMedia;
24
+ export {};
@@ -0,0 +1,92 @@
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.detectorMedia = exports.DetectorMedia = 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
+ class DetectorMedia {
12
+ static getInstance() {
13
+ if (!DetectorMedia.instance) {
14
+ DetectorMedia.instance = new DetectorMedia();
15
+ }
16
+ return DetectorMedia.instance;
17
+ }
18
+ isRemoteUrl(url) {
19
+ try {
20
+ const u = new URL(url);
21
+ return u.protocol === "http:" || u.protocol === "https:";
22
+ }
23
+ catch {
24
+ return false;
25
+ }
26
+ }
27
+ async convertPathToBase64(filePath) {
28
+ const fileBuffer = await promises_1.default.readFile(filePath);
29
+ const mediaType = this.mapMimeToCategory(mime_types_1.default.lookup(filePath).toString());
30
+ if (!mediaType)
31
+ throw new Error("No se pudo determinar el tipo MIME del archivo");
32
+ const base64Data = fileBuffer.toString("base64");
33
+ const media = base64Data;
34
+ const fileName = path_1.default.basename(filePath);
35
+ return {
36
+ media,
37
+ mediaType,
38
+ fileName,
39
+ mimeType: mime_types_1.default.lookup(filePath).toString(),
40
+ };
41
+ }
42
+ async getMimeTypeFromUrl(url) {
43
+ try {
44
+ const res = await axios_1.default.head(url);
45
+ const mediaType = this.mapMimeToCategory(res.headers["content-type"]);
46
+ return mediaType || null;
47
+ }
48
+ catch {
49
+ return null;
50
+ }
51
+ }
52
+ async extractFileNameFromUrl(url) {
53
+ const urlObj = new URL(url);
54
+ const pathname = urlObj.pathname;
55
+ const name = pathname.split("/").pop();
56
+ return name || `file_${Date.now()}`;
57
+ }
58
+ /**
59
+ * Método unificado que acepta path o url y devuelve:
60
+ * - media (base64 si es path, url si es remota)
61
+ * - mimeType
62
+ * - fileName
63
+ */
64
+ async processMedia(input) {
65
+ if (this.isRemoteUrl(input)) {
66
+ const mediaType = await this.getMimeTypeFromUrl(input);
67
+ if (!mediaType)
68
+ throw new Error("No se pudo determinar el tipo MIME de la URL remota");
69
+ const fileName = await this.extractFileNameFromUrl(input);
70
+ return {
71
+ media: input,
72
+ mimeType: mime_types_1.default.lookup(input).toString(),
73
+ fileName,
74
+ mediaType,
75
+ };
76
+ }
77
+ return this.convertPathToBase64(input);
78
+ }
79
+ mapMimeToCategory(mimeType) {
80
+ if (mimeType.startsWith("image/"))
81
+ return "image";
82
+ if (mimeType.startsWith("video/"))
83
+ return "video";
84
+ if (mimeType.startsWith("audio/"))
85
+ return "audio";
86
+ if (mimeType.startsWith("application/") || mimeType.startsWith("text/"))
87
+ return "document";
88
+ return "unknown";
89
+ }
90
+ }
91
+ exports.DetectorMedia = DetectorMedia;
92
+ exports.detectorMedia = DetectorMedia.getInstance();
@@ -0,0 +1,2 @@
1
+ import { ParsedMessage } from "../core/interface/parser.interface";
2
+ export declare function parseIncomingMsg(payload: any): ParsedMessage | null;
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseIncomingMsg = parseIncomingMsg;
4
+ const bot_1 = require("@builderbot/bot"); // Asegúrate de importar utils correctamente
5
+ function parseIncomingMsg(payload) {
6
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
7
+ try {
8
+ const msg = payload.data;
9
+ if (msg.messageType === "reactionMessage")
10
+ return null;
11
+ if (!msg) {
12
+ return null;
13
+ }
14
+ // if (msg.key.fromMe) return null
15
+ const fromMe = msg.key.fromMe;
16
+ const from = (_a = msg.key) === null || _a === void 0 ? void 0 : _a.remoteJid.split("@")[0];
17
+ const to = payload.instance || "";
18
+ const name = msg.pushName;
19
+ const messageContent = msg.message || {};
20
+ const messageType = msg.messageType || Object.keys(messageContent)[0];
21
+ let body = "";
22
+ let type = messageType;
23
+ let media;
24
+ let caption;
25
+ // 🎯 Primero detección especial de eventos por tipo de mensaje
26
+ if (messageContent.locationMessage) {
27
+ body = bot_1.utils.generateRefProvider("_event_location_");
28
+ type = "locationMessage";
29
+ }
30
+ else if (messageContent.orderMessage) {
31
+ body = bot_1.utils.generateRefProvider("_event_order_");
32
+ type = "orderMessage";
33
+ }
34
+ else if (messageContent.videoMessage) {
35
+ body = bot_1.utils.generateRefProvider("_event_media_");
36
+ type = "videoMessage";
37
+ media = (_b = messageContent.videoMessage) === null || _b === void 0 ? void 0 : _b.url;
38
+ caption = ((_c = messageContent.videoMessage) === null || _c === void 0 ? void 0 : _c.caption) || "";
39
+ }
40
+ else if (messageContent.stickerMessage) {
41
+ body = bot_1.utils.generateRefProvider("_event_media_");
42
+ type = "stickerMessage";
43
+ media = (_d = messageContent.stickerMessage) === null || _d === void 0 ? void 0 : _d.url;
44
+ }
45
+ else if (messageContent.imageMessage) {
46
+ body = bot_1.utils.generateRefProvider("_event_media_");
47
+ type = "imageMessage";
48
+ media = (_e = messageContent.imageMessage) === null || _e === void 0 ? void 0 : _e.url;
49
+ caption = ((_f = messageContent.imageMessage) === null || _f === void 0 ? void 0 : _f.caption) || "";
50
+ }
51
+ else if (messageContent.documentMessage ||
52
+ messageContent.documentWithCaptionMessage) {
53
+ body = bot_1.utils.generateRefProvider("_event_document_");
54
+ type = "documentMessage";
55
+ media =
56
+ ((_g = messageContent.documentMessage) === null || _g === void 0 ? void 0 : _g.url) ||
57
+ ((_h = messageContent.documentWithCaptionMessage) === null || _h === void 0 ? void 0 : _h.url);
58
+ caption =
59
+ ((_j = messageContent.documentMessage) === null || _j === void 0 ? void 0 : _j.caption) ||
60
+ ((_k = messageContent.documentWithCaptionMessage) === null || _k === void 0 ? void 0 : _k.caption) ||
61
+ "";
62
+ }
63
+ else if (messageContent.audioMessage) {
64
+ body = bot_1.utils.generateRefProvider("_event_voice_note_");
65
+ type = "audioMessage";
66
+ media = (_l = messageContent.audioMessage) === null || _l === void 0 ? void 0 : _l.url;
67
+ }
68
+ else {
69
+ // 🎯 Si no es media especial, hacer parsing normal por tipo
70
+ switch (type) {
71
+ case "conversation":
72
+ body = messageContent.conversation || "";
73
+ break;
74
+ case "buttonsResponseMessage":
75
+ body = ((_m = messageContent.buttonsResponseMessage) === null || _m === void 0 ? void 0 : _m.selectedButtonId) || "";
76
+ break;
77
+ case "listResponseMessage":
78
+ body = ((_o = messageContent.listResponseMessage) === null || _o === void 0 ? void 0 : _o.title) || "";
79
+ break;
80
+ case "listMessage":
81
+ body =
82
+ `${(_p = messageContent.listMessage) === null || _p === void 0 ? void 0 : _p.title}${((_q = messageContent.listMessage) === null || _q === void 0 ? void 0 : _q.title) ? "\n" : ""}${(_r = messageContent.listMessage) === null || _r === void 0 ? void 0 : _r.description}` || "";
83
+ break;
84
+ default:
85
+ body = "Tipo de mensaje no soportado aún";
86
+ }
87
+ }
88
+ return {
89
+ fromMe,
90
+ from,
91
+ to,
92
+ name,
93
+ body,
94
+ type,
95
+ media,
96
+ caption,
97
+ // originalPayload: payload,
98
+ };
99
+ }
100
+ catch (error) {
101
+ console.error("[parseIncomingMsg] Error:", error);
102
+ return null;
103
+ }
104
+ }
@@ -0,0 +1,36 @@
1
+ import { EventEmitter } from "events";
2
+ import { SendWaveProvider } from "../provider/provider";
3
+ interface QueueFlowConfig {
4
+ warningTimeout?: number;
5
+ endTimeout?: number;
6
+ warningMessage?: string;
7
+ }
8
+ declare class QueueFlow extends EventEmitter {
9
+ static instance: QueueFlow;
10
+ private userTimeouts;
11
+ ignoredUsers: Set<string>;
12
+ private config;
13
+ constructor(config?: QueueFlowConfig);
14
+ static getInstance(config?: QueueFlowConfig): QueueFlow;
15
+ updateConfig(config: Partial<QueueFlowConfig>): void;
16
+ clearUserTimeout(from: string): void;
17
+ resetUserTimeout: ({ provider, from, name, }: {
18
+ from: string;
19
+ provider: SendWaveProvider;
20
+ name?: string;
21
+ }) => {
22
+ isActive: boolean;
23
+ from: string;
24
+ name: string | undefined;
25
+ };
26
+ forceClearUser(from: string): void;
27
+ removeUserListeners(from: string): void;
28
+ getUserStats(): {
29
+ activeTimeouts: number;
30
+ ignoredUsers: number;
31
+ config: Required<QueueFlowConfig>;
32
+ };
33
+ isUserIgnored(from: string): boolean;
34
+ }
35
+ export declare const queueFlow: QueueFlow;
36
+ export { QueueFlow, type QueueFlowConfig };
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.QueueFlow = exports.queueFlow = void 0;
4
+ const events_1 = require("events");
5
+ class QueueFlow extends events_1.EventEmitter {
6
+ constructor(config = {}) {
7
+ super();
8
+ this.userTimeouts = new Map();
9
+ this.ignoredUsers = new Set();
10
+ this.resetUserTimeout = ({ provider, from, name, }) => {
11
+ this.clearUserTimeout(from);
12
+ let isActive = true;
13
+ // 🔥 Timeout de advertencia (configurable)
14
+ const warningTimeout = setTimeout(async () => {
15
+ await provider.sendText({
16
+ from,
17
+ text: this.config.warningMessage,
18
+ });
19
+ this.emit(`userInactive-${from}`, { from, name, isActive: true });
20
+ // 🔥 Timeout para finalizar flujo (configurable después)
21
+ const endTimeout = setTimeout(async () => {
22
+ // 1. Marcar como ignorado INMEDIATAMENTE
23
+ this.ignoredUsers.add(from);
24
+ // 2. Esperar un momento para que se registre el ignore
25
+ await new Promise(resolve => setTimeout(resolve, 100));
26
+ // 3. Limpiar listeners
27
+ this.removeUserListeners(from);
28
+ // 4. Enviar flow para que ejecute endFlow correctamente
29
+ provider.sendFlow({ event: "END_FLOW", from, name: name || "" });
30
+ // 5. Emitir evento
31
+ this.emit(`userInactive-${from}`, { from, name, isActive: false });
32
+ }, this.config.endTimeout);
33
+ this.userTimeouts.set(from, endTimeout);
34
+ }, this.config.warningTimeout);
35
+ this.userTimeouts.set(from, warningTimeout);
36
+ return { isActive, from, name };
37
+ };
38
+ this.config = {
39
+ warningTimeout: config.warningTimeout || 30 * 60 * 1000, // 30 minutes
40
+ endTimeout: config.endTimeout || 2 * 60 * 1000, // 2 minutes
41
+ warningMessage: config.warningMessage || "⏳ Parece que has estado inactivo. ¿Sigues ahí?",
42
+ };
43
+ }
44
+ static getInstance(config) {
45
+ if (!this.instance) {
46
+ this.instance = new QueueFlow(config);
47
+ }
48
+ return this.instance;
49
+ }
50
+ updateConfig(config) {
51
+ this.config = { ...this.config, ...config };
52
+ }
53
+ clearUserTimeout(from) {
54
+ if (this.userTimeouts.has(from)) {
55
+ clearTimeout(this.userTimeouts.get(from));
56
+ this.userTimeouts.delete(from);
57
+ }
58
+ }
59
+ forceClearUser(from) {
60
+ this.clearUserTimeout(from);
61
+ this.removeUserListeners(from);
62
+ }
63
+ removeUserListeners(from) {
64
+ // 🔥 Eliminar todos los listeners de este usuario
65
+ this.removeAllListeners(`userInactive-${from}`);
66
+ this.removeAllListeners(`forceClearTimeout-${from}`);
67
+ this.userTimeouts.delete(from);
68
+ this.ignoredUsers.delete(from);
69
+ }
70
+ getUserStats() {
71
+ return {
72
+ activeTimeouts: this.userTimeouts.size,
73
+ ignoredUsers: this.ignoredUsers.size,
74
+ config: this.config,
75
+ };
76
+ }
77
+ isUserIgnored(from) {
78
+ return this.ignoredUsers.has(from);
79
+ }
80
+ }
81
+ exports.QueueFlow = QueueFlow;
82
+ exports.queueFlow = QueueFlow.getInstance();
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@gamastudio/sendwave-provider",
3
+ "version": "0.0.2",
4
+ "description": "Librería para interactuar con Sendwave usando configuración dinámica.",
5
+ "main": "build/index.js",
6
+ "types": "build/index.d.ts",
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc && tsc-alias && copyfiles package.json build",
12
+ "test": "ts-node -r tsconfig-paths/register test/test.ts",
13
+ "dev": "ts-node-dev --respawn --transpile-only -r tsconfig-paths/register test/test.ts",
14
+ "prepublishOnly": "npm run build"
15
+ },
16
+ "keywords": [
17
+ "Sendwave",
18
+ "Provider",
19
+ "Gamastudio",
20
+ "Bot"
21
+ ],
22
+ "author": "Ameth Galarcio <amethgm@gmail.com>",
23
+ "license": "ISC",
24
+ "dependencies": {
25
+ "@builderbot/bot": "^1.3.1",
26
+ "@gamastudio/colorslog": "^0.1.6",
27
+ "@types/mime-types": "^2.1.4",
28
+ "axios": "^1.11.0",
29
+ "body-parser": "^2.2.0",
30
+ "cors": "^2.8.5",
31
+ "file-type": "^20.5.0",
32
+ "mime-types": "^3.0.1",
33
+ "queue-promise": "^2.2.1",
34
+ "sirv": "^3.0.1"
35
+ },
36
+ "devDependencies": {
37
+ "@types/axios": "^0.14.4",
38
+ "@types/body-parser": "^1.19.6",
39
+ "@types/cors": "^2.8.19",
40
+ "@types/node": "^22.18.0",
41
+ "copyfiles": "^2.4.1",
42
+ "ts-node": "^10.9.2",
43
+ "ts-node-dev": "^2.0.0",
44
+ "tsc-alias": "^1.8.16",
45
+ "tsconfig-paths": "^4.2.0",
46
+ "typescript": "^5.9.2"
47
+ }
48
+ }
Binary file
File without changes
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "baseUrl": "./src",
4
+ "paths": {
5
+ "@provider/*": ["provider/*"],
6
+ "@interface/*": ["interface/*"],
7
+ "@utils/*": ["utils/*"],
8
+ "@core/*": ["core/*"]
9
+ },
10
+ "outDir": "build",
11
+ "module": "CommonJS",
12
+ "target": "ES2019",
13
+ "declaration": true,
14
+ "esModuleInterop": true,
15
+ "strict": true,
16
+ "skipLibCheck": true
17
+ },
18
+ "include": ["src/**/*"]
19
+ }