@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.
Files changed (261) hide show
  1. package/.env.example +58 -13
  2. package/.github/workflows/ci.yml +5 -5
  3. package/.github/workflows/codeql.yml +1 -1
  4. package/.github/workflows/db-migration-check.yml +2 -2
  5. package/.github/workflows/dependency-review.yml +1 -1
  6. package/.github/workflows/deploy.yml +2 -2
  7. package/.github/workflows/release.yml +2 -2
  8. package/.github/workflows/security-attest-provenance.yml +2 -2
  9. package/.github/workflows/security-gitleaks.yml +13 -4
  10. package/.github/workflows/security-runner-hardening.yml +2 -2
  11. package/.github/workflows/security-scorecard.yml +1 -1
  12. package/.github/workflows/security-zap-baseline.yml +1 -1
  13. package/.github/workflows/security-zap-full-scan.yml +2 -1
  14. package/.github/workflows/security-zizmor.yml +1 -1
  15. package/.github/workflows/wiki-sync.yml +1 -1
  16. package/.gitleaksignore +9 -0
  17. package/CODE_OF_CONDUCT.md +2 -2
  18. package/GEMINI.md +64 -0
  19. package/README.md +52 -82
  20. package/SECURITY.md +1 -1
  21. package/app/config/index.js +2 -0
  22. package/app/configParts/adminIdentity.js +5 -5
  23. package/app/configParts/baileysConfig.js +230 -58
  24. package/app/configParts/groupUtils.js +5 -0
  25. package/app/configParts/messagePersistenceService.js +145 -4
  26. package/app/configParts/sessionConfig.js +157 -0
  27. package/app/connection/baileysCompatibility.test.js +1 -1
  28. package/app/connection/groupOwnerWriteStateResolver.js +109 -0
  29. package/app/connection/socketController.js +660 -158
  30. package/app/connection/socketController.multiSession.test.js +108 -0
  31. package/app/controllers/messageController.js +1 -1
  32. package/app/controllers/messagePipeline/commandMiddleware.js +12 -10
  33. package/app/controllers/messagePipeline/conversationMiddleware.js +2 -1
  34. package/app/controllers/messagePipeline/messagePipelineMiddlewares.test.js +104 -0
  35. package/app/controllers/messagePipeline/preProcessingMiddlewares.js +80 -2
  36. package/app/controllers/messageProcessingPipeline.js +93 -13
  37. package/app/controllers/messageProcessingPipeline.test.js +200 -0
  38. package/app/modules/adminModule/AGENT.md +1 -1
  39. package/app/modules/adminModule/commandConfig.json +3318 -1347
  40. package/app/modules/adminModule/groupCommandHandlers.js +858 -15
  41. package/app/modules/adminModule/groupCommandHandlers.test.js +378 -11
  42. package/app/modules/adminModule/groupWarningRepository.js +152 -0
  43. package/app/modules/aiModule/AGENT.md +47 -30
  44. package/app/modules/aiModule/aiConfigRuntime.js +1 -0
  45. package/app/modules/aiModule/catCommand.js +135 -27
  46. package/app/modules/aiModule/commandConfig.json +114 -28
  47. package/app/modules/analyticsModule/messageAnalysisEventRepository.js +54 -6
  48. package/app/modules/gameModule/AGENT.md +1 -1
  49. package/app/modules/gameModule/commandConfig.json +29 -0
  50. package/app/modules/menuModule/AGENT.md +1 -1
  51. package/app/modules/menuModule/commandConfig.json +45 -10
  52. package/app/modules/menuModule/menuCatalogService.js +190 -0
  53. package/app/modules/menuModule/menuCommandUsageRepository.js +109 -0
  54. package/app/modules/menuModule/menuDynamicService.js +511 -0
  55. package/app/modules/menuModule/menuDynamicService.test.js +141 -0
  56. package/app/modules/menuModule/menus.js +36 -5
  57. package/app/modules/playModule/AGENT.md +10 -5
  58. package/app/modules/playModule/commandConfig.json +140 -12
  59. package/app/modules/playModule/playCommand.js +1 -1417
  60. package/app/modules/playModule/playCommandConstants.js +80 -0
  61. package/app/modules/playModule/playCommandCore.js +361 -0
  62. package/app/modules/playModule/playCommandHandlers.js +41 -0
  63. package/app/modules/playModule/playCommandMediaClient.js +1872 -0
  64. package/app/modules/playModule/playConfigRuntime.js +245 -4
  65. package/app/modules/playModule/playModuleCriticalFlows.test.js +152 -0
  66. package/app/modules/quoteModule/AGENT.md +1 -1
  67. package/app/modules/quoteModule/commandConfig.json +29 -0
  68. package/app/modules/quoteModule/quoteCommand.js +3 -2
  69. package/app/modules/rpgPokemonModule/AGENT.md +1 -1
  70. package/app/modules/rpgPokemonModule/commandConfig.json +29 -0
  71. package/app/modules/rpgPokemonModule/rpgBattleCanvasRenderer.js +5 -4
  72. package/app/modules/rpgPokemonModule/rpgBattleService.test.js +2 -1
  73. package/app/modules/rpgPokemonModule/rpgPokemonDomain.js +2 -1
  74. package/app/modules/rpgPokemonModule/rpgPokemonService.js +38 -37
  75. package/app/modules/rpgPokemonModule/rpgProfileCanvasRenderer.js +4 -3
  76. package/app/modules/statsModule/AGENT.md +1 -1
  77. package/app/modules/statsModule/commandConfig.json +58 -0
  78. package/app/modules/statsModule/rankingCommon.js +5 -4
  79. package/app/modules/stickerModule/AGENT.md +1 -1
  80. package/app/modules/stickerModule/addStickerMetadata.js +4 -3
  81. package/app/modules/stickerModule/commandConfig.json +145 -0
  82. package/app/modules/stickerModule/stickerCommand.js +1 -1
  83. package/app/modules/stickerPackModule/AGENT.md +1 -1
  84. package/app/modules/stickerPackModule/autoPackCollectorService.js +5 -1
  85. package/app/modules/stickerPackModule/commandConfig.json +29 -0
  86. package/app/modules/stickerPackModule/semanticThemeClusterService.js +7 -6
  87. package/app/modules/stickerPackModule/stickerAutoPackByTagsRuntime.js +10 -9
  88. package/app/modules/stickerPackModule/stickerClassificationBackgroundRuntime.js +9 -8
  89. package/app/modules/stickerPackModule/stickerDomainEventConsumerRuntime.js +3 -2
  90. package/app/modules/stickerPackModule/stickerMarketplaceDriftService.js +2 -1
  91. package/app/modules/stickerPackModule/stickerPackCommandHandlers.js +80 -58
  92. package/app/modules/stickerPackModule/stickerPackMarketplaceService.js +2 -1
  93. package/app/modules/stickerPackModule/stickerPackRepository.js +2 -1
  94. package/app/modules/stickerPackModule/stickerPackScoreSnapshotRuntime.js +5 -4
  95. package/app/modules/stickerPackModule/stickerPackService.js +13 -6
  96. package/app/modules/stickerPackModule/stickerStorageService.js +3 -2
  97. package/app/modules/stickerPackModule/stickerWorkerPipelineRuntime.js +2 -1
  98. package/app/modules/systemMetricsModule/AGENT.md +1 -1
  99. package/app/modules/systemMetricsModule/commandConfig.json +29 -0
  100. package/app/modules/systemMetricsModule/pingCommand.js +6 -5
  101. package/app/modules/tiktokModule/AGENT.md +1 -1
  102. package/app/modules/tiktokModule/commandConfig.json +29 -0
  103. package/app/modules/tiktokModule/tiktokCommand.js +2 -1
  104. package/app/modules/userModule/AGENT.md +1 -1
  105. package/app/modules/userModule/commandConfig.json +29 -0
  106. package/app/modules/userModule/userCommand.js +72 -23
  107. package/app/modules/waifuPicsModule/AGENT.md +57 -27
  108. package/app/modules/waifuPicsModule/commandConfig.json +87 -0
  109. package/app/modules/waifuPicsModule/waifuPicsCommand.js +3 -2
  110. package/app/observability/metrics.js +136 -0
  111. package/app/services/ai/commandConfigEnrichmentService.js +229 -47
  112. package/app/services/ai/conversationRouterService.js +4 -3
  113. package/app/services/ai/geminiService.js +132 -7
  114. package/app/services/ai/geminiService.test.js +59 -2
  115. package/app/services/ai/globalModuleAiHelpService.js +3 -2
  116. package/app/services/ai/messageCommandExecutionService.js +2 -1
  117. package/app/services/ai/moduleAiHelpCoreService.js +45 -14
  118. package/app/services/ai/moduleToolExecutorService.js +3 -2
  119. package/app/services/ai/moduleToolRegistryService.js +2 -1
  120. package/app/services/ai/toolCandidateSelectorService.js +6 -5
  121. package/app/services/auth/googleWebLinkService.js +3 -2
  122. package/app/services/auth/whatsappLoginLinkService.js +3 -2
  123. package/app/services/external/pokeApiService.js +4 -3
  124. package/app/services/group/groupMetadataService.js +24 -1
  125. package/app/services/infra/dbWriteQueue.js +57 -26
  126. package/app/services/infra/featureFlagService.js +2 -1
  127. package/app/services/messaging/captchaService.js +3 -2
  128. package/app/services/messaging/newsBroadcastService.js +846 -29
  129. package/app/services/multiSession/assignmentBalancerService.js +457 -0
  130. package/app/services/multiSession/groupOwnershipRepository.js +381 -0
  131. package/app/services/multiSession/groupOwnershipService.js +890 -0
  132. package/app/services/multiSession/groupOwnershipService.test.js +309 -0
  133. package/app/services/multiSession/sessionRegistryService.js +293 -0
  134. package/app/services/sticker/stickerFocusService.js +11 -10
  135. package/app/store/aiPromptStore.js +36 -19
  136. package/app/store/conversationSessionStore.js +7 -6
  137. package/app/store/groupConfigStore.js +41 -5
  138. package/app/store/premiumUserStore.js +21 -7
  139. package/app/utils/antiLink/antiLinkModule.js +352 -16
  140. package/app/workers/aiHelperContinuousLearningWorker.js +512 -0
  141. package/app/workers/aiLearningWorker.js +6 -5
  142. package/app/workers/commandConfigEnrichmentWorker.js +4 -3
  143. package/database/index.js +14 -8
  144. package/database/migrations/20260307_d0_hardening_down.sql +1 -1
  145. package/database/migrations/20260314_d7_canonical_sender_down.sql +1 -1
  146. package/database/migrations/20260406_d30_security_analytics_down.sql +1 -1
  147. package/database/migrations/20260411_d35_group_community_metadata_down.sql +59 -0
  148. package/database/migrations/20260411_d35_group_community_metadata_up.sql +62 -0
  149. package/database/migrations/20260412_d36_system_config_tables_down.sql +32 -0
  150. package/database/migrations/20260412_d36_system_config_tables_up.sql +66 -0
  151. package/database/migrations/20260413_d37_group_user_warnings_down.sql +11 -0
  152. package/database/migrations/20260413_d37_group_user_warnings_up.sql +24 -0
  153. package/database/migrations/20260414_d38_multi_session_foundation_down.sql +72 -0
  154. package/database/migrations/20260414_d38_multi_session_foundation_up.sql +125 -0
  155. package/database/migrations/20260414_d39_multi_session_cutover_down.sql +103 -0
  156. package/database/migrations/20260414_d39_multi_session_cutover_up.sql +83 -0
  157. package/database/schema.sql +102 -1
  158. package/docker-compose.yml +4 -1
  159. package/docs/compliance/acceptable-use-policy-2026-03-07.md +1 -1
  160. package/docs/compliance/dpa-b2b-standard-2026-03-07.md +1 -1
  161. package/docs/compliance/privacy-policy-2026-03-07.md +4 -4
  162. package/docs/security/dsar-lgpd-runbook-2026-03-07.md +1 -1
  163. package/docs/security/incident-response-lgpd-anpd-runbook-2026-03-07.md +1 -1
  164. package/docs/security/network-hardening-runbook-2026-03-07.md +53 -0
  165. package/docs/security/omnizap-static-security-headers.conf +25 -0
  166. package/docs/wiki/Home.md +1 -1
  167. package/ecosystem.prod.config.cjs +32 -12
  168. package/index.js +57 -23
  169. package/observability/alert-rules.yml +20 -0
  170. package/observability/grafana/dashboards/omnizap-system-admin.json +229 -0
  171. package/observability/mysql-setup.sql +4 -4
  172. package/observability/system-admin-observability.md +26 -0
  173. package/package.json +20 -6
  174. package/public/apple-touch-icon.png +0 -0
  175. package/public/comandos/commands-catalog.json +2853 -3326
  176. package/public/favicon-16x16.png +0 -0
  177. package/public/favicon-32x32.png +0 -0
  178. package/public/favicon.ico +0 -0
  179. package/public/js/apps/apiDocsApp.js +3 -2
  180. package/public/js/apps/commandsReactApp.js +280 -99
  181. package/public/js/apps/createPackApp.js +11 -10
  182. package/public/js/apps/homeReactApp.js +181 -130
  183. package/public/js/apps/loginReactApp.js +1 -1
  184. package/public/js/apps/stickersApp.js +263 -110
  185. package/public/js/apps/termsReactApp.js +73 -24
  186. package/public/js/apps/userApp.js +4 -3
  187. package/public/js/apps/userPasswordResetReactApp.js +406 -0
  188. package/public/js/apps/userReactApp.js +355 -280
  189. package/public/js/apps/userSystemAdmReactApp.js +1506 -0
  190. package/public/pages/api-docs.html +1 -1
  191. package/public/pages/aup.html +2 -2
  192. package/public/pages/dpa.html +3 -3
  193. package/public/pages/licenca.html +4 -4
  194. package/public/pages/login.html +1 -1
  195. package/public/pages/notice-and-takedown.html +2 -2
  196. package/public/pages/politica-de-privacidade.html +6 -6
  197. package/public/pages/seo-bot-whatsapp-para-grupo.html +3 -3
  198. package/public/pages/seo-bot-whatsapp-sem-programar.html +3 -3
  199. package/public/pages/seo-como-automatizar-avisos-no-whatsapp.html +3 -3
  200. package/public/pages/seo-como-criar-comandos-whatsapp.html +3 -3
  201. package/public/pages/seo-como-evitar-spam-no-whatsapp.html +3 -3
  202. package/public/pages/seo-como-moderar-grupo-whatsapp.html +3 -3
  203. package/public/pages/seo-como-organizar-comunidade-whatsapp.html +3 -3
  204. package/public/pages/seo-melhor-bot-whatsapp-para-grupos.html +3 -3
  205. package/public/pages/stickers-admin.html +1 -1
  206. package/public/pages/stickers-create.html +1 -1
  207. package/public/pages/stickers.html +6 -6
  208. package/public/pages/suboperadores.html +2 -2
  209. package/public/pages/termos-de-uso-texto-integral.html +6 -6
  210. package/public/pages/termos-de-uso.html +3 -3
  211. package/public/pages/user-password-reset.html +4 -5
  212. package/public/pages/user-systemadm.html +9 -463
  213. package/public/pages/user.html +2 -2
  214. package/scripts/clear-whatsapp-session.sh +123 -0
  215. package/scripts/core-ai-mode.mjs +163 -0
  216. package/scripts/deploy.sh +11 -1
  217. package/scripts/email-broadcast-terms-update.mjs +2 -1
  218. package/scripts/enrich-command-config-ux-openai.mjs +492 -0
  219. package/scripts/generate-commands-catalog.mjs +166 -2
  220. package/scripts/generate-module-agents.mjs +2 -1
  221. package/scripts/generate-seo-satellite-pages.mjs +5 -4
  222. package/scripts/github-deploy-notify.mjs +2 -1
  223. package/scripts/github-release-notify.mjs +25 -10
  224. package/scripts/new-whatsapp-session.sh +317 -0
  225. package/scripts/release.sh +2 -19
  226. package/scripts/security-smoketest.mjs +6 -5
  227. package/scripts/security-web-surface-check.mjs +218 -0
  228. package/scripts/sticker-catalog-loadtest.mjs +5 -4
  229. package/server/auth/googleWebAuth/googleWebAuthService.js +8 -7
  230. package/server/auth/jwt/webJwtService.js +1 -1
  231. package/server/auth/stickerCatalogAuthContext.js +2 -1
  232. package/server/auth/termsAcceptance/termsAcceptanceHandler.js +2 -1
  233. package/server/auth/userPassword/userPasswordAuthService.js +2 -1
  234. package/server/auth/userPassword/userPasswordRecoveryService.js +4 -3
  235. package/server/auth/webAccount/webAccountHandlers.js +9 -10
  236. package/server/controllers/admin/adminPanelHandlers.js +267 -16
  237. package/server/controllers/admin/systemAdminController.js +267 -0
  238. package/server/controllers/seo/stickerCatalogSeoContext.js +10 -9
  239. package/server/controllers/sticker/nonCatalogHandlers.js +2 -1
  240. package/server/controllers/sticker/stickerCatalogController.js +23 -36
  241. package/server/controllers/system/contactController.js +9 -17
  242. package/server/controllers/system/githubController.js +3 -2
  243. package/server/controllers/system/stickerCatalogSystemContext.js +41 -19
  244. package/server/controllers/system/systemController.js +254 -1
  245. package/server/controllers/system/systemMetricsController.js +2 -1
  246. package/server/controllers/userController.js +6 -0
  247. package/server/email/emailTemplateService.js +5 -3
  248. package/server/http/httpServer.js +11 -6
  249. package/server/middleware/rateLimit.js +2 -1
  250. package/server/middleware/securityHeaders.js +20 -1
  251. package/server/routes/admin/systemAdminRouter.js +6 -0
  252. package/server/routes/indexRouter.js +30 -6
  253. package/server/routes/observability/grafanaProxyRouter.js +254 -0
  254. package/server/routes/static/staticPageRouter.js +27 -1
  255. package/server/utils/publicContact.js +31 -0
  256. package/utils/time/timeModule.js +135 -0
  257. package/utils/time/timeModule.test.js +65 -0
  258. package/utils/whatsapp/contactEnv.js +39 -0
  259. package/vite.config.mjs +7 -1
  260. package/public/assets/images/brand-icon-192.png +0 -0
  261. 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.error('IMAGE_MENU environment variable not set.');
