@kaikybrofc/omnizap-system 2.2.9 → 2.3.0
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/README.md +20 -18
- package/app/config/adminIdentity.js +1 -3
- package/app/connection/socketController.js +10 -20
- package/app/controllers/messageController.js +7 -28
- package/app/modules/aiModule/catCommand.js +29 -192
- package/app/modules/broadcastModule/noticeCommand.js +28 -97
- package/app/modules/gameModule/diceCommand.js +6 -32
- package/app/modules/playModule/playCommand.js +57 -258
- package/app/modules/quoteModule/quoteCommand.js +2 -4
- package/app/modules/rpgPokemonModule/rpgPokemonRepository.js +1 -13
- package/app/modules/statsModule/noMessageCommand.js +16 -84
- package/app/modules/statsModule/rankingCommand.js +5 -25
- package/app/modules/statsModule/rankingCommon.js +1 -9
- package/app/modules/stickerModule/convertToWebp.js +4 -27
- package/app/modules/stickerModule/stickerCommand.js +13 -24
- package/app/modules/stickerModule/stickerTextCommand.js +13 -25
- package/app/modules/stickerPackModule/autoPackCollectorService.js +16 -7
- package/app/modules/stickerPackModule/domainEventOutboxRepository.js +20 -36
- package/app/modules/stickerPackModule/domainEvents.js +2 -11
- package/app/modules/stickerPackModule/semanticReclassificationEngine.js +13 -50
- package/app/modules/stickerPackModule/semanticReclassificationEngine.test.js +2 -15
- package/app/modules/stickerPackModule/semanticThemeClusterService.js +14 -41
- package/app/modules/stickerPackModule/stickerAssetClassificationRepository.js +25 -95
- package/app/modules/stickerPackModule/stickerAssetRepository.js +12 -31
- package/app/modules/stickerPackModule/stickerAssetReprocessQueueRepository.js +13 -18
- package/app/modules/stickerPackModule/stickerAutoPackByTagsRuntime.js +284 -709
- package/app/modules/stickerPackModule/stickerClassificationBackgroundRuntime.js +27 -106
- package/app/modules/stickerPackModule/stickerClassificationService.js +46 -77
- package/app/modules/stickerPackModule/stickerDedicatedTaskWorkerRuntime.js +13 -53
- package/app/modules/stickerPackModule/stickerDomainEventBus.js +10 -16
- package/app/modules/stickerPackModule/stickerDomainEventConsumerRuntime.js +13 -34
- package/app/modules/stickerPackModule/stickerMarketplaceDriftService.js +1 -4
- package/app/modules/stickerPackModule/stickerObjectStorageService.js +26 -26
- package/app/modules/stickerPackModule/stickerPackCommandHandlers.js +32 -187
- package/app/modules/stickerPackModule/stickerPackInteractionEventRepository.js +6 -15
- package/app/modules/stickerPackModule/stickerPackItemRepository.js +6 -32
- package/app/modules/stickerPackModule/stickerPackMarketplaceService.js +12 -36
- package/app/modules/stickerPackModule/stickerPackMessageService.js +12 -40
- package/app/modules/stickerPackModule/stickerPackRepository.js +23 -66
- package/app/modules/stickerPackModule/stickerPackScoreSnapshotRepository.js +9 -21
- package/app/modules/stickerPackModule/stickerPackScoreSnapshotRuntime.js +10 -40
- package/app/modules/stickerPackModule/stickerPackService.js +50 -115
- package/app/modules/stickerPackModule/stickerPackServiceRuntime.js +2 -21
- package/app/modules/stickerPackModule/stickerPackUtils.js +13 -3
- package/app/modules/stickerPackModule/stickerStorageService.js +16 -65
- package/app/modules/stickerPackModule/stickerWorkerPipelineRuntime.js +4 -22
- package/app/modules/stickerPackModule/stickerWorkerTaskQueueRepository.js +14 -29
- package/app/modules/systemMetricsModule/pingCommand.js +9 -39
- package/app/modules/tiktokModule/tiktokCommand.js +17 -109
- package/app/modules/userModule/userCommand.js +2 -88
- package/app/observability/metrics.js +5 -16
- package/app/services/captchaService.js +1 -6
- package/app/services/dbWriteQueue.js +3 -18
- package/app/services/featureFlagService.js +2 -8
- package/app/services/newsBroadcastService.js +0 -1
- package/app/services/queueUtils.js +2 -4
- package/app/services/whatsappLoginLinkService.js +7 -9
- package/app/store/premiumUserStore.js +1 -2
- package/app/utils/antiLink/antiLinkModule.js +3 -233
- package/app/utils/logger/loggerModule.js +9 -34
- package/app/utils/systemMetrics/systemMetricsModule.js +1 -4
- package/database/init.js +1 -8
- package/docker-compose.yml +27 -27
- package/docs/seo/omnizap-seo-playbook-br-2026-02-28.md +220 -0
- package/docs/seo/satellite-page-template.md +91 -0
- package/docs/seo/satellite-pages-phase1.json +349 -0
- package/eslint.config.js +2 -15
- package/index.js +8 -36
- package/ml/clip_classifier/README.md +4 -6
- package/observability/alert-rules.yml +12 -12
- package/observability/grafana/provisioning/dashboards/dashboards.yml +1 -1
- package/package.json +8 -3
- package/public/api-docs/index.html +224 -141
- package/public/bot-whatsapp-para-grupo/index.html +306 -0
- package/public/bot-whatsapp-sem-programar/index.html +306 -0
- package/public/comandos/index.html +428 -0
- package/public/como-automatizar-avisos-no-whatsapp/index.html +306 -0
- package/public/como-criar-comandos-whatsapp/index.html +306 -0
- package/public/como-evitar-spam-no-whatsapp/index.html +306 -0
- package/public/como-moderar-grupo-whatsapp/index.html +306 -0
- package/public/como-organizar-comunidade-whatsapp/index.html +306 -0
- package/public/css/github-project-panel.css +20 -15
- package/public/css/stickers-admin.css +55 -39
- package/public/css/styles.css +37 -29
- package/public/index.html +1060 -1417
- package/public/js/apps/apiDocsApp.js +36 -153
- package/public/js/apps/createPackApp.js +69 -332
- package/public/js/apps/homeApp.js +201 -434
- package/public/js/apps/loginApp.js +3 -12
- package/public/js/apps/stickersAdminApp.js +190 -181
- package/public/js/apps/stickersApp.js +507 -1366
- package/public/js/catalog.js +11 -74
- package/public/js/github-panel/components/ErrorState.js +1 -8
- package/public/js/github-panel/components/GithubProjectPanel.js +2 -9
- package/public/js/github-panel/components/SkeletonPanel.js +1 -11
- package/public/js/github-panel/components/StatCard.js +1 -7
- package/public/js/github-panel/vendor/react.js +1 -9
- package/public/js/runtime/react-runtime.js +1 -9
- package/public/licenca/index.html +104 -86
- package/public/login/index.html +315 -321
- package/public/melhor-bot-whatsapp-para-grupos/index.html +306 -0
- package/public/sitemap.xml +45 -0
- package/public/stickers/admin/index.html +14 -19
- package/public/stickers/create/index.html +39 -43
- package/public/stickers/index.html +97 -41
- package/public/termos-de-uso/index.html +142 -115
- package/public/user/index.html +347 -346
- package/scripts/cache-bust.mjs +5 -24
- package/scripts/generate-seo-satellite-pages.mjs +431 -0
- package/scripts/run-prettier-all.mjs +25 -0
- package/scripts/sticker-catalog-loadtest.mjs +13 -11
- package/scripts/sticker-worker-task.mjs +1 -4
- package/scripts/sync-readme-snapshot.mjs +3 -2
- package/server/controllers/stickerCatalogController.js +407 -704
- package/server/http/httpServer.js +2 -10
- package/server/routes/stickerCatalog/catalogHandlers/catalogAdminHttp.js +1 -8
- package/server/routes/stickerCatalog/catalogHandlers/catalogAuthHttp.js +1 -9
- package/server/routes/stickerCatalog/catalogHandlers/catalogPublicHttp.js +10 -11
- package/server/routes/stickerCatalog/catalogHandlers/catalogUploadHttp.js +1 -10
- package/server/routes/stickerCatalog/catalogRouter.js +11 -13
- package/kaikybrofc-omnizap-system-2.2.9.tgz +0 -0
package/README.md
CHANGED
|
@@ -51,29 +51,31 @@ Conteúdo incluído no snapshot:
|
|
|
51
51
|
Atualização em cache: **30 minutos** por padrão (`README_SUMMARY_CACHE_SECONDS=1800`).
|
|
52
52
|
|
|
53
53
|
<!-- README_SNAPSHOT:START -->
|
|
54
|
+
|
|
54
55
|
### Snapshot do Sistema
|
|
55
56
|
|
|
56
|
-
> Atualizado em `2026-02-
|
|
57
|
+
> Atualizado em `2026-02-28T21:19:25.225Z` | cache `1800s`
|
|
57
58
|
|
|
58
|
-
| Métrica
|
|
59
|
-
|
|
|
60
|
-
| Usuários (lid_map)
|
|
61
|
-
| Grupos
|
|
62
|
-
| Packs
|
|
63
|
-
| Stickers
|
|
64
|
-
| Mensagens registradas |
|
|
59
|
+
| Métrica | Valor |
|
|
60
|
+
| --------------------- | ------: |
|
|
61
|
+
| Usuários (lid_map) | 5.515 |
|
|
62
|
+
| Grupos | 116 |
|
|
63
|
+
| Packs | 301 |
|
|
64
|
+
| Stickers | 7.169 |
|
|
65
|
+
| Mensagens registradas | 444.374 |
|
|
65
66
|
|
|
66
67
|
#### Tipos de mensagem mais usados (amostra: 25.000)
|
|
67
|
-
|
|
68
|
-
|
|
|
69
|
-
|
|
|
70
|
-
| `
|
|
71
|
-
| `
|
|
72
|
-
| `
|
|
73
|
-
| `
|
|
74
|
-
| `
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
68
|
+
|
|
69
|
+
| Tipo | Total |
|
|
70
|
+
| ----------- | -----: |
|
|
71
|
+
| `texto` | 16.084 |
|
|
72
|
+
| `figurinha` | 4.777 |
|
|
73
|
+
| `reacao` | 1.546 |
|
|
74
|
+
| `imagem` | 1.339 |
|
|
75
|
+
| `outros` | 849 |
|
|
76
|
+
| `video` | 215 |
|
|
77
|
+
| `audio` | 184 |
|
|
78
|
+
| `documento` | 6 |
|
|
77
79
|
|
|
78
80
|
<details><summary>Comandos disponíveis (62)</summary>
|
|
79
81
|
|
|
@@ -69,9 +69,7 @@ export const isAdminSenderAsync = async (senderIdentity) => {
|
|
|
69
69
|
const normalizedCachedSender = normalizeJid(cachedSender || '');
|
|
70
70
|
const resolvedSender = await resolveUserId(senderInfo).catch(() => null);
|
|
71
71
|
const normalizedResolvedSender = normalizeJid(resolvedSender || '');
|
|
72
|
-
const senderCandidates = new Set(
|
|
73
|
-
[normalizedSender, normalizedCachedSender, normalizedResolvedSender].filter(Boolean),
|
|
74
|
-
);
|
|
72
|
+
const senderCandidates = new Set([normalizedSender, normalizedCachedSender, normalizedResolvedSender].filter(Boolean));
|
|
75
73
|
if (!senderCandidates.size) return false;
|
|
76
74
|
|
|
77
75
|
const adminJid = (await resolveAdminJid()) || getAdminJid();
|
|
@@ -42,16 +42,14 @@ const parseEnvInt = (value, fallback, min, max) => {
|
|
|
42
42
|
return Math.max(min, Math.min(max, Math.floor(parsed)));
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
const IS_PRODUCTION =
|
|
45
|
+
const IS_PRODUCTION =
|
|
46
|
+
String(process.env.NODE_ENV || '')
|
|
47
|
+
.trim()
|
|
48
|
+
.toLowerCase() === 'production';
|
|
46
49
|
const MSG_RETRY_CACHE_TTL_SECONDS = parseEnvInt(process.env.BAILEYS_MSG_RETRY_CACHE_TTL_SECONDS, 600, 60, 24 * 60 * 60);
|
|
47
50
|
const MSG_RETRY_CACHE_CHECKPERIOD_SECONDS = parseEnvInt(process.env.BAILEYS_MSG_RETRY_CACHE_CHECKPERIOD_SECONDS, 120, 30, 3600);
|
|
48
51
|
const BAILEYS_EVENT_LOG_ENABLED = parseEnvBool(process.env.BAILEYS_EVENT_LOG_ENABLED, !IS_PRODUCTION);
|
|
49
|
-
const BAILEYS_RECONNECT_ATTEMPT_RESET_MS = parseEnvInt(
|
|
50
|
-
process.env.BAILEYS_RECONNECT_ATTEMPT_RESET_MS,
|
|
51
|
-
10 * 60 * 1000,
|
|
52
|
-
60 * 1000,
|
|
53
|
-
24 * 60 * 60 * 1000,
|
|
54
|
-
);
|
|
52
|
+
const BAILEYS_RECONNECT_ATTEMPT_RESET_MS = parseEnvInt(process.env.BAILEYS_RECONNECT_ATTEMPT_RESET_MS, 10 * 60 * 1000, 60 * 1000, 24 * 60 * 60 * 1000);
|
|
55
53
|
const GROUP_SYNC_ON_CONNECT = parseEnvBool(process.env.GROUP_SYNC_ON_CONNECT, true);
|
|
56
54
|
const GROUP_SYNC_TIMEOUT_MS = parseEnvInt(process.env.GROUP_SYNC_TIMEOUT_MS, 30 * 1000, 5 * 1000, 120 * 1000);
|
|
57
55
|
const GROUP_SYNC_MAX_GROUPS = parseEnvInt(process.env.GROUP_SYNC_MAX_GROUPS, 0, 0, 10_000);
|
|
@@ -193,9 +191,7 @@ const shouldLogBaileysEvent = (eventName) => {
|
|
|
193
191
|
};
|
|
194
192
|
|
|
195
193
|
const registerBaileysEventLoggers = (sock) => {
|
|
196
|
-
const eventsToLog = BAILEYS_EVENT_NAMES.filter(
|
|
197
|
-
(eventName) => !BAILEYS_EVENTS_WITH_INTERNAL_LOG.has(eventName) && shouldLogBaileysEvent(eventName),
|
|
198
|
-
);
|
|
194
|
+
const eventsToLog = BAILEYS_EVENT_NAMES.filter((eventName) => !BAILEYS_EVENTS_WITH_INTERNAL_LOG.has(eventName) && shouldLogBaileysEvent(eventName));
|
|
199
195
|
|
|
200
196
|
for (const eventName of eventsToLog) {
|
|
201
197
|
sock.ev.on(eventName, (payload) => {
|
|
@@ -388,16 +384,9 @@ const syncGroupsOnConnectionOpen = async (sock) => {
|
|
|
388
384
|
return;
|
|
389
385
|
}
|
|
390
386
|
|
|
391
|
-
const allGroups = await withTimeout(
|
|
392
|
-
sock.groupFetchAllParticipating(),
|
|
393
|
-
GROUP_SYNC_TIMEOUT_MS,
|
|
394
|
-
`groups_sync_timeout_${GROUP_SYNC_TIMEOUT_MS}ms`,
|
|
395
|
-
);
|
|
387
|
+
const allGroups = await withTimeout(sock.groupFetchAllParticipating(), GROUP_SYNC_TIMEOUT_MS, `groups_sync_timeout_${GROUP_SYNC_TIMEOUT_MS}ms`);
|
|
396
388
|
const allGroupEntries = Object.values(allGroups || {});
|
|
397
|
-
const selectedGroups =
|
|
398
|
-
GROUP_SYNC_MAX_GROUPS > 0
|
|
399
|
-
? allGroupEntries.slice(0, GROUP_SYNC_MAX_GROUPS)
|
|
400
|
-
: allGroupEntries;
|
|
389
|
+
const selectedGroups = GROUP_SYNC_MAX_GROUPS > 0 ? allGroupEntries.slice(0, GROUP_SYNC_MAX_GROUPS) : allGroupEntries;
|
|
401
390
|
|
|
402
391
|
let syncedCount = 0;
|
|
403
392
|
let failedCount = 0;
|
|
@@ -408,7 +397,8 @@ const syncGroupsOnConnectionOpen = async (sock) => {
|
|
|
408
397
|
batch.map((group) =>
|
|
409
398
|
upsertGroupMetadata(group.id, buildGroupMetadataFromGroup(group), {
|
|
410
399
|
mergeExisting: false,
|
|
411
|
-
})
|
|
400
|
+
}),
|
|
401
|
+
),
|
|
412
402
|
);
|
|
413
403
|
for (const result of results) {
|
|
414
404
|
if (result.status === 'fulfilled') syncedCount += 1;
|
|
@@ -30,9 +30,10 @@ import { buildWhatsAppGoogleLoginUrl } from '../services/whatsappLoginLinkServic
|
|
|
30
30
|
|
|
31
31
|
const DEFAULT_COMMAND_PREFIX = process.env.COMMAND_PREFIX || '/';
|
|
32
32
|
const COMMAND_REACT_EMOJI = process.env.COMMAND_REACT_EMOJI || '🤖';
|
|
33
|
-
const START_LOGIN_TRIGGER =
|
|
34
|
-
.
|
|
35
|
-
|
|
33
|
+
const START_LOGIN_TRIGGER =
|
|
34
|
+
String(process.env.WHATSAPP_LOGIN_TRIGGER || 'iniciar')
|
|
35
|
+
.trim()
|
|
36
|
+
.toLowerCase() || 'iniciar';
|
|
36
37
|
const WHATSAPP_USER_SERVERS = new Set(['s.whatsapp.net', 'c.us', 'hosted']);
|
|
37
38
|
const WHATSAPP_LID_SERVERS = new Set(['lid', 'hosted.lid']);
|
|
38
39
|
|
|
@@ -61,17 +62,7 @@ const resolveCanonicalWhatsAppJid = (...candidates) => {
|
|
|
61
62
|
return '';
|
|
62
63
|
};
|
|
63
64
|
|
|
64
|
-
const maybeHandleStartLoginMessage = async ({
|
|
65
|
-
sock,
|
|
66
|
-
messageInfo,
|
|
67
|
-
extractedText,
|
|
68
|
-
senderName,
|
|
69
|
-
senderJid,
|
|
70
|
-
remoteJid,
|
|
71
|
-
expirationMessage,
|
|
72
|
-
isMessageFromBot,
|
|
73
|
-
isGroupMessage,
|
|
74
|
-
}) => {
|
|
65
|
+
const maybeHandleStartLoginMessage = async ({ sock, messageInfo, extractedText, senderName, senderJid, remoteJid, expirationMessage, isMessageFromBot, isGroupMessage }) => {
|
|
75
66
|
if (isMessageFromBot || !isStartLoginTrigger(extractedText)) return false;
|
|
76
67
|
|
|
77
68
|
if (isGroupMessage) {
|
|
@@ -88,15 +79,7 @@ const maybeHandleStartLoginMessage = async ({
|
|
|
88
79
|
|
|
89
80
|
const key = messageInfo?.key || {};
|
|
90
81
|
const senderInfo = extractSenderInfoFromMessage(messageInfo);
|
|
91
|
-
let canonicalUserId = resolveCanonicalWhatsAppJid(
|
|
92
|
-
senderInfo?.jid,
|
|
93
|
-
senderInfo?.lid,
|
|
94
|
-
senderInfo?.participantAlt,
|
|
95
|
-
key.participantAlt,
|
|
96
|
-
key.participant,
|
|
97
|
-
key.remoteJid,
|
|
98
|
-
senderJid,
|
|
99
|
-
);
|
|
82
|
+
let canonicalUserId = resolveCanonicalWhatsAppJid(senderInfo?.jid, senderInfo?.lid, senderInfo?.participantAlt, key.participantAlt, key.participant, key.remoteJid, senderJid);
|
|
100
83
|
try {
|
|
101
84
|
const resolvedUserId = await resolveUserId(senderInfo);
|
|
102
85
|
canonicalUserId = resolveCanonicalWhatsAppJid(resolvedUserId, canonicalUserId, senderInfo?.jid, senderInfo?.lid);
|
|
@@ -133,11 +116,7 @@ const maybeHandleStartLoginMessage = async ({
|
|
|
133
116
|
sock,
|
|
134
117
|
remoteJid,
|
|
135
118
|
{
|
|
136
|
-
text:
|
|
137
|
-
`${greeting}\n\n` +
|
|
138
|
-
'Para continuar no OmniZap, faca login com Google neste link:\n' +
|
|
139
|
-
`${loginUrl}\n\n` +
|
|
140
|
-
'Seu numero do WhatsApp sera vinculado automaticamente a conta logada.',
|
|
119
|
+
text: `${greeting}\n\n` + 'Para continuar no OmniZap, faca login com Google neste link:\n' + `${loginUrl}\n\n` + 'Seu numero do WhatsApp sera vinculado automaticamente a conta logada.',
|
|
141
120
|
},
|
|
142
121
|
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
143
122
|
);
|
|
@@ -110,17 +110,12 @@ const TTS_OUTPUT_FORMAT = OPENAI_TTS_PTT ? 'opus' : SAFE_TTS_FORMAT;
|
|
|
110
110
|
const TTS_MIME_TYPE = AUDIO_MIME_BY_FORMAT[TTS_OUTPUT_FORMAT] || 'audio/mpeg';
|
|
111
111
|
const TTS_MAX_CHARS = Number.isFinite(OPENAI_TTS_MAX_CHARS) && OPENAI_TTS_MAX_CHARS > 0 ? OPENAI_TTS_MAX_CHARS : 4096;
|
|
112
112
|
const OPENAI_TIMEOUT = Number.isFinite(OPENAI_TIMEOUT_MS) && OPENAI_TIMEOUT_MS > 0 ? OPENAI_TIMEOUT_MS : 30000;
|
|
113
|
-
const OPENAI_IMAGE_TIMEOUT =
|
|
114
|
-
Number.isFinite(OPENAI_IMAGE_TIMEOUT_MS) && OPENAI_IMAGE_TIMEOUT_MS > 0 ? OPENAI_IMAGE_TIMEOUT_MS : 120000;
|
|
113
|
+
const OPENAI_IMAGE_TIMEOUT = Number.isFinite(OPENAI_IMAGE_TIMEOUT_MS) && OPENAI_IMAGE_TIMEOUT_MS > 0 ? OPENAI_IMAGE_TIMEOUT_MS : 120000;
|
|
115
114
|
const OPENAI_CLIENT_TIMEOUT = Math.max(OPENAI_TIMEOUT, OPENAI_IMAGE_TIMEOUT);
|
|
116
115
|
const OPENAI_RETRIES = Number.isFinite(OPENAI_MAX_RETRIES) && OPENAI_MAX_RETRIES >= 0 ? OPENAI_MAX_RETRIES : 2;
|
|
117
|
-
const OPENAI_RETRY_BASE =
|
|
118
|
-
Number.isFinite(OPENAI_RETRY_BASE_MS) && OPENAI_RETRY_BASE_MS > 0 ? OPENAI_RETRY_BASE_MS : 500;
|
|
116
|
+
const OPENAI_RETRY_BASE = Number.isFinite(OPENAI_RETRY_BASE_MS) && OPENAI_RETRY_BASE_MS > 0 ? OPENAI_RETRY_BASE_MS : 500;
|
|
119
117
|
const OPENAI_RETRY_MAX = Number.isFinite(OPENAI_RETRY_MAX_MS) && OPENAI_RETRY_MAX_MS > 0 ? OPENAI_RETRY_MAX_MS : 4000;
|
|
120
|
-
const MAX_IMAGE_BYTES =
|
|
121
|
-
Number.isFinite(OPENAI_MAX_IMAGE_MB) && OPENAI_MAX_IMAGE_MB > 0
|
|
122
|
-
? OPENAI_MAX_IMAGE_MB * 1024 * 1024
|
|
123
|
-
: 50 * 1024 * 1024;
|
|
118
|
+
const MAX_IMAGE_BYTES = Number.isFinite(OPENAI_MAX_IMAGE_MB) && OPENAI_MAX_IMAGE_MB > 0 ? OPENAI_MAX_IMAGE_MB * 1024 * 1024 : 50 * 1024 * 1024;
|
|
124
119
|
|
|
125
120
|
const getClient = () => {
|
|
126
121
|
if (cachedClient) return cachedClient;
|
|
@@ -204,21 +199,7 @@ const sendUsage = async (sock, remoteJid, messageInfo, expirationMessage, comman
|
|
|
204
199
|
sock,
|
|
205
200
|
remoteJid,
|
|
206
201
|
{
|
|
207
|
-
text: [
|
|
208
|
-
'🤖 *Comando CAT*',
|
|
209
|
-
'',
|
|
210
|
-
'Use assim:',
|
|
211
|
-
`*${commandPrefix}cat* [--audio] sua pergunta`,
|
|
212
|
-
`*${commandPrefix}cat* (responda ou envie uma imagem com legenda)`,
|
|
213
|
-
'',
|
|
214
|
-
'Opções:',
|
|
215
|
-
'--audio | --texto',
|
|
216
|
-
'--detail low | high | auto',
|
|
217
|
-
'',
|
|
218
|
-
'Exemplo:',
|
|
219
|
-
`*${commandPrefix}cat* Explique como funciona a fotossíntese.`,
|
|
220
|
-
`*${commandPrefix}cat* --audio Resuma a imagem.`,
|
|
221
|
-
].join('\n'),
|
|
202
|
+
text: ['🤖 *Comando CAT*', '', 'Use assim:', `*${commandPrefix}cat* [--audio] sua pergunta`, `*${commandPrefix}cat* (responda ou envie uma imagem com legenda)`, '', 'Opções:', '--audio | --texto', '--detail low | high | auto', '', 'Exemplo:', `*${commandPrefix}cat* Explique como funciona a fotossíntese.`, `*${commandPrefix}cat* --audio Resuma a imagem.`].join('\n'),
|
|
222
203
|
},
|
|
223
204
|
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
224
205
|
);
|
|
@@ -253,70 +234,29 @@ const sendPremiumOnly = async (sock, remoteJid, messageInfo, expirationMessage)
|
|
|
253
234
|
sock,
|
|
254
235
|
remoteJid,
|
|
255
236
|
{
|
|
256
|
-
text: [
|
|
257
|
-
'⭐ *Comando Premium*',
|
|
258
|
-
'',
|
|
259
|
-
'Este comando é exclusivo para usuários premium.',
|
|
260
|
-
'Fale com o administrador para liberar o acesso.',
|
|
261
|
-
].join('\n'),
|
|
237
|
+
text: ['⭐ *Comando Premium*', '', 'Este comando é exclusivo para usuários premium.', 'Fale com o administrador para liberar o acesso.'].join('\n'),
|
|
262
238
|
},
|
|
263
239
|
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
264
240
|
);
|
|
265
241
|
};
|
|
266
242
|
|
|
267
|
-
const sendPromptUsage = async (
|
|
268
|
-
sock,
|
|
269
|
-
remoteJid,
|
|
270
|
-
messageInfo,
|
|
271
|
-
expirationMessage,
|
|
272
|
-
commandPrefix = DEFAULT_COMMAND_PREFIX,
|
|
273
|
-
) => {
|
|
243
|
+
const sendPromptUsage = async (sock, remoteJid, messageInfo, expirationMessage, commandPrefix = DEFAULT_COMMAND_PREFIX) => {
|
|
274
244
|
await sendAndStore(
|
|
275
245
|
sock,
|
|
276
246
|
remoteJid,
|
|
277
247
|
{
|
|
278
|
-
text: [
|
|
279
|
-
'🧠 *Prompt da IA*',
|
|
280
|
-
'',
|
|
281
|
-
'Use assim:',
|
|
282
|
-
`*${commandPrefix}catprompt* seu novo prompt`,
|
|
283
|
-
'',
|
|
284
|
-
'Para voltar ao padrão:',
|
|
285
|
-
`*${commandPrefix}catprompt reset*`,
|
|
286
|
-
].join('\n'),
|
|
248
|
+
text: ['🧠 *Prompt da IA*', '', 'Use assim:', `*${commandPrefix}catprompt* seu novo prompt`, '', 'Para voltar ao padrão:', `*${commandPrefix}catprompt reset*`].join('\n'),
|
|
287
249
|
},
|
|
288
250
|
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
289
251
|
);
|
|
290
252
|
};
|
|
291
253
|
|
|
292
|
-
const sendImageUsage = async (
|
|
293
|
-
sock,
|
|
294
|
-
remoteJid,
|
|
295
|
-
messageInfo,
|
|
296
|
-
expirationMessage,
|
|
297
|
-
commandPrefix = DEFAULT_COMMAND_PREFIX,
|
|
298
|
-
) => {
|
|
254
|
+
const sendImageUsage = async (sock, remoteJid, messageInfo, expirationMessage, commandPrefix = DEFAULT_COMMAND_PREFIX) => {
|
|
299
255
|
await sendAndStore(
|
|
300
256
|
sock,
|
|
301
257
|
remoteJid,
|
|
302
258
|
{
|
|
303
|
-
text: [
|
|
304
|
-
'🖼️ *Imagem IA*',
|
|
305
|
-
'',
|
|
306
|
-
'Use assim:',
|
|
307
|
-
`*${commandPrefix}catimg* seu prompt`,
|
|
308
|
-
`*${commandPrefix}catimg* (responda uma imagem com legenda para editar)`,
|
|
309
|
-
'',
|
|
310
|
-
'Opções:',
|
|
311
|
-
'--size 1024x1024 | 1024x1536 | 1536x1024 | auto',
|
|
312
|
-
'--quality low | medium | high | auto',
|
|
313
|
-
'--format png | jpeg | webp',
|
|
314
|
-
'--background transparent | opaque | auto',
|
|
315
|
-
'--compression 0-100',
|
|
316
|
-
'',
|
|
317
|
-
'Exemplo:',
|
|
318
|
-
`*${commandPrefix}catimg* --size 1536x1024 Um gato astronauta em aquarela.`,
|
|
319
|
-
].join('\n'),
|
|
259
|
+
text: ['🖼️ *Imagem IA*', '', 'Use assim:', `*${commandPrefix}catimg* seu prompt`, `*${commandPrefix}catimg* (responda uma imagem com legenda para editar)`, '', 'Opções:', '--size 1024x1024 | 1024x1536 | 1536x1024 | auto', '--quality low | medium | high | auto', '--format png | jpeg | webp', '--background transparent | opaque | auto', '--compression 0-100', '', 'Exemplo:', `*${commandPrefix}catimg* --size 1536x1024 Um gato astronauta em aquarela.`].join('\n'),
|
|
320
260
|
},
|
|
321
261
|
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
322
262
|
);
|
|
@@ -581,15 +521,7 @@ const buildImageDataUrl = async (imageMedia, senderJid) => {
|
|
|
581
521
|
}
|
|
582
522
|
};
|
|
583
523
|
|
|
584
|
-
export async function handleCatCommand({
|
|
585
|
-
sock,
|
|
586
|
-
remoteJid,
|
|
587
|
-
messageInfo,
|
|
588
|
-
expirationMessage,
|
|
589
|
-
senderJid,
|
|
590
|
-
text,
|
|
591
|
-
commandPrefix = DEFAULT_COMMAND_PREFIX,
|
|
592
|
-
}) {
|
|
524
|
+
export async function handleCatCommand({ sock, remoteJid, messageInfo, expirationMessage, senderJid, text, commandPrefix = DEFAULT_COMMAND_PREFIX }) {
|
|
593
525
|
const { prompt: rawPrompt, wantsAudio, imageDetail } = parseCatOptions(text || '');
|
|
594
526
|
|
|
595
527
|
if (!process.env.OPENAI_API_KEY) {
|
|
@@ -598,11 +530,7 @@ export async function handleCatCommand({
|
|
|
598
530
|
sock,
|
|
599
531
|
remoteJid,
|
|
600
532
|
{
|
|
601
|
-
text: [
|
|
602
|
-
'⚠️ *OpenAI não configurada*',
|
|
603
|
-
'',
|
|
604
|
-
'Defina a variável *OPENAI_API_KEY* no `.env` para usar o comando *cat*.',
|
|
605
|
-
].join('\n'),
|
|
533
|
+
text: ['⚠️ *OpenAI não configurada*', '', 'Defina a variável *OPENAI_API_KEY* no `.env` para usar o comando *cat*.'].join('\n'),
|
|
606
534
|
},
|
|
607
535
|
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
608
536
|
);
|
|
@@ -632,12 +560,7 @@ export async function handleCatCommand({
|
|
|
632
560
|
}
|
|
633
561
|
|
|
634
562
|
if (imageResult.error === 'download_failed') {
|
|
635
|
-
await sendAndStore(
|
|
636
|
-
sock,
|
|
637
|
-
remoteJid,
|
|
638
|
-
{ text: '⚠️ Não consegui baixar a imagem. Tente reenviar.' },
|
|
639
|
-
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
640
|
-
);
|
|
563
|
+
await sendAndStore(sock, remoteJid, { text: '⚠️ Não consegui baixar a imagem. Tente reenviar.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
641
564
|
return;
|
|
642
565
|
}
|
|
643
566
|
|
|
@@ -695,23 +618,13 @@ export async function handleCatCommand({
|
|
|
695
618
|
});
|
|
696
619
|
|
|
697
620
|
if (!outputText) {
|
|
698
|
-
await sendAndStore(
|
|
699
|
-
sock,
|
|
700
|
-
remoteJid,
|
|
701
|
-
{ text: '⚠️ Não consegui gerar uma resposta agora. Tente novamente.' },
|
|
702
|
-
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
703
|
-
);
|
|
621
|
+
await sendAndStore(sock, remoteJid, { text: '⚠️ Não consegui gerar uma resposta agora. Tente novamente.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
704
622
|
return;
|
|
705
623
|
}
|
|
706
624
|
|
|
707
625
|
if (wantsAudio) {
|
|
708
626
|
if (outputText.length > TTS_MAX_CHARS) {
|
|
709
|
-
await sendAndStore(
|
|
710
|
-
sock,
|
|
711
|
-
remoteJid,
|
|
712
|
-
{ text: '⚠️ A resposta ficou longa demais para áudio. Enviando em texto.' },
|
|
713
|
-
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
714
|
-
);
|
|
627
|
+
await sendAndStore(sock, remoteJid, { text: '⚠️ A resposta ficou longa demais para áudio. Enviando em texto.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
715
628
|
} else {
|
|
716
629
|
try {
|
|
717
630
|
const audioResponse = await callOpenAI(
|
|
@@ -739,22 +652,12 @@ export async function handleCatCommand({
|
|
|
739
652
|
return;
|
|
740
653
|
} catch (audioError) {
|
|
741
654
|
logger.error('handleCatCommand: erro ao gerar audio.', audioError);
|
|
742
|
-
await sendAndStore(
|
|
743
|
-
sock,
|
|
744
|
-
remoteJid,
|
|
745
|
-
{ text: '⚠️ Não consegui gerar o áudio agora. Enviando texto.' },
|
|
746
|
-
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
747
|
-
);
|
|
655
|
+
await sendAndStore(sock, remoteJid, { text: '⚠️ Não consegui gerar o áudio agora. Enviando texto.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
748
656
|
}
|
|
749
657
|
}
|
|
750
658
|
}
|
|
751
659
|
|
|
752
|
-
await sendAndStore(
|
|
753
|
-
sock,
|
|
754
|
-
remoteJid,
|
|
755
|
-
{ text: `🐈⬛ ${outputText}` },
|
|
756
|
-
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
757
|
-
);
|
|
660
|
+
await sendAndStore(sock, remoteJid, { text: `🐈⬛ ${outputText}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
758
661
|
} catch (error) {
|
|
759
662
|
logger.error('handleCatCommand: erro ao chamar OpenAI.', error);
|
|
760
663
|
await sendAndStore(
|
|
@@ -768,15 +671,7 @@ export async function handleCatCommand({
|
|
|
768
671
|
}
|
|
769
672
|
}
|
|
770
673
|
|
|
771
|
-
export async function handleCatImageCommand({
|
|
772
|
-
sock,
|
|
773
|
-
remoteJid,
|
|
774
|
-
messageInfo,
|
|
775
|
-
expirationMessage,
|
|
776
|
-
senderJid,
|
|
777
|
-
text,
|
|
778
|
-
commandPrefix = DEFAULT_COMMAND_PREFIX,
|
|
779
|
-
}) {
|
|
674
|
+
export async function handleCatImageCommand({ sock, remoteJid, messageInfo, expirationMessage, senderJid, text, commandPrefix = DEFAULT_COMMAND_PREFIX }) {
|
|
780
675
|
const { prompt, toolOptions, errors } = parseImageGenOptions(text || '');
|
|
781
676
|
|
|
782
677
|
if (!process.env.OPENAI_API_KEY) {
|
|
@@ -785,11 +680,7 @@ export async function handleCatImageCommand({
|
|
|
785
680
|
sock,
|
|
786
681
|
remoteJid,
|
|
787
682
|
{
|
|
788
|
-
text: [
|
|
789
|
-
'⚠️ *OpenAI não configurada*',
|
|
790
|
-
'',
|
|
791
|
-
'Defina a variável *OPENAI_API_KEY* no `.env` para usar o comando *catimg*.',
|
|
792
|
-
].join('\n'),
|
|
683
|
+
text: ['⚠️ *OpenAI não configurada*', '', 'Defina a variável *OPENAI_API_KEY* no `.env` para usar o comando *catimg*.'].join('\n'),
|
|
793
684
|
},
|
|
794
685
|
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
795
686
|
);
|
|
@@ -819,12 +710,7 @@ export async function handleCatImageCommand({
|
|
|
819
710
|
}
|
|
820
711
|
|
|
821
712
|
if (imageResult.error === 'download_failed') {
|
|
822
|
-
await sendAndStore(
|
|
823
|
-
sock,
|
|
824
|
-
remoteJid,
|
|
825
|
-
{ text: '⚠️ Não consegui baixar a imagem. Tente reenviar.' },
|
|
826
|
-
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
827
|
-
);
|
|
713
|
+
await sendAndStore(sock, remoteJid, { text: '⚠️ Não consegui baixar a imagem. Tente reenviar.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
828
714
|
return;
|
|
829
715
|
}
|
|
830
716
|
|
|
@@ -838,12 +724,7 @@ export async function handleCatImageCommand({
|
|
|
838
724
|
sock,
|
|
839
725
|
remoteJid,
|
|
840
726
|
{
|
|
841
|
-
text: [
|
|
842
|
-
'⚠️ Opções inválidas no comando.',
|
|
843
|
-
`Detalhes: ${errors.join(', ')}`,
|
|
844
|
-
'',
|
|
845
|
-
`Use *${commandPrefix}catimg* sem opções para ver o formato correto.`,
|
|
846
|
-
].join('\n'),
|
|
727
|
+
text: ['⚠️ Opções inválidas no comando.', `Detalhes: ${errors.join(', ')}`, '', `Use *${commandPrefix}catimg* sem opções para ver o formato correto.`].join('\n'),
|
|
847
728
|
},
|
|
848
729
|
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
849
730
|
);
|
|
@@ -888,11 +769,7 @@ export async function handleCatImageCommand({
|
|
|
888
769
|
|
|
889
770
|
try {
|
|
890
771
|
const client = getClient();
|
|
891
|
-
const response = await callOpenAI(
|
|
892
|
-
() => client.responses.create(payload),
|
|
893
|
-
'responses.create.image',
|
|
894
|
-
OPENAI_IMAGE_TIMEOUT,
|
|
895
|
-
);
|
|
772
|
+
const response = await callOpenAI(() => client.responses.create(payload), 'responses.create.image', OPENAI_IMAGE_TIMEOUT);
|
|
896
773
|
const outputText = response.output_text?.trim();
|
|
897
774
|
|
|
898
775
|
sessionCache.set(sessionKey, {
|
|
@@ -900,28 +777,16 @@ export async function handleCatImageCommand({
|
|
|
900
777
|
updatedAt: Date.now(),
|
|
901
778
|
});
|
|
902
779
|
|
|
903
|
-
const imageOutputs = Array.isArray(response.output)
|
|
904
|
-
? response.output.filter((output) => output.type === 'image_generation_call' && output.result)
|
|
905
|
-
: [];
|
|
780
|
+
const imageOutputs = Array.isArray(response.output) ? response.output.filter((output) => output.type === 'image_generation_call' && output.result) : [];
|
|
906
781
|
const imageBase64 = imageOutputs[0]?.result;
|
|
907
782
|
|
|
908
783
|
if (!imageBase64) {
|
|
909
784
|
if (outputText) {
|
|
910
|
-
await sendAndStore(
|
|
911
|
-
sock,
|
|
912
|
-
remoteJid,
|
|
913
|
-
{ text: `🖼️ ${outputText}` },
|
|
914
|
-
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
915
|
-
);
|
|
785
|
+
await sendAndStore(sock, remoteJid, { text: `🖼️ ${outputText}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
916
786
|
return;
|
|
917
787
|
}
|
|
918
788
|
|
|
919
|
-
await sendAndStore(
|
|
920
|
-
sock,
|
|
921
|
-
remoteJid,
|
|
922
|
-
{ text: '⚠️ Não consegui gerar a imagem agora. Tente novamente.' },
|
|
923
|
-
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
924
|
-
);
|
|
789
|
+
await sendAndStore(sock, remoteJid, { text: '⚠️ Não consegui gerar a imagem agora. Tente novamente.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
925
790
|
return;
|
|
926
791
|
}
|
|
927
792
|
|
|
@@ -935,12 +800,7 @@ export async function handleCatImageCommand({
|
|
|
935
800
|
const imageBuffer = Buffer.from(imageBase64, 'base64');
|
|
936
801
|
const caption = outputText ? `🖼️ ${outputText}` : '🖼️ Imagem gerada.';
|
|
937
802
|
|
|
938
|
-
await sendAndStore(
|
|
939
|
-
sock,
|
|
940
|
-
remoteJid,
|
|
941
|
-
{ image: imageBuffer, caption, mimetype },
|
|
942
|
-
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
943
|
-
);
|
|
803
|
+
await sendAndStore(sock, remoteJid, { image: imageBuffer, caption, mimetype }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
944
804
|
} catch (error) {
|
|
945
805
|
logger.error('handleCatImageCommand: erro ao chamar OpenAI.', error);
|
|
946
806
|
await sendAndStore(
|
|
@@ -954,15 +814,7 @@ export async function handleCatImageCommand({
|
|
|
954
814
|
}
|
|
955
815
|
}
|
|
956
816
|
|
|
957
|
-
export async function handleCatPromptCommand({
|
|
958
|
-
sock,
|
|
959
|
-
remoteJid,
|
|
960
|
-
messageInfo,
|
|
961
|
-
expirationMessage,
|
|
962
|
-
senderJid,
|
|
963
|
-
text,
|
|
964
|
-
commandPrefix = DEFAULT_COMMAND_PREFIX,
|
|
965
|
-
}) {
|
|
817
|
+
export async function handleCatPromptCommand({ sock, remoteJid, messageInfo, expirationMessage, senderJid, text, commandPrefix = DEFAULT_COMMAND_PREFIX }) {
|
|
966
818
|
const promptText = text?.trim();
|
|
967
819
|
if (!promptText) {
|
|
968
820
|
await sendPromptUsage(sock, remoteJid, messageInfo, expirationMessage, commandPrefix);
|
|
@@ -977,30 +829,15 @@ export async function handleCatPromptCommand({
|
|
|
977
829
|
const lower = promptText.toLowerCase();
|
|
978
830
|
if (lower === 'reset' || lower === 'default' || lower === 'padrao' || lower === 'padrão') {
|
|
979
831
|
await aiPromptStore.clearPrompt(senderJid);
|
|
980
|
-
await sendAndStore(
|
|
981
|
-
sock,
|
|
982
|
-
remoteJid,
|
|
983
|
-
{ text: '✅ Prompt da IA restaurado para o padrão.' },
|
|
984
|
-
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
985
|
-
);
|
|
832
|
+
await sendAndStore(sock, remoteJid, { text: '✅ Prompt da IA restaurado para o padrão.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
986
833
|
return;
|
|
987
834
|
}
|
|
988
835
|
|
|
989
836
|
if (promptText.length > 2000) {
|
|
990
|
-
await sendAndStore(
|
|
991
|
-
sock,
|
|
992
|
-
remoteJid,
|
|
993
|
-
{ text: '⚠️ Prompt muito longo. Limite: 2000 caracteres.' },
|
|
994
|
-
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
995
|
-
);
|
|
837
|
+
await sendAndStore(sock, remoteJid, { text: '⚠️ Prompt muito longo. Limite: 2000 caracteres.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
996
838
|
return;
|
|
997
839
|
}
|
|
998
840
|
|
|
999
841
|
await aiPromptStore.setPrompt(senderJid, promptText);
|
|
1000
|
-
await sendAndStore(
|
|
1001
|
-
sock,
|
|
1002
|
-
remoteJid,
|
|
1003
|
-
{ text: '✅ Prompt da IA atualizado para você.' },
|
|
1004
|
-
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1005
|
-
);
|
|
842
|
+
await sendAndStore(sock, remoteJid, { text: '✅ Prompt da IA atualizado para você.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1006
843
|
}
|