@omnizap-system/omnizap 2.6.0 → 2.6.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.
- package/.env.example +58 -13
- package/.github/workflows/ci.yml +5 -5
- package/.github/workflows/codeql.yml +1 -1
- package/.github/workflows/db-migration-check.yml +2 -2
- package/.github/workflows/dependency-review.yml +1 -1
- package/.github/workflows/deploy.yml +2 -2
- package/.github/workflows/release.yml +2 -2
- package/.github/workflows/security-attest-provenance.yml +2 -2
- package/.github/workflows/security-gitleaks.yml +13 -4
- package/.github/workflows/security-runner-hardening.yml +2 -2
- package/.github/workflows/security-scorecard.yml +1 -1
- package/.github/workflows/security-zap-baseline.yml +1 -1
- package/.github/workflows/security-zap-full-scan.yml +2 -1
- package/.github/workflows/security-zizmor.yml +1 -1
- package/.github/workflows/wiki-sync.yml +1 -1
- package/.gitleaksignore +9 -0
- package/CODE_OF_CONDUCT.md +2 -2
- package/GEMINI.md +64 -0
- package/README.md +52 -82
- package/SECURITY.md +1 -1
- package/app/config/index.js +2 -0
- package/app/configParts/adminIdentity.js +5 -5
- package/app/configParts/baileysConfig.js +230 -58
- package/app/configParts/groupUtils.js +5 -0
- package/app/configParts/messagePersistenceService.js +145 -4
- package/app/configParts/sessionConfig.js +157 -0
- package/app/connection/baileysCompatibility.test.js +1 -1
- package/app/connection/groupOwnerWriteStateResolver.js +109 -0
- package/app/connection/socketController.js +660 -158
- package/app/connection/socketController.multiSession.test.js +108 -0
- package/app/controllers/messageController.js +1 -1
- package/app/controllers/messagePipeline/commandMiddleware.js +12 -10
- package/app/controllers/messagePipeline/conversationMiddleware.js +2 -1
- package/app/controllers/messagePipeline/messagePipelineMiddlewares.test.js +104 -0
- package/app/controllers/messagePipeline/preProcessingMiddlewares.js +80 -2
- package/app/controllers/messageProcessingPipeline.js +93 -13
- package/app/controllers/messageProcessingPipeline.test.js +200 -0
- package/app/modules/adminModule/AGENT.md +1 -1
- package/app/modules/adminModule/commandConfig.json +3318 -1347
- package/app/modules/adminModule/groupCommandHandlers.js +858 -15
- package/app/modules/adminModule/groupCommandHandlers.test.js +378 -11
- package/app/modules/adminModule/groupWarningRepository.js +152 -0
- package/app/modules/aiModule/AGENT.md +47 -30
- package/app/modules/aiModule/aiConfigRuntime.js +1 -0
- package/app/modules/aiModule/catCommand.js +135 -27
- package/app/modules/aiModule/commandConfig.json +114 -28
- package/app/modules/analyticsModule/messageAnalysisEventRepository.js +54 -6
- package/app/modules/gameModule/AGENT.md +1 -1
- package/app/modules/gameModule/commandConfig.json +29 -0
- package/app/modules/menuModule/AGENT.md +1 -1
- package/app/modules/menuModule/commandConfig.json +45 -10
- package/app/modules/menuModule/menuCatalogService.js +190 -0
- package/app/modules/menuModule/menuCommandUsageRepository.js +109 -0
- package/app/modules/menuModule/menuDynamicService.js +511 -0
- package/app/modules/menuModule/menuDynamicService.test.js +141 -0
- package/app/modules/menuModule/menus.js +36 -5
- package/app/modules/playModule/AGENT.md +10 -5
- package/app/modules/playModule/commandConfig.json +140 -12
- package/app/modules/playModule/playCommand.js +1 -1417
- package/app/modules/playModule/playCommandConstants.js +80 -0
- package/app/modules/playModule/playCommandCore.js +361 -0
- package/app/modules/playModule/playCommandHandlers.js +41 -0
- package/app/modules/playModule/playCommandMediaClient.js +1872 -0
- package/app/modules/playModule/playConfigRuntime.js +245 -4
- package/app/modules/playModule/playModuleCriticalFlows.test.js +152 -0
- package/app/modules/quoteModule/AGENT.md +1 -1
- package/app/modules/quoteModule/commandConfig.json +29 -0
- package/app/modules/quoteModule/quoteCommand.js +3 -2
- package/app/modules/rpgPokemonModule/AGENT.md +1 -1
- package/app/modules/rpgPokemonModule/commandConfig.json +29 -0
- package/app/modules/rpgPokemonModule/rpgBattleCanvasRenderer.js +5 -4
- package/app/modules/rpgPokemonModule/rpgBattleService.test.js +2 -1
- package/app/modules/rpgPokemonModule/rpgPokemonDomain.js +2 -1
- package/app/modules/rpgPokemonModule/rpgPokemonService.js +38 -37
- package/app/modules/rpgPokemonModule/rpgProfileCanvasRenderer.js +4 -3
- package/app/modules/statsModule/AGENT.md +1 -1
- package/app/modules/statsModule/commandConfig.json +58 -0
- package/app/modules/statsModule/rankingCommon.js +5 -4
- package/app/modules/stickerModule/AGENT.md +1 -1
- package/app/modules/stickerModule/addStickerMetadata.js +4 -3
- package/app/modules/stickerModule/commandConfig.json +145 -0
- package/app/modules/stickerModule/stickerCommand.js +1 -1
- package/app/modules/stickerPackModule/AGENT.md +1 -1
- package/app/modules/stickerPackModule/autoPackCollectorService.js +5 -1
- package/app/modules/stickerPackModule/commandConfig.json +29 -0
- package/app/modules/stickerPackModule/semanticThemeClusterService.js +7 -6
- package/app/modules/stickerPackModule/stickerAutoPackByTagsRuntime.js +10 -9
- package/app/modules/stickerPackModule/stickerClassificationBackgroundRuntime.js +9 -8
- package/app/modules/stickerPackModule/stickerDomainEventConsumerRuntime.js +3 -2
- package/app/modules/stickerPackModule/stickerMarketplaceDriftService.js +2 -1
- package/app/modules/stickerPackModule/stickerPackCommandHandlers.js +80 -58
- package/app/modules/stickerPackModule/stickerPackMarketplaceService.js +2 -1
- package/app/modules/stickerPackModule/stickerPackRepository.js +2 -1
- package/app/modules/stickerPackModule/stickerPackScoreSnapshotRuntime.js +5 -4
- package/app/modules/stickerPackModule/stickerPackService.js +13 -6
- package/app/modules/stickerPackModule/stickerStorageService.js +3 -2
- package/app/modules/stickerPackModule/stickerWorkerPipelineRuntime.js +2 -1
- package/app/modules/systemMetricsModule/AGENT.md +1 -1
- package/app/modules/systemMetricsModule/commandConfig.json +29 -0
- package/app/modules/systemMetricsModule/pingCommand.js +6 -5
- package/app/modules/tiktokModule/AGENT.md +1 -1
- package/app/modules/tiktokModule/commandConfig.json +29 -0
- package/app/modules/tiktokModule/tiktokCommand.js +2 -1
- package/app/modules/userModule/AGENT.md +1 -1
- package/app/modules/userModule/commandConfig.json +29 -0
- package/app/modules/userModule/userCommand.js +72 -23
- package/app/modules/waifuPicsModule/AGENT.md +57 -27
- package/app/modules/waifuPicsModule/commandConfig.json +87 -0
- package/app/modules/waifuPicsModule/waifuPicsCommand.js +3 -2
- package/app/observability/metrics.js +136 -0
- package/app/services/ai/commandConfigEnrichmentService.js +229 -47
- package/app/services/ai/conversationRouterService.js +4 -3
- package/app/services/ai/geminiService.js +132 -7
- package/app/services/ai/geminiService.test.js +59 -2
- package/app/services/ai/globalModuleAiHelpService.js +3 -2
- package/app/services/ai/messageCommandExecutionService.js +2 -1
- package/app/services/ai/moduleAiHelpCoreService.js +45 -14
- package/app/services/ai/moduleToolExecutorService.js +3 -2
- package/app/services/ai/moduleToolRegistryService.js +2 -1
- package/app/services/ai/toolCandidateSelectorService.js +6 -5
- package/app/services/auth/googleWebLinkService.js +3 -2
- package/app/services/auth/whatsappLoginLinkService.js +3 -2
- package/app/services/external/pokeApiService.js +4 -3
- package/app/services/group/groupMetadataService.js +24 -1
- package/app/services/infra/dbWriteQueue.js +57 -26
- package/app/services/infra/featureFlagService.js +2 -1
- package/app/services/messaging/captchaService.js +3 -2
- package/app/services/messaging/newsBroadcastService.js +846 -29
- package/app/services/multiSession/assignmentBalancerService.js +457 -0
- package/app/services/multiSession/groupOwnershipRepository.js +381 -0
- package/app/services/multiSession/groupOwnershipService.js +890 -0
- package/app/services/multiSession/groupOwnershipService.test.js +309 -0
- package/app/services/multiSession/sessionRegistryService.js +293 -0
- package/app/services/sticker/stickerFocusService.js +11 -10
- package/app/store/aiPromptStore.js +36 -19
- package/app/store/conversationSessionStore.js +7 -6
- package/app/store/groupConfigStore.js +41 -5
- package/app/store/premiumUserStore.js +21 -7
- package/app/utils/antiLink/antiLinkModule.js +352 -16
- package/app/workers/aiHelperContinuousLearningWorker.js +512 -0
- package/app/workers/aiLearningWorker.js +6 -5
- package/app/workers/commandConfigEnrichmentWorker.js +4 -3
- package/database/index.js +14 -8
- package/database/migrations/20260307_d0_hardening_down.sql +1 -1
- package/database/migrations/20260314_d7_canonical_sender_down.sql +1 -1
- package/database/migrations/20260406_d30_security_analytics_down.sql +1 -1
- package/database/migrations/20260411_d35_group_community_metadata_down.sql +59 -0
- package/database/migrations/20260411_d35_group_community_metadata_up.sql +62 -0
- package/database/migrations/20260412_d36_system_config_tables_down.sql +32 -0
- package/database/migrations/20260412_d36_system_config_tables_up.sql +66 -0
- package/database/migrations/20260413_d37_group_user_warnings_down.sql +11 -0
- package/database/migrations/20260413_d37_group_user_warnings_up.sql +24 -0
- package/database/migrations/20260414_d38_multi_session_foundation_down.sql +72 -0
- package/database/migrations/20260414_d38_multi_session_foundation_up.sql +125 -0
- package/database/migrations/20260414_d39_multi_session_cutover_down.sql +103 -0
- package/database/migrations/20260414_d39_multi_session_cutover_up.sql +83 -0
- package/database/schema.sql +102 -1
- package/docker-compose.yml +4 -1
- package/docs/compliance/acceptable-use-policy-2026-03-07.md +1 -1
- package/docs/compliance/dpa-b2b-standard-2026-03-07.md +1 -1
- package/docs/compliance/privacy-policy-2026-03-07.md +4 -4
- package/docs/security/dsar-lgpd-runbook-2026-03-07.md +1 -1
- package/docs/security/incident-response-lgpd-anpd-runbook-2026-03-07.md +1 -1
- package/docs/security/network-hardening-runbook-2026-03-07.md +53 -0
- package/docs/security/omnizap-static-security-headers.conf +25 -0
- package/docs/wiki/Home.md +1 -1
- package/ecosystem.prod.config.cjs +32 -12
- package/index.js +57 -23
- package/observability/alert-rules.yml +20 -0
- package/observability/grafana/dashboards/omnizap-system-admin.json +229 -0
- package/observability/mysql-setup.sql +4 -4
- package/observability/system-admin-observability.md +26 -0
- package/package.json +20 -6
- package/public/apple-touch-icon.png +0 -0
- package/public/comandos/commands-catalog.json +2853 -3326
- package/public/favicon-16x16.png +0 -0
- package/public/favicon-32x32.png +0 -0
- package/public/favicon.ico +0 -0
- package/public/js/apps/apiDocsApp.js +3 -2
- package/public/js/apps/commandsReactApp.js +280 -99
- package/public/js/apps/createPackApp.js +11 -10
- package/public/js/apps/homeReactApp.js +181 -130
- package/public/js/apps/loginReactApp.js +1 -1
- package/public/js/apps/stickersApp.js +263 -110
- package/public/js/apps/termsReactApp.js +73 -24
- package/public/js/apps/userApp.js +4 -3
- package/public/js/apps/userPasswordResetReactApp.js +406 -0
- package/public/js/apps/userReactApp.js +355 -280
- package/public/js/apps/userSystemAdmReactApp.js +1506 -0
- package/public/pages/api-docs.html +1 -1
- package/public/pages/aup.html +2 -2
- package/public/pages/dpa.html +3 -3
- package/public/pages/licenca.html +4 -4
- package/public/pages/login.html +1 -1
- package/public/pages/notice-and-takedown.html +2 -2
- package/public/pages/politica-de-privacidade.html +6 -6
- package/public/pages/seo-bot-whatsapp-para-grupo.html +3 -3
- package/public/pages/seo-bot-whatsapp-sem-programar.html +3 -3
- package/public/pages/seo-como-automatizar-avisos-no-whatsapp.html +3 -3
- package/public/pages/seo-como-criar-comandos-whatsapp.html +3 -3
- package/public/pages/seo-como-evitar-spam-no-whatsapp.html +3 -3
- package/public/pages/seo-como-moderar-grupo-whatsapp.html +3 -3
- package/public/pages/seo-como-organizar-comunidade-whatsapp.html +3 -3
- package/public/pages/seo-melhor-bot-whatsapp-para-grupos.html +3 -3
- package/public/pages/stickers-admin.html +1 -1
- package/public/pages/stickers-create.html +1 -1
- package/public/pages/stickers.html +6 -6
- package/public/pages/suboperadores.html +2 -2
- package/public/pages/termos-de-uso-texto-integral.html +6 -6
- package/public/pages/termos-de-uso.html +3 -3
- package/public/pages/user-password-reset.html +4 -5
- package/public/pages/user-systemadm.html +9 -463
- package/public/pages/user.html +2 -2
- package/scripts/clear-whatsapp-session.sh +123 -0
- package/scripts/core-ai-mode.mjs +163 -0
- package/scripts/deploy.sh +11 -1
- package/scripts/email-broadcast-terms-update.mjs +2 -1
- package/scripts/enrich-command-config-ux-openai.mjs +492 -0
- package/scripts/generate-commands-catalog.mjs +166 -2
- package/scripts/generate-module-agents.mjs +2 -1
- package/scripts/generate-seo-satellite-pages.mjs +5 -4
- package/scripts/github-deploy-notify.mjs +2 -1
- package/scripts/github-release-notify.mjs +25 -10
- package/scripts/new-whatsapp-session.sh +317 -0
- package/scripts/release.sh +2 -19
- package/scripts/security-smoketest.mjs +6 -5
- package/scripts/security-web-surface-check.mjs +218 -0
- package/scripts/sticker-catalog-loadtest.mjs +5 -4
- package/server/auth/googleWebAuth/googleWebAuthService.js +8 -7
- package/server/auth/jwt/webJwtService.js +1 -1
- package/server/auth/stickerCatalogAuthContext.js +2 -1
- package/server/auth/termsAcceptance/termsAcceptanceHandler.js +2 -1
- package/server/auth/userPassword/userPasswordAuthService.js +2 -1
- package/server/auth/userPassword/userPasswordRecoveryService.js +4 -3
- package/server/auth/webAccount/webAccountHandlers.js +9 -10
- package/server/controllers/admin/adminPanelHandlers.js +267 -16
- package/server/controllers/admin/systemAdminController.js +267 -0
- package/server/controllers/seo/stickerCatalogSeoContext.js +10 -9
- package/server/controllers/sticker/nonCatalogHandlers.js +2 -1
- package/server/controllers/sticker/stickerCatalogController.js +23 -36
- package/server/controllers/system/contactController.js +9 -17
- package/server/controllers/system/githubController.js +3 -2
- package/server/controllers/system/stickerCatalogSystemContext.js +41 -19
- package/server/controllers/system/systemController.js +254 -1
- package/server/controllers/system/systemMetricsController.js +2 -1
- package/server/controllers/userController.js +6 -0
- package/server/email/emailTemplateService.js +5 -3
- package/server/http/httpServer.js +11 -6
- package/server/middleware/rateLimit.js +2 -1
- package/server/middleware/securityHeaders.js +20 -1
- package/server/routes/admin/systemAdminRouter.js +6 -0
- package/server/routes/indexRouter.js +30 -6
- package/server/routes/observability/grafanaProxyRouter.js +254 -0
- package/server/routes/static/staticPageRouter.js +27 -1
- package/server/utils/publicContact.js +31 -0
- package/utils/time/timeModule.js +135 -0
- package/utils/time/timeModule.test.js +65 -0
- package/utils/whatsapp/contactEnv.js +39 -0
- package/vite.config.mjs +7 -1
- package/public/assets/images/brand-icon-192.png +0 -0
- package/scripts/sync-readme-snapshot.mjs +0 -133
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import logger from '#logger';
|
|
2
2
|
import { buildAnimeMenu, buildAiMenu, buildMediaMenu, buildMenuCaption, buildQuoteMenu, buildStatsMenu, buildStickerMenu, buildAdminMenu } from './common.js';
|
|
3
|
+
import { resolveDynamicMenuText } from './menuDynamicService.js';
|
|
3
4
|
import getImageBuffer from '../../utils/http/getImageBufferModule.js';
|
|
4
5
|
import { sendAndStore } from '../../services/messaging/messagePersistenceService.js';
|
|
5
6
|
|
|
@@ -11,10 +12,13 @@ const sanitizeLogValue = (value) =>
|
|
|
11
12
|
.trim();
|
|
12
13
|
|
|
13
14
|
const sendMenuImage = async (sock, remoteJid, messageInfo, expirationMessage, caption) => {
|
|
15
|
+
const safeCaption = String(caption || '').trim() || 'Menu indisponível no momento.';
|
|
14
16
|
const imageUrl = process.env[MENU_IMAGE_ENV];
|
|
15
17
|
if (!imageUrl) {
|
|
16
|
-
logger.
|
|
17
|
-
|
|
18
|
+
logger.warn('IMAGE_MENU environment variable not set. Sending plain-text menu fallback.', {
|
|
19
|
+
action: 'menu_image_env_missing',
|
|
20
|
+
});
|
|
21
|
+
await sendAndStore(sock, remoteJid, { text: safeCaption }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
18
22
|
return;
|
|
19
23
|
}
|
|
20
24
|
|
|
@@ -25,7 +29,7 @@ const sendMenuImage = async (sock, remoteJid, messageInfo, expirationMessage, ca
|
|
|
25
29
|
remoteJid,
|
|
26
30
|
{
|
|
27
31
|
image: imageBuffer,
|
|
28
|
-
caption,
|
|
32
|
+
caption: safeCaption,
|
|
29
33
|
},
|
|
30
34
|
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
31
35
|
);
|
|
@@ -33,11 +37,22 @@ const sendMenuImage = async (sock, remoteJid, messageInfo, expirationMessage, ca
|
|
|
33
37
|
logger.error('Error fetching menu image.', {
|
|
34
38
|
error: sanitizeLogValue(error?.message) || 'unknown_error',
|
|
35
39
|
});
|
|
36
|
-
await sendAndStore(sock, remoteJid, { text:
|
|
40
|
+
await sendAndStore(sock, remoteJid, { text: safeCaption }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
37
41
|
}
|
|
38
42
|
};
|
|
39
43
|
|
|
40
44
|
export async function handleMenuCommand(sock, remoteJid, messageInfo, expirationMessage, senderName, commandPrefix, args = []) {
|
|
45
|
+
const dynamicCaption = await resolveDynamicMenuText({
|
|
46
|
+
args,
|
|
47
|
+
senderName,
|
|
48
|
+
commandPrefix,
|
|
49
|
+
remoteJid,
|
|
50
|
+
});
|
|
51
|
+
if (dynamicCaption) {
|
|
52
|
+
await sendMenuImage(sock, remoteJid, messageInfo, expirationMessage, dynamicCaption.trim());
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
41
56
|
const category = args?.[0]?.toLowerCase();
|
|
42
57
|
const categoryMap = new Map([
|
|
43
58
|
['figurinhas', (prefix) => buildStickerMenu(prefix)],
|
|
@@ -61,6 +76,22 @@ export async function handleMenuCommand(sock, remoteJid, messageInfo, expiration
|
|
|
61
76
|
await sendMenuImage(sock, remoteJid, messageInfo, expirationMessage, caption);
|
|
62
77
|
}
|
|
63
78
|
|
|
64
|
-
export async function handleMenuAdmCommand(sock, remoteJid, messageInfo, expirationMessage, commandPrefix) {
|
|
79
|
+
export async function handleMenuAdmCommand(sock, remoteJid, messageInfo, expirationMessage, commandPrefix, args = []) {
|
|
80
|
+
const safeArgs = Array.isArray(args) ? args.map((value) => String(value || '').trim()).filter(Boolean) : [];
|
|
81
|
+
const dynamicArgs = safeArgs.length ? safeArgs : ['categoria', 'admin'];
|
|
82
|
+
const dynamicCaption = await resolveDynamicMenuText({
|
|
83
|
+
args: dynamicArgs,
|
|
84
|
+
senderName: 'admin',
|
|
85
|
+
commandPrefix,
|
|
86
|
+
remoteJid,
|
|
87
|
+
menuCommandName: 'menuadm',
|
|
88
|
+
categoryScopeKeys: ['admin'],
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
if (dynamicCaption) {
|
|
92
|
+
await sendMenuImage(sock, remoteJid, messageInfo, expirationMessage, dynamicCaption.trim());
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
65
96
|
await sendMenuImage(sock, remoteJid, messageInfo, expirationMessage, buildAdminMenu(commandPrefix).trim());
|
|
66
97
|
}
|
|
@@ -7,13 +7,18 @@ Este arquivo e destinado a agentes de IA para gerar respostas no contexto dos co
|
|
|
7
7
|
- arquivo_base: `app/modules/playModule/commandConfig.json`
|
|
8
8
|
- schema_version: `2.0.0`
|
|
9
9
|
- module_enabled: `true`
|
|
10
|
-
- generated_at: `2026-03-
|
|
10
|
+
- generated_at: `2026-03-17T04:04:14.195Z`
|
|
11
11
|
|
|
12
12
|
## Escopo do Modulo
|
|
13
13
|
|
|
14
14
|
- module: `playModule`
|
|
15
15
|
- source_files:
|
|
16
16
|
- playCommand.js
|
|
17
|
+
- playCommandHandlers.js
|
|
18
|
+
- playCommandCore.js
|
|
19
|
+
- playCommandMediaClient.js
|
|
20
|
+
- playCommandConstants.js
|
|
21
|
+
- playConfigRuntime.js
|
|
17
22
|
- total_commands: `2`
|
|
18
23
|
- total_enabled_commands: `2`
|
|
19
24
|
|
|
@@ -119,10 +124,10 @@ Este arquivo e destinado a agentes de IA para gerar respostas no contexto dos co
|
|
|
119
124
|
- texto do comando e argumentos
|
|
120
125
|
- contexto da mensagem (citacao e mencoes, quando existir)
|
|
121
126
|
- link ou termo de busca enviado no comando
|
|
122
|
-
- metadados de
|
|
127
|
+
- metadados de busca/download retornados pelo provedor de midia
|
|
123
128
|
- informacoes de tamanho do arquivo para validacao de limite
|
|
124
129
|
- dependencias_externas:
|
|
125
|
-
-
|
|
130
|
+
- provedor de midia local (ytmp3 via API)
|
|
126
131
|
- ffmpeg
|
|
127
132
|
- ffprobe
|
|
128
133
|
- efeitos_colaterais:
|
|
@@ -244,10 +249,10 @@ Este arquivo e destinado a agentes de IA para gerar respostas no contexto dos co
|
|
|
244
249
|
- texto do comando e argumentos
|
|
245
250
|
- contexto da mensagem (citacao e mencoes, quando existir)
|
|
246
251
|
- link ou termo de busca enviado no comando
|
|
247
|
-
- metadados de
|
|
252
|
+
- metadados de busca/download retornados pelo provedor de midia
|
|
248
253
|
- informacoes de tamanho e formato de video para validacao
|
|
249
254
|
- dependencias_externas:
|
|
250
|
-
-
|
|
255
|
+
- provedor de midia local (ytmp3 via API)
|
|
251
256
|
- ffmpeg
|
|
252
257
|
- ffprobe
|
|
253
258
|
- efeitos_colaterais:
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schema_version": "2.0.0",
|
|
3
3
|
"module": "playModule",
|
|
4
4
|
"enabled": true,
|
|
5
|
-
"source_files": ["playCommand.js"],
|
|
5
|
+
"source_files": ["playCommand.js", "playCommandHandlers.js", "playCommandCore.js", "playCommandMediaClient.js", "playCommandConstants.js", "playConfigRuntime.js"],
|
|
6
6
|
"defaults": {
|
|
7
7
|
"inheritance_mode": "deep_merge_with_command_overrides",
|
|
8
8
|
"compatibility_mode": "legacy_and_v2_fields",
|
|
@@ -62,8 +62,8 @@
|
|
|
62
62
|
"janela_ms": null,
|
|
63
63
|
"escopo": "sem_rate_limit_explicito"
|
|
64
64
|
},
|
|
65
|
-
"dependencies": ["
|
|
66
|
-
"dependencias_externas": ["
|
|
65
|
+
"dependencies": ["provedor de midia local (ytmp3 via API)", "ffmpeg", "ffprobe"],
|
|
66
|
+
"dependencias_externas": ["provedor de midia local (ytmp3 via API)", "ffmpeg", "ffprobe"],
|
|
67
67
|
"responses": {
|
|
68
68
|
"success": "Comando executado com sucesso.",
|
|
69
69
|
"usage_error": "Formato de uso inválido. Consulte metodos_de_uso.",
|
|
@@ -152,7 +152,7 @@
|
|
|
152
152
|
"permissao_necessaria": "usuario comum",
|
|
153
153
|
"limite_de_uso": "arquivo ate PLAY_MAX_MB (padrao 100 MB)",
|
|
154
154
|
"local_de_uso": ["privado", "grupo"],
|
|
155
|
-
"informacoes_coletadas": ["identificador do chat (remoteJid)", "identificador do remetente (senderJid)", "texto do comando e argumentos", "contexto da mensagem (citacao e mencoes, quando existir)", "link ou termo de busca enviado no comando", "metadados de
|
|
155
|
+
"informacoes_coletadas": ["identificador do chat (remoteJid)", "identificador do remetente (senderJid)", "texto do comando e argumentos", "contexto da mensagem (citacao e mencoes, quando existir)", "link ou termo de busca enviado no comando", "metadados de busca/download retornados pelo provedor de midia", "informacoes de tamanho do arquivo para validacao de limite"],
|
|
156
156
|
"enabled": true,
|
|
157
157
|
"categoria": "midia",
|
|
158
158
|
"subcomandos": [],
|
|
@@ -179,7 +179,7 @@
|
|
|
179
179
|
"janela_ms": null,
|
|
180
180
|
"escopo": "sem_rate_limit_explicito"
|
|
181
181
|
},
|
|
182
|
-
"dependencias_externas": ["
|
|
182
|
+
"dependencias_externas": ["provedor de midia local (ytmp3 via API)", "ffmpeg", "ffprobe"],
|
|
183
183
|
"efeitos_colaterais": ["baixa mídia temporária", "envia áudio no chat"],
|
|
184
184
|
"respostas_padrao": {
|
|
185
185
|
"sucesso": "Comando executado com sucesso.",
|
|
@@ -228,7 +228,7 @@
|
|
|
228
228
|
},
|
|
229
229
|
"permission": "usuario comum",
|
|
230
230
|
"contexts": ["privado", "grupo"],
|
|
231
|
-
"collected_data": ["identificador do chat (remoteJid)", "identificador do remetente (senderJid)", "texto do comando e argumentos", "contexto da mensagem (citacao e mencoes, quando existir)", "link ou termo de busca enviado no comando", "metadados de
|
|
231
|
+
"collected_data": ["identificador do chat (remoteJid)", "identificador do remetente (senderJid)", "texto do comando e argumentos", "contexto da mensagem (citacao e mencoes, quando existir)", "link ou termo de busca enviado no comando", "metadados de busca/download retornados pelo provedor de midia", "informacoes de tamanho do arquivo para validacao de limite"],
|
|
232
232
|
"requirements": {
|
|
233
233
|
"require_group": false,
|
|
234
234
|
"require_group_admin": false,
|
|
@@ -290,7 +290,7 @@
|
|
|
290
290
|
}
|
|
291
291
|
}
|
|
292
292
|
},
|
|
293
|
-
"dependencies": ["
|
|
293
|
+
"dependencies": ["provedor de midia local (ytmp3 via API)", "ffmpeg", "ffprobe"],
|
|
294
294
|
"side_effects": ["baixa mídia temporária", "envia áudio no chat"],
|
|
295
295
|
"observability": {
|
|
296
296
|
"event_name": "command.executed",
|
|
@@ -357,6 +357,35 @@
|
|
|
357
357
|
"schema": "legacy_v1_and_v2",
|
|
358
358
|
"legacy_name": "tocar",
|
|
359
359
|
"legacy_fields_present": ["descricao", "metodos_de_uso", "permissao_necessaria", "local_de_uso", "informacoes_coletadas", "argumentos", "pre_condicoes", "dependencias_externas", "efeitos_colaterais", "observabilidade", "privacidade", "acesso", "limite_uso_por_plano"]
|
|
360
|
+
},
|
|
361
|
+
"user_experience": {
|
|
362
|
+
"resumo_usuario": "Tocar reproduz/gera áudio a partir de um link do YouTube ou de um termo de busca. Disponível para todos (não requer premium).",
|
|
363
|
+
"quando_usar": ["Quando quiser ouvir o áudio de um vídeo do YouTube sem abrir o navegador.", "Quando você tem um link do YouTube e quer ouvir rapidamente no chat.", "Quando prefere buscar por um termo e ouvir o áudio resultante."],
|
|
364
|
+
"exemplos_reais": [
|
|
365
|
+
{
|
|
366
|
+
"situacao": "Usuário tem o link de um vídeo e quer ouvir o áudio.",
|
|
367
|
+
"comando": "<prefix>tocar https://youtube.com/watch?v=EXEMPLO",
|
|
368
|
+
"resposta_esperada": "Comando executado com sucesso.",
|
|
369
|
+
"variacao": "<prefix>tocar https://youtu.be/EXEMPLO."
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
"situacao": "Usuário quer ouvir áudio a partir de um termo de busca.",
|
|
373
|
+
"comando": "<prefix>tocar melhor trilha sonora de cinema",
|
|
374
|
+
"resposta_esperada": "Comando executado com sucesso.",
|
|
375
|
+
"variacao": "<prefix>tocar <termo de busca>."
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
"situacao": "Usuário envia o comando sem argumento ou com formato incorreto.",
|
|
379
|
+
"comando": "<prefix>tocar",
|
|
380
|
+
"resposta_esperada": "Formato de uso inválido. Consulte metodos_de_uso.",
|
|
381
|
+
"variacao": "<prefix>tocar <link>."
|
|
382
|
+
}
|
|
383
|
+
],
|
|
384
|
+
"resposta_esperada": ["Comando executado com sucesso.", "Formato de uso inválido. Consulte metodos_de_uso.", "Permissão insuficiente para executar este comando."],
|
|
385
|
+
"erros_comuns_usuario": ["Não fornecer argumento (link ou termo de busca).", "Link não é de vídeo YouTube válido.", "Formato do comando não segue <prefix>tocar <link> ou <prefix>tocar <termo>.", "Não estar logado com a conta Google quando solicitado.", "Conectividade ruim ou serviço temporariamente indisponível."],
|
|
386
|
+
"passos_se_der_erro": ["Verifique se o comando usa <prefix>tocar <link> ou <prefix>tocar <termo>.", "Copie o link direto do YouTube ou revise o termo de busca.", "Tente novamente em instantes.", "Caso persista, confirme que a conta Google está disponível e tente novamente.", "Se ainda falhar, informe o contexto (link ou termo usado) para suporte."],
|
|
387
|
+
"resumo_usuario_origem": "auto_ia_assistida",
|
|
388
|
+
"resumo_usuario_revisao_pendente": true
|
|
360
389
|
}
|
|
361
390
|
},
|
|
362
391
|
{
|
|
@@ -370,7 +399,7 @@
|
|
|
370
399
|
"permissao_necessaria": "usuario comum",
|
|
371
400
|
"limite_de_uso": "arquivo ate PLAY_MAX_MB (padrao 100 MB)",
|
|
372
401
|
"local_de_uso": ["privado", "grupo"],
|
|
373
|
-
"informacoes_coletadas": ["identificador do chat (remoteJid)", "identificador do remetente (senderJid)", "texto do comando e argumentos", "contexto da mensagem (citacao e mencoes, quando existir)", "link ou termo de busca enviado no comando", "metadados de
|
|
402
|
+
"informacoes_coletadas": ["identificador do chat (remoteJid)", "identificador do remetente (senderJid)", "texto do comando e argumentos", "contexto da mensagem (citacao e mencoes, quando existir)", "link ou termo de busca enviado no comando", "metadados de busca/download retornados pelo provedor de midia", "informacoes de tamanho e formato de video para validacao"],
|
|
374
403
|
"enabled": true,
|
|
375
404
|
"categoria": "midia",
|
|
376
405
|
"subcomandos": [],
|
|
@@ -397,7 +426,7 @@
|
|
|
397
426
|
"janela_ms": null,
|
|
398
427
|
"escopo": "sem_rate_limit_explicito"
|
|
399
428
|
},
|
|
400
|
-
"dependencias_externas": ["
|
|
429
|
+
"dependencias_externas": ["provedor de midia local (ytmp3 via API)", "ffmpeg", "ffprobe"],
|
|
401
430
|
"efeitos_colaterais": ["baixa mídia temporária", "envia vídeo no chat"],
|
|
402
431
|
"respostas_padrao": {
|
|
403
432
|
"sucesso": "Comando executado com sucesso.",
|
|
@@ -446,7 +475,7 @@
|
|
|
446
475
|
},
|
|
447
476
|
"permission": "usuario comum",
|
|
448
477
|
"contexts": ["privado", "grupo"],
|
|
449
|
-
"collected_data": ["identificador do chat (remoteJid)", "identificador do remetente (senderJid)", "texto do comando e argumentos", "contexto da mensagem (citacao e mencoes, quando existir)", "link ou termo de busca enviado no comando", "metadados de
|
|
478
|
+
"collected_data": ["identificador do chat (remoteJid)", "identificador do remetente (senderJid)", "texto do comando e argumentos", "contexto da mensagem (citacao e mencoes, quando existir)", "link ou termo de busca enviado no comando", "metadados de busca/download retornados pelo provedor de midia", "informacoes de tamanho e formato de video para validacao"],
|
|
450
479
|
"requirements": {
|
|
451
480
|
"require_group": false,
|
|
452
481
|
"require_group_admin": false,
|
|
@@ -508,7 +537,7 @@
|
|
|
508
537
|
}
|
|
509
538
|
}
|
|
510
539
|
},
|
|
511
|
-
"dependencies": ["
|
|
540
|
+
"dependencies": ["provedor de midia local (ytmp3 via API)", "ffmpeg", "ffprobe"],
|
|
512
541
|
"side_effects": ["baixa mídia temporária", "envia vídeo no chat"],
|
|
513
542
|
"observability": {
|
|
514
543
|
"event_name": "command.executed",
|
|
@@ -575,10 +604,109 @@
|
|
|
575
604
|
"schema": "legacy_v1_and_v2",
|
|
576
605
|
"legacy_name": "tocarvideo",
|
|
577
606
|
"legacy_fields_present": ["descricao", "metodos_de_uso", "permissao_necessaria", "local_de_uso", "informacoes_coletadas", "argumentos", "pre_condicoes", "dependencias_externas", "efeitos_colaterais", "observabilidade", "privacidade", "acesso", "limite_uso_por_plano"]
|
|
607
|
+
},
|
|
608
|
+
"user_experience": {
|
|
609
|
+
"resumo_usuario": "Baixe ou reproduza vídeos do YouTube a partir de um link ou de termos de busca. Requer login Google e assinatura Premium. O conteúdo fica disponível no chat.",
|
|
610
|
+
"quando_usar": ["Quando você tem um link do YouTube que quer baixar para assistir no chat.", "Quando prefere buscar um vídeo pelo título/termo de busca em vez de colar o link.", "Antes de usar, confirme que você tem acesso à assinatura Premium."],
|
|
611
|
+
"exemplos_reais": [
|
|
612
|
+
{
|
|
613
|
+
"situacao": "Baixar vídeo a partir de um link do YouTube.",
|
|
614
|
+
"comando": "<prefix>tocarvideo https://www.youtube.com/watch?v=dQw4w9WgXcQ",
|
|
615
|
+
"resposta_esperada": "Comando executado com sucesso.",
|
|
616
|
+
"variacao": "uso com link direto (alias: playvid)."
|
|
617
|
+
},
|
|
618
|
+
{
|
|
619
|
+
"situacao": "Buscar vídeo pelo termo de busca.",
|
|
620
|
+
"comando": "<prefix>tocarvideo melhor tutorial de edição de fotos",
|
|
621
|
+
"resposta_esperada": "Comando executado com sucesso.",
|
|
622
|
+
"variacao": "uso com termo de busca."
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
"situacao": "Tentar usar sem Premium.",
|
|
626
|
+
"comando": "<prefix>tocarvideo https://www.youtube.com/watch?v=dQw4w9WgXcQ",
|
|
627
|
+
"resposta_esperada": "Permissão insuficiente para executar este comando.",
|
|
628
|
+
"variacao": "sem assinatura Premium."
|
|
629
|
+
}
|
|
630
|
+
],
|
|
631
|
+
"resposta_esperada": ["Comando executado com sucesso.", "Formato de uso inválido. Consulte metodos_de_uso.", "Permissão insuficiente para executar este comando."],
|
|
632
|
+
"erros_comuns_usuario": ["Esquecer de incluir o link ou termo de busca.", "Enviar link que não é do YouTube.", "Não estar logado com uma conta Google.", "Tentar usar o recurso sem a assinatura Premium."],
|
|
633
|
+
"passos_se_der_erro": ["Verifique se você está usando o formato correto: <prefix>tocarvideo <link_do_youtube> ou <prefix>tocarvideo <termo>.", "Certifique-se de estar logado com uma conta Google válida.", "Confirme que você possui assinatura Premium ativa para este comando.", "Se o erro persistir, tente novamente após confirmar as informações ou entre em contato com o suporte com a captura de tela do erro."],
|
|
634
|
+
"resumo_usuario_origem": "auto_ia_assistida",
|
|
635
|
+
"resumo_usuario_revisao_pendente": true
|
|
578
636
|
}
|
|
579
637
|
}
|
|
580
638
|
],
|
|
639
|
+
"limites_operacionais": {
|
|
640
|
+
"max_search_results": 5,
|
|
641
|
+
"search_cache_ttl_ms": 60000,
|
|
642
|
+
"max_search_cache_entries": 500,
|
|
643
|
+
"max_redirects": 2,
|
|
644
|
+
"max_concurrent_jobs": 2,
|
|
645
|
+
"max_error_body_bytes": 65536,
|
|
646
|
+
"max_meta_body_chars": 512,
|
|
647
|
+
"retry_backoff_base_ms": 200,
|
|
648
|
+
"search_retry_count": 1,
|
|
649
|
+
"thumbnail_retry_count": 1,
|
|
650
|
+
"thumbnail_timeout_ms": 15000,
|
|
651
|
+
"max_thumb_bytes": 5242880,
|
|
652
|
+
"admin_alert_dedupe_window_ms": 120000
|
|
653
|
+
},
|
|
654
|
+
"opcoes_execucao": {
|
|
655
|
+
"media_provider_args": [],
|
|
656
|
+
"estrategias_formato": {
|
|
657
|
+
"audio": ["bestaudio/best", "best"],
|
|
658
|
+
"video": ["bv*[ext=mp4]+ba[ext=m4a]/b[ext=mp4]/best", "bestvideo*+bestaudio/best", "best"],
|
|
659
|
+
"audio_extract": {
|
|
660
|
+
"enabled": true,
|
|
661
|
+
"format": "mp3",
|
|
662
|
+
"quality": "0"
|
|
663
|
+
},
|
|
664
|
+
"video_merge_output_format": "mp4"
|
|
665
|
+
}
|
|
666
|
+
},
|
|
581
667
|
"textos": {
|
|
582
|
-
"usage_header": ""
|
|
668
|
+
"usage_header": "",
|
|
669
|
+
"error_prefix": "❌ Erro: ",
|
|
670
|
+
"generic_error": "Erro inesperado ao processar sua solicitação.",
|
|
671
|
+
"user_error_timeout": "A operação demorou mais que o esperado. Tente novamente.",
|
|
672
|
+
"user_error_technical_generic": "Não foi possível processar sua solicitação agora. Tente novamente em instantes.",
|
|
673
|
+
"admin_error_title": "Erro no módulo play (diagnóstico).",
|
|
674
|
+
"wait_audio": "⏳ Processando sua mídia...",
|
|
675
|
+
"wait_video": "⏳ Processando sua mídia...",
|
|
676
|
+
"ready_title_audio": "🎵 Áudio pronto!",
|
|
677
|
+
"ready_title_video": "🎬 Vídeo pronto!",
|
|
678
|
+
"video_fallback_to_audio": "⚠️ Este link retornou somente áudio. Enviando no formato de áudio.",
|
|
679
|
+
"anti_bot_with_cookies": "YouTube solicitou verificação anti-bot. Atualize o arquivo .secrets/cookies.txt e tente novamente.",
|
|
680
|
+
"anti_bot_with_browser_profile": "YouTube solicitou verificação anti-bot no provedor de mídia. Verifique suas credenciais e tente novamente.",
|
|
681
|
+
"anti_bot_without_cookies": "YouTube solicitou verificação anti-bot no provedor de mídia. Tente novamente em alguns minutos.",
|
|
682
|
+
"usage_fallback_audio": "🎵 Uso: <prefix>play <link do YouTube ou termo de busca>",
|
|
683
|
+
"usage_fallback_video": "🎬 Uso: <prefix>playvid <link do YouTube ou termo de busca>",
|
|
684
|
+
"invalid_media_type": "Tipo de mídia inválido.",
|
|
685
|
+
"provider_error_generic": "Falha ao processar mídia no provedor.",
|
|
686
|
+
"provider_timeout_generic": "Timeout ao processar mídia no provedor.",
|
|
687
|
+
"binary_exec_failed": "Falha ao executar <command>.",
|
|
688
|
+
"search_invalid_input": "Você precisa informar um link do YouTube ou termo de busca.",
|
|
689
|
+
"search_not_found": "Nenhum resultado encontrado para a busca.",
|
|
690
|
+
"search_timeout": "Timeout ao buscar metadados do vídeo.",
|
|
691
|
+
"search_failed": "Não foi possível buscar o vídeo agora.",
|
|
692
|
+
"video_unavailable": "Não foi possível acessar este vídeo agora. Tente outro link.",
|
|
693
|
+
"ffmpeg_not_found": "ffmpeg não encontrado no servidor para processar esta mídia.",
|
|
694
|
+
"download_timeout": "Timeout ao baixar o arquivo.",
|
|
695
|
+
"download_failed": "Falha ao baixar o arquivo localmente.",
|
|
696
|
+
"download_file_not_found": "Não foi possível localizar o arquivo baixado.",
|
|
697
|
+
"download_invalid_media": "Falha ao baixar mídia válida.",
|
|
698
|
+
"media_too_big": "O arquivo excede o limite permitido de <max_mb> MB.",
|
|
699
|
+
"probe_timeout": "Timeout ao analisar o vídeo recebido.",
|
|
700
|
+
"probe_failed": "Falha ao validar o vídeo recebido.",
|
|
701
|
+
"transcode_timeout": "Timeout ao normalizar o vídeo para envio.",
|
|
702
|
+
"transcode_failed": "Falha ao converter o vídeo para um formato compatível.",
|
|
703
|
+
"transcode_output_invalid": "Falha ao gerar vídeo compatível para envio.",
|
|
704
|
+
"video_without_streams": "Não foi possível enviar como vídeo: a mídia não possui faixa de vídeo nem áudio.",
|
|
705
|
+
"thumbnail_timeout": "Timeout ao baixar a thumbnail.",
|
|
706
|
+
"thumbnail_failed": "Falha ao baixar a thumbnail.",
|
|
707
|
+
"thumbnail_too_big": "Thumbnail excede o limite permitido.",
|
|
708
|
+
"http_timeout": "Timeout na requisição HTTP.",
|
|
709
|
+
"http_failed": "Falha na requisição HTTP.",
|
|
710
|
+
"content_too_big": "Conteúdo excede o limite permitido."
|
|
583
711
|
}
|
|
584
712
|
}
|