17
- await sendAndStore(sock, remoteJid, { text: 'Ocorreu um erro ao carregar o menu.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
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: 'Ocorreu um erro ao carregar a imagem do menu.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
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-11T02:35:17.177Z`
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 fila/download retornados pelo servico de midia
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
- - serviço YTDLS/Downloader
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 fila/download retornados pelo servico de midia
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
- - serviço YTDLS/Downloader
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": ["serviço YTDLS/Downloader", "ffmpeg", "ffprobe"],
66
- "dependencias_externas": ["serviço YTDLS/Downloader", "ffmpeg", "ffprobe"],
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 fila/download retornados pelo servico de midia", "informacoes de tamanho do arquivo para validacao de limite"],
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": ["serviço YTDLS/Downloader", "ffmpeg", "ffprobe"],
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 fila/download retornados pelo servico de midia", "informacoes de tamanho do arquivo para validacao de limite"],
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": ["serviço YTDLS/Downloader", "ffmpeg", "ffprobe"],
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 fila/download retornados pelo servico de midia", "informacoes de tamanho e formato de video para validacao"],
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": ["serviço YTDLS/Downloader", "ffmpeg", "ffprobe"],
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 fila/download retornados pelo servico de midia", "informacoes de tamanho e formato de video para validacao"],
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": ["serviço YTDLS/Downloader", "ffmpeg", "ffprobe"],
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
  }