@omnizap-system/omnizap 2.5.12

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 (425) hide show
  1. package/.clusterfuzzlite/Dockerfile +10 -0
  2. package/.env.example +907 -0
  3. package/.github/codeql/codeql-config.yml +10 -0
  4. package/.github/dependabot.yml +35 -0
  5. package/.github/workflows/ci.yml +73 -0
  6. package/.github/workflows/codeql.yml +106 -0
  7. package/.github/workflows/db-migration-check.yml +98 -0
  8. package/.github/workflows/dependency-review.yml +22 -0
  9. package/.github/workflows/deploy.yml +95 -0
  10. package/.github/workflows/release.yml +106 -0
  11. package/.github/workflows/security-attest-provenance.yml +51 -0
  12. package/.github/workflows/security-gitleaks.yml +34 -0
  13. package/.github/workflows/security-runner-hardening.yml +31 -0
  14. package/.github/workflows/security-scorecard.yml +44 -0
  15. package/.github/workflows/security-zap-baseline.yml +44 -0
  16. package/.github/workflows/security-zap-full-scan.yml +43 -0
  17. package/.github/workflows/security-zizmor.yml +36 -0
  18. package/.github/workflows/wiki-sync.yml +44 -0
  19. package/.gitleaks.toml +15 -0
  20. package/.prettierrc +34 -0
  21. package/CODE_OF_CONDUCT.md +114 -0
  22. package/LICENSE +56 -0
  23. package/README.md +110 -0
  24. package/SECURITY.md +110 -0
  25. package/app/config/index.js +4 -0
  26. package/app/configParts/adminIdentity.js +92 -0
  27. package/app/configParts/baileysConfig.js +1818 -0
  28. package/app/configParts/groupUtils.js +692 -0
  29. package/app/configParts/loggerConfig.js +394 -0
  30. package/app/configParts/messagePersistenceService.js +305 -0
  31. package/app/connection/baileysCompatibility.test.js +40 -0
  32. package/app/connection/baileysDbAuthState.js +344 -0
  33. package/app/connection/socketController.js +2243 -0
  34. package/app/controllers/messageController.js +7 -0
  35. package/app/controllers/messagePipeline/commandMiddleware.js +146 -0
  36. package/app/controllers/messagePipeline/conversationMiddleware.js +183 -0
  37. package/app/controllers/messagePipeline/messagePipelineMiddlewares.test.js +522 -0
  38. package/app/controllers/messagePipeline/postProcessingMiddleware.js +41 -0
  39. package/app/controllers/messagePipeline/preProcessingMiddlewares.js +166 -0
  40. package/app/controllers/messageProcessingPipeline.js +699 -0
  41. package/app/modules/adminModule/AGENT.md +4056 -0
  42. package/app/modules/adminModule/adminAiHelpService.js +56 -0
  43. package/app/modules/adminModule/adminConfigRuntime.js +177 -0
  44. package/app/modules/adminModule/commandConfig.json +7122 -0
  45. package/app/modules/adminModule/groupCommandHandlers.js +1823 -0
  46. package/app/modules/adminModule/groupCommandHandlers.test.js +350 -0
  47. package/app/modules/adminModule/groupEventHandlers.js +399 -0
  48. package/app/modules/aiModule/AGENT.md +547 -0
  49. package/app/modules/aiModule/aiAiHelpService.js +14 -0
  50. package/app/modules/aiModule/aiConfigRuntime.js +135 -0
  51. package/app/modules/aiModule/catCommand.js +967 -0
  52. package/app/modules/aiModule/commandConfig.json +981 -0
  53. package/app/modules/analyticsModule/messageAnalysisEventRepository.js +83 -0
  54. package/app/modules/gameModule/AGENT.md +196 -0
  55. package/app/modules/gameModule/commandConfig.json +366 -0
  56. package/app/modules/gameModule/diceCommand.js +42 -0
  57. package/app/modules/gameModule/gameAiHelpService.js +14 -0
  58. package/app/modules/gameModule/gameConfigRuntime.js +68 -0
  59. package/app/modules/menuModule/AGENT.md +205 -0
  60. package/app/modules/menuModule/commandConfig.json +366 -0
  61. package/app/modules/menuModule/common.js +316 -0
  62. package/app/modules/menuModule/menuAiHelpService.js +14 -0
  63. package/app/modules/menuModule/menuConfigRuntime.js +68 -0
  64. package/app/modules/menuModule/menus.js +66 -0
  65. package/app/modules/playModule/AGENT.md +321 -0
  66. package/app/modules/playModule/commandConfig.json +584 -0
  67. package/app/modules/playModule/playAiHelpService.js +14 -0
  68. package/app/modules/playModule/playCommand.js +1417 -0
  69. package/app/modules/playModule/playConfigRuntime.js +68 -0
  70. package/app/modules/quoteModule/AGENT.md +199 -0
  71. package/app/modules/quoteModule/commandConfig.json +366 -0
  72. package/app/modules/quoteModule/quoteAiHelpService.js +14 -0
  73. package/app/modules/quoteModule/quoteCommand.js +842 -0
  74. package/app/modules/quoteModule/quoteConfigRuntime.js +68 -0
  75. package/app/modules/rpgPokemonModule/AGENT.md +229 -0
  76. package/app/modules/rpgPokemonModule/commandConfig.json +386 -0
  77. package/app/modules/rpgPokemonModule/rpgBattleCanvasRenderer.js +795 -0
  78. package/app/modules/rpgPokemonModule/rpgBattleService.js +2110 -0
  79. package/app/modules/rpgPokemonModule/rpgBattleService.test.js +770 -0
  80. package/app/modules/rpgPokemonModule/rpgEvolutionUtils.js +22 -0
  81. package/app/modules/rpgPokemonModule/rpgPokemonAiHelpService.js +14 -0
  82. package/app/modules/rpgPokemonModule/rpgPokemonCommand.js +174 -0
  83. package/app/modules/rpgPokemonModule/rpgPokemonConfigRuntime.js +68 -0
  84. package/app/modules/rpgPokemonModule/rpgPokemonDomain.js +192 -0
  85. package/app/modules/rpgPokemonModule/rpgPokemonDomain.test.js +93 -0
  86. package/app/modules/rpgPokemonModule/rpgPokemonEvolution.test.js +46 -0
  87. package/app/modules/rpgPokemonModule/rpgPokemonMessages.js +746 -0
  88. package/app/modules/rpgPokemonModule/rpgPokemonRepository.js +1847 -0
  89. package/app/modules/rpgPokemonModule/rpgPokemonService.js +6839 -0
  90. package/app/modules/rpgPokemonModule/rpgProfileCanvasRenderer.js +354 -0
  91. package/app/modules/statsModule/AGENT.md +320 -0
  92. package/app/modules/statsModule/commandConfig.json +540 -0
  93. package/app/modules/statsModule/globalRankingCommand.js +64 -0
  94. package/app/modules/statsModule/rankingCommand.js +41 -0
  95. package/app/modules/statsModule/rankingCommon.js +1305 -0
  96. package/app/modules/statsModule/statsAiHelpService.js +14 -0
  97. package/app/modules/statsModule/statsConfigRuntime.js +68 -0
  98. package/app/modules/stickerModule/AGENT.md +692 -0
  99. package/app/modules/stickerModule/addStickerMetadata.js +239 -0
  100. package/app/modules/stickerModule/commandConfig.json +1216 -0
  101. package/app/modules/stickerModule/convertToWebp.js +367 -0
  102. package/app/modules/stickerModule/stickerAiHelpService.js +14 -0
  103. package/app/modules/stickerModule/stickerCommand.js +446 -0
  104. package/app/modules/stickerModule/stickerConfigRuntime.js +68 -0
  105. package/app/modules/stickerModule/stickerConvertCommand.js +159 -0
  106. package/app/modules/stickerModule/stickerTextCommand.js +653 -0
  107. package/app/modules/stickerPackModule/AGENT.md +215 -0
  108. package/app/modules/stickerPackModule/autoPackCollectorRuntime.js +20 -0
  109. package/app/modules/stickerPackModule/autoPackCollectorService.js +357 -0
  110. package/app/modules/stickerPackModule/commandConfig.json +387 -0
  111. package/app/modules/stickerPackModule/domainEventOutboxRepository.js +227 -0
  112. package/app/modules/stickerPackModule/domainEvents.js +52 -0
  113. package/app/modules/stickerPackModule/semanticReclassificationEngine.js +429 -0
  114. package/app/modules/stickerPackModule/semanticReclassificationEngine.test.js +75 -0
  115. package/app/modules/stickerPackModule/semanticThemeClusterService.js +544 -0
  116. package/app/modules/stickerPackModule/stickerAssetClassificationRepository.js +400 -0
  117. package/app/modules/stickerPackModule/stickerAssetRepository.js +400 -0
  118. package/app/modules/stickerPackModule/stickerAssetReprocessQueueRepository.js +175 -0
  119. package/app/modules/stickerPackModule/stickerAutoPackByTagsRuntime.js +3702 -0
  120. package/app/modules/stickerPackModule/stickerClassificationBackgroundRuntime.js +559 -0
  121. package/app/modules/stickerPackModule/stickerClassificationService.js +557 -0
  122. package/app/modules/stickerPackModule/stickerDedicatedTaskWorkerRuntime.js +249 -0
  123. package/app/modules/stickerPackModule/stickerDomainEventBus.js +65 -0
  124. package/app/modules/stickerPackModule/stickerDomainEventConsumerRuntime.js +208 -0
  125. package/app/modules/stickerPackModule/stickerMarketplaceDriftService.js +99 -0
  126. package/app/modules/stickerPackModule/stickerObjectStorageService.js +285 -0
  127. package/app/modules/stickerPackModule/stickerPackAiHelpService.js +14 -0
  128. package/app/modules/stickerPackModule/stickerPackCommandHandlers.js +1148 -0
  129. package/app/modules/stickerPackModule/stickerPackConfigRuntime.js +68 -0
  130. package/app/modules/stickerPackModule/stickerPackEngagementRepository.js +152 -0
  131. package/app/modules/stickerPackModule/stickerPackErrors.js +30 -0
  132. package/app/modules/stickerPackModule/stickerPackInteractionEventRepository.js +101 -0
  133. package/app/modules/stickerPackModule/stickerPackItemRepository.js +432 -0
  134. package/app/modules/stickerPackModule/stickerPackMarketplaceService.js +313 -0
  135. package/app/modules/stickerPackModule/stickerPackMessageService.js +268 -0
  136. package/app/modules/stickerPackModule/stickerPackRepository.js +450 -0
  137. package/app/modules/stickerPackModule/stickerPackScoreSnapshotRepository.js +179 -0
  138. package/app/modules/stickerPackModule/stickerPackScoreSnapshotRuntime.js +271 -0
  139. package/app/modules/stickerPackModule/stickerPackService.js +733 -0
  140. package/app/modules/stickerPackModule/stickerPackServiceRuntime.js +32 -0
  141. package/app/modules/stickerPackModule/stickerPackUtils.js +107 -0
  142. package/app/modules/stickerPackModule/stickerStorageService.js +559 -0
  143. package/app/modules/stickerPackModule/stickerWorkerPipelineRuntime.js +242 -0
  144. package/app/modules/stickerPackModule/stickerWorkerTaskQueueRepository.js +242 -0
  145. package/app/modules/systemMetricsModule/AGENT.md +193 -0
  146. package/app/modules/systemMetricsModule/commandConfig.json +344 -0
  147. package/app/modules/systemMetricsModule/pingCommand.js +399 -0
  148. package/app/modules/systemMetricsModule/systemMetricsAiHelpService.js +14 -0
  149. package/app/modules/systemMetricsModule/systemMetricsConfigRuntime.js +68 -0
  150. package/app/modules/tiktokModule/AGENT.md +196 -0
  151. package/app/modules/tiktokModule/commandConfig.json +366 -0
  152. package/app/modules/tiktokModule/tiktokAiHelpService.js +14 -0
  153. package/app/modules/tiktokModule/tiktokCommand.js +716 -0
  154. package/app/modules/tiktokModule/tiktokConfigRuntime.js +68 -0
  155. package/app/modules/userModule/AGENT.md +200 -0
  156. package/app/modules/userModule/commandConfig.json +386 -0
  157. package/app/modules/userModule/userAiHelpService.js +14 -0
  158. package/app/modules/userModule/userCommand.js +1155 -0
  159. package/app/modules/userModule/userConfigRuntime.js +68 -0
  160. package/app/modules/waifuPicsModule/AGENT.md +431 -0
  161. package/app/modules/waifuPicsModule/commandConfig.json +780 -0
  162. package/app/modules/waifuPicsModule/waifuPicsAiHelpService.js +14 -0
  163. package/app/modules/waifuPicsModule/waifuPicsCommand.js +586 -0
  164. package/app/modules/waifuPicsModule/waifuPicsConfigRuntime.js +68 -0
  165. package/app/observability/metrics.js +766 -0
  166. package/app/services/ai/aiHelpResponseCacheRepository.js +280 -0
  167. package/app/services/ai/aiLearningRepository.js +400 -0
  168. package/app/services/ai/commandConfigEnrichmentRepository.js +769 -0
  169. package/app/services/ai/commandConfigEnrichmentService.js +452 -0
  170. package/app/services/ai/commandConfigValidationService.js +443 -0
  171. package/app/services/ai/commandToolBuilderService.js +192 -0
  172. package/app/services/ai/conversationRouterService.js +516 -0
  173. package/app/services/ai/geminiService.js +115 -0
  174. package/app/services/ai/geminiService.test.js +87 -0
  175. package/app/services/ai/globalModuleAiHelpService.js +1412 -0
  176. package/app/services/ai/globalToolCallingService.js +203 -0
  177. package/app/services/ai/messageCommandExecutionService.js +391 -0
  178. package/app/services/ai/moduleAiHelpCoreService.js +1099 -0
  179. package/app/services/ai/moduleAiHelpWrapperFactory.js +65 -0
  180. package/app/services/ai/moduleCommandConfigRuntimeService.js +113 -0
  181. package/app/services/ai/moduleToolExecutorService.js +464 -0
  182. package/app/services/ai/moduleToolRegistryService.js +178 -0
  183. package/app/services/ai/toolCandidateSelectorService.js +781 -0
  184. package/app/services/auth/googleWebLinkService.js +80 -0
  185. package/app/services/auth/whatsappLoginLinkService.js +230 -0
  186. package/app/services/external/pokeApiService.js +398 -0
  187. package/app/services/group/groupMetadataService.js +311 -0
  188. package/app/services/infra/dbWriteQueue.js +874 -0
  189. package/app/services/infra/featureFlagService.js +131 -0
  190. package/app/services/infra/queueUtils.js +55 -0
  191. package/app/services/messaging/captchaService.js +491 -0
  192. package/app/services/messaging/messagePersistenceService.js +1 -0
  193. package/app/services/messaging/newsBroadcastService.js +347 -0
  194. package/app/services/sticker/stickerFocusService.js +347 -0
  195. package/app/services/sticker/stickerFocusService.test.js +43 -0
  196. package/app/store/aiPromptStore.js +38 -0
  197. package/app/store/conversationSessionStore.js +131 -0
  198. package/app/store/groupConfigStore.js +58 -0
  199. package/app/store/premiumUserStore.js +54 -0
  200. package/app/utils/antiLink/antiLinkModule.js +700 -0
  201. package/app/utils/http/getImageBufferModule.js +18 -0
  202. package/app/utils/json/jsonSanitizer.js +113 -0
  203. package/app/utils/json/jsonSanitizer.test.js +40 -0
  204. package/app/utils/systemMetrics/systemMetricsModule.js +88 -0
  205. package/app/workers/aiLearningWorker.js +605 -0
  206. package/app/workers/commandConfigEnrichmentWorker.js +242 -0
  207. package/database/index.js +2075 -0
  208. package/database/init.js +151 -0
  209. package/database/migrations/.gitkeep +0 -0
  210. package/database/migrations/20260307_d0_hardening_down.sql +64 -0
  211. package/database/migrations/20260307_d0_hardening_up.sql +79 -0
  212. package/database/migrations/20260307_d1_terms_acceptance_down.sql +11 -0
  213. package/database/migrations/20260307_d1_terms_acceptance_up.sql +37 -0
  214. package/database/migrations/20260307_d2_auth_hardening_down.sql +75 -0
  215. package/database/migrations/20260307_d2_auth_hardening_up.sql +100 -0
  216. package/database/migrations/20260314_d7_canonical_sender_down.sql +53 -0
  217. package/database/migrations/20260314_d7_canonical_sender_up.sql +114 -0
  218. package/database/migrations/20260406_d30_security_analytics_down.sql +95 -0
  219. package/database/migrations/20260406_d30_security_analytics_up.sql +292 -0
  220. package/database/migrations/20260407_d31_web_google_session_token_hardening_down.sql +2 -0
  221. package/database/migrations/20260407_d31_web_google_session_token_hardening_up.sql +17 -0
  222. package/database/migrations/20260408_d32_ai_help_response_cache_down.sql +1 -0
  223. package/database/migrations/20260408_d32_ai_help_response_cache_up.sql +22 -0
  224. package/database/migrations/20260409_d33_ai_learning_tables_down.sql +4 -0
  225. package/database/migrations/20260409_d33_ai_learning_tables_up.sql +52 -0
  226. package/database/migrations/20260410_d34_command_config_enrichment_down.sql +3 -0
  227. package/database/migrations/20260410_d34_command_config_enrichment_up.sql +48 -0
  228. package/database/schema.sql +1186 -0
  229. package/docker-compose.yml +104 -0
  230. package/docs/audits/stickerCatalogController-out-of-scope.md +103 -0
  231. package/docs/audits/stickerCatalogController-symbols.md +58 -0
  232. package/docs/compliance/acceptable-use-policy-2026-03-07.md +35 -0
  233. package/docs/compliance/dpa-b2b-standard-2026-03-07.md +80 -0
  234. package/docs/compliance/monthly-compliance-checklist-2026-03-07.md +88 -0
  235. package/docs/compliance/notice-and-takedown-policy-2026-03-07.md +34 -0
  236. package/docs/compliance/privacy-policy-2026-03-07.md +75 -0
  237. package/docs/compliance/subprocessors-inventory-2026-03-07.md +16 -0
  238. package/docs/database/production-db-evolution-runbook-2026q1.md +365 -0
  239. package/docs/security/dsar-lgpd-runbook-2026-03-07.md +86 -0
  240. package/docs/security/incident-response-lgpd-anpd-runbook-2026-03-07.md +77 -0
  241. package/docs/security/network-hardening-runbook-2026-03-07.md +137 -0
  242. package/docs/seo/omnizap-seo-playbook-br-2026-02-28.md +238 -0
  243. package/docs/seo/satellite-page-template.md +116 -0
  244. package/docs/seo/satellite-pages-phase1.json +364 -0
  245. package/docs/wiki/Home.md +120 -0
  246. package/docs/wiki/pair-extraordinaire-2026-03-08.md +3 -0
  247. package/docs/wiki/recent-changes-2026-03-08.md +47 -0
  248. package/ecosystem.prod.config.cjs +135 -0
  249. package/eslint.config.js +89 -0
  250. package/index.js +488 -0
  251. package/ml/clip_classifier/Dockerfile +18 -0
  252. package/ml/clip_classifier/README.md +118 -0
  253. package/ml/clip_classifier/adaptive_scoring.py +40 -0
  254. package/ml/clip_classifier/classifier.py +654 -0
  255. package/ml/clip_classifier/embedding_store.py +481 -0
  256. package/ml/clip_classifier/env_loader.py +15 -0
  257. package/ml/clip_classifier/llm_label_expander.py +144 -0
  258. package/ml/clip_classifier/main.py +213 -0
  259. package/ml/clip_classifier/requirements.txt +10 -0
  260. package/ml/clip_classifier/similarity_engine.py +74 -0
  261. package/new-logo.png +0 -0
  262. package/observability/alert-rules.yml +60 -0
  263. package/observability/grafana/dashboards/omnizap-mysql.json +136 -0
  264. package/observability/grafana/dashboards/omnizap-overview.json +170 -0
  265. package/observability/grafana/provisioning/dashboards/dashboards.yml +11 -0
  266. package/observability/grafana/provisioning/datasources/datasources.yml +15 -0
  267. package/observability/loki-config.yml +38 -0
  268. package/observability/mysql-setup.sql +46 -0
  269. package/observability/prometheus.yml +35 -0
  270. package/observability/promtail-config.yml +84 -0
  271. package/observability/sticker-catalog-slo.md +83 -0
  272. package/observability/sticker-scale-hardening-rollout.md +128 -0
  273. package/package.json +144 -0
  274. package/public/apple-touch-icon.png +0 -0
  275. package/public/assets/css/commands-react.input.css +71 -0
  276. package/public/assets/css/create-pack-react.input.css +31 -0
  277. package/public/assets/css/home-react.input.css +106 -0
  278. package/public/assets/css/login-react.input.css +58 -0
  279. package/public/assets/css/stickers-react.input.css +18 -0
  280. package/public/assets/css/terms-react.input.css +115 -0
  281. package/public/assets/css/user-react.input.css +57 -0
  282. package/public/assets/images/brand-icon-192.png +0 -0
  283. package/public/assets/images/brand-logo-128.webp +0 -0
  284. package/public/assets/images/hero-banner-1280.jpg +0 -0
  285. package/public/comandos/commands-catalog.json +4517 -0
  286. package/public/css/api-docs.css +161 -0
  287. package/public/css/stickers-admin.css +1288 -0
  288. package/public/css/styles.css +679 -0
  289. package/public/css/systemadm/admin.css +474 -0
  290. package/public/css/systemadm/base.css +73 -0
  291. package/public/css/systemadm/components.css +662 -0
  292. package/public/css/systemadm/layout.css +229 -0
  293. package/public/css/systemadm/tokens.css +56 -0
  294. package/public/favicon-16x16.png +0 -0
  295. package/public/favicon-32x32.png +0 -0
  296. package/public/favicon.ico +0 -0
  297. package/public/js/apps/apiDocsApp.js +235 -0
  298. package/public/js/apps/commandsReactApp.js +528 -0
  299. package/public/js/apps/createPackApp.js +1646 -0
  300. package/public/js/apps/homeReactApp.js +942 -0
  301. package/public/js/apps/loginReactApp.js +496 -0
  302. package/public/js/apps/stickersAdminApp.js +1753 -0
  303. package/public/js/apps/stickersApp.js +3797 -0
  304. package/public/js/apps/termsReactApp.js +528 -0
  305. package/public/js/apps/userApp.js +2540 -0
  306. package/public/js/apps/userProfile/actions.js +66 -0
  307. package/public/js/apps/userReactApp.js +547 -0
  308. package/public/js/catalog.js +950 -0
  309. package/public/pages/api-docs.html +40 -0
  310. package/public/pages/aup.html +158 -0
  311. package/public/pages/comandos.html +41 -0
  312. package/public/pages/dpa.html +227 -0
  313. package/public/pages/home.html +45 -0
  314. package/public/pages/licenca.html +182 -0
  315. package/public/pages/login.html +40 -0
  316. package/public/pages/notice-and-takedown.html +234 -0
  317. package/public/pages/politica-de-privacidade.html +251 -0
  318. package/public/pages/seo-bot-whatsapp-para-grupo.html +350 -0
  319. package/public/pages/seo-bot-whatsapp-sem-programar.html +350 -0
  320. package/public/pages/seo-como-automatizar-avisos-no-whatsapp.html +350 -0
  321. package/public/pages/seo-como-criar-comandos-whatsapp.html +350 -0
  322. package/public/pages/seo-como-evitar-spam-no-whatsapp.html +350 -0
  323. package/public/pages/seo-como-moderar-grupo-whatsapp.html +350 -0
  324. package/public/pages/seo-como-organizar-comunidade-whatsapp.html +350 -0
  325. package/public/pages/seo-melhor-bot-whatsapp-para-grupos.html +350 -0
  326. package/public/pages/stickers-admin.html +31 -0
  327. package/public/pages/stickers-create.html +41 -0
  328. package/public/pages/stickers.html +45 -0
  329. package/public/pages/suboperadores.html +237 -0
  330. package/public/pages/termos-de-uso-texto-integral.html +241 -0
  331. package/public/pages/termos-de-uso.html +41 -0
  332. package/public/pages/user-password-reset.html +32 -0
  333. package/public/pages/user-systemadm.html +508 -0
  334. package/public/pages/user.html +39 -0
  335. package/public/robots.txt +9 -0
  336. package/public/site.webmanifest +24 -0
  337. package/public/sitemap.xml +98 -0
  338. package/schemas/command-config.schema.json +582 -0
  339. package/scripts/baileys-compat-smoke.mjs +12 -0
  340. package/scripts/cache-bust.mjs +142 -0
  341. package/scripts/deploy.sh +916 -0
  342. package/scripts/email-broadcast-terms-update.mjs +170 -0
  343. package/scripts/enrich-command-discovery-fields.mjs +286 -0
  344. package/scripts/generate-command-config-schema.mjs +273 -0
  345. package/scripts/generate-commands-catalog.mjs +308 -0
  346. package/scripts/generate-module-agents.mjs +631 -0
  347. package/scripts/generate-seo-satellite-pages.mjs +400 -0
  348. package/scripts/github-deploy-notify.mjs +174 -0
  349. package/scripts/github-release-notify.mjs +219 -0
  350. package/scripts/release.sh +599 -0
  351. package/scripts/run-codeql-local.sh +116 -0
  352. package/scripts/run-prettier-all.mjs +25 -0
  353. package/scripts/security-smoketest.mjs +581 -0
  354. package/scripts/sticker-catalog-loadtest.mjs +210 -0
  355. package/scripts/sticker-worker-task.mjs +119 -0
  356. package/scripts/sync-readme-snapshot.mjs +133 -0
  357. package/scripts/validate-command-config-schema.mjs +130 -0
  358. package/scripts/validate-command-configs.mjs +15 -0
  359. package/scripts/wiki-sync.sh +191 -0
  360. package/server/auth/googleWebAuth/googleWebAuthRuntime.js +62 -0
  361. package/server/auth/googleWebAuth/googleWebAuthService.js +807 -0
  362. package/server/auth/jwt/webJwtService.js +147 -0
  363. package/server/auth/stickerCatalogAuthContext.js +165 -0
  364. package/server/auth/termsAcceptance/termsAcceptanceHandler.js +189 -0
  365. package/server/auth/userPassword/index.js +14 -0
  366. package/server/auth/userPassword/userPasswordAuthService.js +422 -0
  367. package/server/auth/userPassword/userPasswordCrypto.js +199 -0
  368. package/server/auth/userPassword/userPasswordCrypto.test.js +76 -0
  369. package/server/auth/userPassword/userPasswordRecoveryService.js +728 -0
  370. package/server/auth/validation/authSchemas.js +236 -0
  371. package/server/auth/webAccount/webAccountHandlers.js +1434 -0
  372. package/server/controllers/admin/adminBanService.js +138 -0
  373. package/server/controllers/admin/adminPanelHandlers.js +2083 -0
  374. package/server/controllers/admin/stickerCatalogAdminContext.js +17 -0
  375. package/server/controllers/admin/systemAdminController.js +201 -0
  376. package/server/controllers/email/emailAutomationController.js +239 -0
  377. package/server/controllers/metricsController.js +21 -0
  378. package/server/controllers/seo/stickerCatalogSeoContext.js +514 -0
  379. package/server/controllers/sticker/nonCatalogHandlers.js +303 -0
  380. package/server/controllers/sticker/stickerCatalogController.js +4700 -0
  381. package/server/controllers/system/contactController.js +115 -0
  382. package/server/controllers/system/githubController.js +137 -0
  383. package/server/controllers/system/stickerCatalogSystemContext.js +758 -0
  384. package/server/controllers/system/storageController.js +154 -0
  385. package/server/controllers/system/systemController.js +135 -0
  386. package/server/controllers/system/systemMetricsController.js +156 -0
  387. package/server/controllers/system/visitController.js +90 -0
  388. package/server/controllers/userController.js +145 -0
  389. package/server/email/emailAutomationRuntime.js +225 -0
  390. package/server/email/emailAutomationService.js +125 -0
  391. package/server/email/emailOutboxRepository.js +282 -0
  392. package/server/email/emailTemplateService.js +480 -0
  393. package/server/email/emailTransportService.js +156 -0
  394. package/server/http/clientIp.js +95 -0
  395. package/server/http/httpRequestUtils.js +262 -0
  396. package/server/http/httpRequestUtils.test.js +80 -0
  397. package/server/http/httpServer.js +180 -0
  398. package/server/http/requestContext.js +20 -0
  399. package/server/http/siteRoutingUtils.js +87 -0
  400. package/server/index.js +1 -0
  401. package/server/middleware/cachePolicy.js +26 -0
  402. package/server/middleware/cachePolicyHelpers.js +1 -0
  403. package/server/middleware/endpointRateLimit.js +181 -0
  404. package/server/middleware/rateLimit.js +70 -0
  405. package/server/middleware/requireAdminAuth.js +48 -0
  406. package/server/middleware/securityHeaders.js +97 -0
  407. package/server/routes/admin/systemAdminRouter.js +64 -0
  408. package/server/routes/email/emailAutomationRouter.js +46 -0
  409. package/server/routes/health/healthRouter.js +41 -0
  410. package/server/routes/indexRouter.js +234 -0
  411. package/server/routes/metrics/metricsRouter.js +58 -0
  412. package/server/routes/static/staticPageRouter.js +134 -0
  413. package/server/routes/sticker/catalogHandlers/catalogAdminHttp.js +105 -0
  414. package/server/routes/sticker/catalogHandlers/catalogAuthHttp.js +77 -0
  415. package/server/routes/sticker/catalogHandlers/catalogPublicHttp.js +120 -0
  416. package/server/routes/sticker/catalogHandlers/catalogUploadHttp.js +83 -0
  417. package/server/routes/sticker/catalogRouter.js +77 -0
  418. package/server/routes/sticker/stickerApiRouter.js +84 -0
  419. package/server/routes/sticker/stickerDataRouter.js +145 -0
  420. package/server/routes/sticker/stickerSiteRouter.js +43 -0
  421. package/server/routes/user/userApiPaths.js +66 -0
  422. package/server/routes/user/userRouter.js +65 -0
  423. package/server/utils/safePath.js +26 -0
  424. package/utils/logger/loggerModule.js +35 -0
  425. package/vite.config.mjs +38 -0
@@ -0,0 +1,215 @@
1
+ # StickerPackModule Agent Guide
2
+
3
+ Este arquivo e destinado a agentes de IA para gerar respostas no contexto dos comandos deste modulo.
4
+
5
+ ## Fonte de Verdade
6
+
7
+ - arquivo_base: `app/modules/stickerPackModule/commandConfig.json`
8
+ - schema_version: `2.0.0`
9
+ - module_enabled: `true`
10
+ - generated_at: `2026-03-11T02:35:17.177Z`
11
+
12
+ ## Escopo do Modulo
13
+
14
+ - module: `stickerPackModule`
15
+ - source_files:
16
+ - stickerPackCommandHandlers.js
17
+ - total_commands: `1`
18
+ - total_enabled_commands: `1`
19
+
20
+ ## Defaults Schema v2
21
+
22
+ - inheritance_mode: deep_merge_with_command_overrides
23
+ - compatibility_mode: legacy_and_v2_fields
24
+ - legacy_field_aliases:
25
+ - descricao: description
26
+ - metodos_de_uso: usage
27
+ - permissao_necessaria: permission
28
+ - local_de_uso: contexts
29
+ - informacoes_coletadas: collected_data
30
+ - pre_condicoes: requirements
31
+ - dependencias_externas: dependencies
32
+ - efeitos_colaterais: side_effects
33
+ - observabilidade: observability
34
+ - privacidade: privacy
35
+ - limite_uso_por_plano: plan_limits
36
+ - argumentos: arguments
37
+ - acesso: access
38
+ - defaults.command:
39
+ - enabled: true
40
+ - category: figurinhas
41
+ - version: 1.0.0
42
+ - stability: stable
43
+ - deprecated: false
44
+ - replaced_by: null
45
+ - risk_level: medium
46
+ - defaults.requirements (legacy view):
47
+ - requer_grupo: nao
48
+ - requer_admin: nao
49
+ - requer_admin_principal: nao
50
+ - requer_google_login: sim
51
+ - requer_nsfw: nao
52
+ - requer_midia: nao
53
+ - requer_mensagem_respondida: nao
54
+
55
+ ## Protocolo de Resposta para IA
56
+
57
+ - Passo 1: identificar comando pelo token apos o prefixo.
58
+ - Passo 2: resolver alias para nome canonico usando campo `aliases`.
59
+ - Passo 3: validar `enabled`, `pre_condicoes`, permissao e local de uso.
60
+ - Passo 4: se houver erro de uso, responder com `mensagens_uso` (quando existir) ou `metodos_de_uso`.
61
+ - Passo 5: seguir `respostas_padrao` como fallback de texto.
62
+ - Passo 6: considerar `informacoes_coletadas`, `privacidade` e `observabilidade` ao elaborar resposta.
63
+
64
+ ## Regras de Seguranca para IA
65
+
66
+ - A IA orienta, mas nao executa acao administrativa automaticamente.
67
+ - Nao inventar comandos, subcomandos ou permissao fora do JSON.
68
+ - Sempre informar onde pode usar (grupo/privado) e quem pode usar.
69
+ - Em duvida de permissao, responder com orientacao conservadora.
70
+
71
+ ## Catalogo de Comandos
72
+
73
+ ### pacote
74
+
75
+ - id: stickerpack.pacote
76
+ - aliases: packs, pacotes, pack
77
+ - enabled: true
78
+ - categoria: figurinhas
79
+ - descricao: Gerencia packs de figurinhas (criar, listar, adicionar, enviar).
80
+ - permissao_necessaria: usuario comum
81
+ - version: 1.0.0
82
+ - stability: stable
83
+ - deprecated: nao
84
+ - risk_level: low
85
+ - local_de_uso:
86
+ - privado
87
+ - grupo
88
+ - metodos_de_uso:
89
+ - <prefix>pacote help
90
+ - <prefix>pacote create meupack
91
+ - <prefix>pacote list
92
+ - <prefix>pacote add <pacote>
93
+ - <prefix>pacote send <pacote>
94
+ - mensagens_uso (variantes):
95
+ - default:
96
+ - <prefix>pacote help
97
+ - <prefix>pacote create meupack
98
+ - <prefix>pacote list
99
+ - <prefix>pacote add <pacote>
100
+ - <prefix>pacote send <pacote>
101
+ - subcomandos:
102
+ - help
103
+ - create
104
+ - list
105
+ - info
106
+ - add
107
+ - setcover
108
+ - setdesc
109
+ - setpublisher
110
+ - send
111
+ - rename
112
+ - remove
113
+ - delete
114
+ - reorder
115
+ - argumentos:
116
+ - subcomando | tipo: string | obrigatorio | validacao: ação de gerenciamento de pack | default: null | posicao: 0
117
+ - parametros | tipo: array | opcional | validacao: dependente do subcomando | default: null | posicao: 1
118
+ - pre_condicoes:
119
+ - requer_grupo: nao
120
+ - requer_admin: nao
121
+ - requer_admin_principal: nao
122
+ - requer_google_login: sim
123
+ - requer_nsfw: nao
124
+ - requer_midia: nao
125
+ - requer_mensagem_respondida: nao
126
+ - rate_limit:
127
+ - max: 20
128
+ - janela_ms: 60000
129
+ - escopo: usuario
130
+ - acesso:
131
+ - somente_premium: nao
132
+ - planos_permitidos: comum, premium
133
+ - limite_uso_por_plano:
134
+ - comum: max=12, janela_ms=300000, escopo=usuario
135
+ - premium: max=45, janela_ms=300000, escopo=usuario
136
+ - informacoes_coletadas:
137
+ - identificador do chat (remoteJid)
138
+ - identificador do remetente (senderJid)
139
+ - texto do comando e argumentos
140
+ - contexto da mensagem (citacao e mencoes, quando existir)
141
+ - subcomando e argumentos do pack
142
+ - figurinha da mensagem atual/citada (para add/setcover)
143
+ - estado de rate limit por usuario
144
+ - dados de packs do usuario no armazenamento interno
145
+ - dependencias_externas:
146
+ - banco de dados de packs
147
+ - armazenamento de assets de figurinha
148
+ - efeitos_colaterais:
149
+ - cria/atualiza packs no banco
150
+ - pode armazenar/remover assets de figurinha
151
+ - respostas_padrao:
152
+ - success: Comando executado com sucesso.
153
+ - usage_error: Formato de uso inválido. Consulte metodos_de_uso.
154
+ - permission_error: Permissão insuficiente para executar este comando.
155
+ - sucesso: Comando executado com sucesso.
156
+ - erro_uso: Formato de uso inválido. Consulte metodos_de_uso.
157
+ - erro_permissao: Permissão insuficiente para executar este comando.
158
+ - mensagens_sistema:
159
+ - (nao informado)
160
+ - limites_operacionais:
161
+ - (nao informado)
162
+ - opcoes:
163
+ - toggle_on_off_status.type: toggle
164
+ - toggle_on_off_status.allowed_actions: on, off, status
165
+ - toggle_on_off_status.action_argument: acao
166
+ - add_remove_list.type: list_management
167
+ - add_remove_list.allowed_actions: add, remove, list
168
+ - add_remove_list.action_argument: acao
169
+ - approve_reject.type: moderation_decision
170
+ - approve_reject.allowed_actions: approve, reject
171
+ - approve_reject.action_argument: acao
172
+ - approve_reject.requires_targets: true
173
+ - set_status_reset.type: configuration_window
174
+ - set_status_reset.allowed_actions: set, status, reset
175
+ - set_status_reset.action_argument: valor
176
+ - observabilidade:
177
+ - event_name: command.executed
178
+ - analytics_event: whatsapp_command_pack
179
+ - tags_log: whatsapp, command, stickerPackModule, pack
180
+ - nivel_log: info
181
+ - privacidade:
182
+ - dados_sensiveis:
183
+ - sender_identifier
184
+ - retencao: standard_app_logs
185
+ - base_legal: service_execution_and_legitimate_interest
186
+ - docs:
187
+ - summary: Gerencia packs de figurinhas (criar, listar, adicionar, enviar).
188
+ - usage_examples: <prefix>pacote help, <prefix>pacote create meupack, <prefix>pacote list, <prefix>pacote add <pacote>, <prefix>pacote send <pacote>
189
+ - usage_variants.default: <prefix>pacote help, <prefix>pacote create meupack, <prefix>pacote list, <prefix>pacote add <pacote>, <prefix>pacote send <pacote>
190
+ - behavior:
191
+ - type: list_management
192
+ - allowed_actions: add, remove, list
193
+ - action_argument: acao
194
+ - limits:
195
+ - usage_description: rate limit por janela e limite de itens por pack
196
+ - rate_limit.max: 20
197
+ - rate_limit.janela_ms: 60000
198
+ - rate_limit.escopo: usuario
199
+ - access.somente_premium: false
200
+ - access.planos_permitidos: comum, premium
201
+ - plan_limits.comum.max: 12
202
+ - plan_limits.comum.janela_ms: 300000
203
+ - plan_limits.comum.escopo: usuario
204
+ - plan_limits.premium.max: 45
205
+ - plan_limits.premium.janela_ms: 300000
206
+ - plan_limits.premium.escopo: usuario
207
+ - discovery:
208
+ - keywords: pacote, packs, figurinhas, privado, grupo
209
+ - faq_queries: como usar pacote, o que faz pacote, comando pacote
210
+ - user_phrasings: quero usar pacote, me ajuda com pacote, gerencia packs de figurinhas
211
+ - suggestion_priority: 100
212
+ - handler:
213
+ - file: stickerPackCommandHandlers.js
214
+ - method: handlePackCommand
215
+ - command_case: pacote
@@ -0,0 +1,20 @@
1
+ import logger from '#logger';
2
+ import { createAutoPackCollector } from './autoPackCollectorService.js';
3
+ import stickerPackService from './stickerPackServiceRuntime.js';
4
+ import { saveStickerAssetFromBuffer } from './stickerStorageService.js';
5
+
6
+ /**
7
+ * Instância singleton do coletor automático de figurinhas.
8
+ */
9
+ const autoPackCollector = createAutoPackCollector({
10
+ logger,
11
+ stickerPackService,
12
+ saveStickerAssetFromBuffer,
13
+ });
14
+
15
+ /**
16
+ * Atalho para adicionar figurinhas ao pack automático do usuário.
17
+ */
18
+ export const addStickerToAutoPack = autoPackCollector.addStickerToAutoPack;
19
+
20
+ export default autoPackCollector;
@@ -0,0 +1,357 @@
1
+ import { STICKER_PACK_ERROR_CODES, StickerPackError } from './stickerPackErrors.js';
2
+ import { sanitizeText } from './stickerPackUtils.js';
3
+
4
+ /**
5
+ * Serviço responsável por direcionar figurinhas recém-criadas para packs automáticos.
6
+ */
7
+ const DEFAULT_AUTO_PACK_NAME = process.env.STICKER_PACK_AUTO_PACK_NAME || 'pack';
8
+ const AUTO_PACK_TARGET_VISIBILITY = 'unlisted';
9
+ const AUTO_COLLECT_ENABLED = process.env.STICKER_PACK_AUTO_COLLECT_ENABLED !== 'false';
10
+ const AUTO_PACK_NAME_MAX_LENGTH = 120;
11
+ const AUTO_PACK_DESCRIPTION_MARKER = '[auto-pack:collector]';
12
+ const AUTO_PACK_DESCRIPTION_TEXT = 'Coleção automática de figurinhas criadas pelo usuário.';
13
+ const normalizeVisibility = (value) =>
14
+ String(value || '')
15
+ .trim()
16
+ .toLowerCase();
17
+
18
+ /**
19
+ * Escapa texto para uso seguro em RegExp.
20
+ *
21
+ * @param {unknown} value Valor de entrada.
22
+ * @returns {string} Valor escapado.
23
+ */
24
+ const escapeRegex = (value) => String(value || '').replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
25
+
26
+ /**
27
+ * Remove acentos para facilitar normalização de nomes.
28
+ *
29
+ * @param {unknown} value Valor de entrada.
30
+ * @returns {string} Texto sem diacríticos.
31
+ */
32
+ const removeDiacritics = (value) =>
33
+ String(value || '')
34
+ .normalize('NFD')
35
+ .replace(/[\u0300-\u036f]/g, '');
36
+
37
+ /**
38
+ * Gera nome de pack automático válido no padrão aceito.
39
+ *
40
+ * @param {unknown} value Nome base.
41
+ * @param {{ fallback?: string, maxLength?: number }} [options] Configurações de fallback/tamanho.
42
+ * @returns {string} Nome normalizado.
43
+ */
44
+ const normalizeAutoPackName = (value, { fallback = 'pack', maxLength = AUTO_PACK_NAME_MAX_LENGTH } = {}) => {
45
+ const sanitized = sanitizeText(value, maxLength, { allowEmpty: true }) || '';
46
+ const normalized = removeDiacritics(sanitized)
47
+ .toLowerCase()
48
+ .replace(/[^a-z0-9]+/g, '')
49
+ .slice(0, maxLength);
50
+
51
+ return normalized || fallback;
52
+ };
53
+
54
+ const buildAutoPackDescription = () => `${AUTO_PACK_DESCRIPTION_TEXT} ${AUTO_PACK_DESCRIPTION_MARKER}`.trim();
55
+
56
+ const isThemeCurationAutoPack = (pack) => {
57
+ if (!pack || typeof pack !== 'object') return false;
58
+ const description = String(pack.description || '').toLowerCase();
59
+ if (description.includes('[auto-theme:') || description.includes('[auto-tag:')) return true;
60
+ if (
61
+ String(pack.name || '')
62
+ .trim()
63
+ .toLowerCase()
64
+ .startsWith('[auto]')
65
+ )
66
+ return true;
67
+ return Boolean(String(pack.pack_theme_key || '').trim());
68
+ };
69
+
70
+ const isAutoCollectorPack = (pack) => {
71
+ if (!pack || typeof pack !== 'object') return false;
72
+ if (isThemeCurationAutoPack(pack)) return false;
73
+
74
+ const description = String(pack.description || '').toLowerCase();
75
+ if (description.includes(AUTO_PACK_DESCRIPTION_MARKER)) return true;
76
+ if (description.includes('coleção automática de figurinhas criadas pelo usuário.')) return true;
77
+
78
+ const normalizedName = normalizeAutoPackName(pack.name, {
79
+ fallback: '',
80
+ maxLength: AUTO_PACK_NAME_MAX_LENGTH,
81
+ });
82
+ if (!normalizedName) return false;
83
+
84
+ const base = normalizeAutoPackName(DEFAULT_AUTO_PACK_NAME, {
85
+ fallback: 'pack',
86
+ maxLength: AUTO_PACK_NAME_MAX_LENGTH,
87
+ });
88
+ const matcher = new RegExp(`^${escapeRegex(base.toLowerCase())}\\d+$`, 'i');
89
+ const looksLikeLegacyCollector = matcher.test(normalizedName);
90
+ if (looksLikeLegacyCollector) return true;
91
+
92
+ return pack.is_auto_pack === true || Number(pack.is_auto_pack || 0) === 1;
93
+ };
94
+
95
+ const isUserManagedPackCandidate = (pack) => {
96
+ if (!pack || typeof pack !== 'object') return false;
97
+ if (isThemeCurationAutoPack(pack)) return false;
98
+ if (isAutoCollectorPack(pack)) return false;
99
+ return Number(pack.is_auto_pack || 0) !== 1;
100
+ };
101
+
102
+ /**
103
+ * Monta candidato incremental para nome de pack automático.
104
+ *
105
+ * @param {string} base Base do nome.
106
+ * @param {number} index Índice incremental.
107
+ * @returns {string} Nome candidato.
108
+ */
109
+ const buildAutoPackCandidate = (base, index) => {
110
+ const suffix = String(index);
111
+ const maxBaseLength = Math.max(1, AUTO_PACK_NAME_MAX_LENGTH - suffix.length);
112
+ const trimmedBase = normalizeAutoPackName(base, { fallback: 'pack', maxLength: maxBaseLength });
113
+ return `${trimmedBase}${suffix}`;
114
+ };
115
+
116
+ /**
117
+ * Define o próximo nome disponível para auto packs.
118
+ *
119
+ * @param {Array<{name?: string}>} packs Packs já existentes.
120
+ * @returns {string} Nome único sugerido.
121
+ */
122
+ const makeAutoPackName = (packs) => {
123
+ const base = normalizeAutoPackName(DEFAULT_AUTO_PACK_NAME, {
124
+ fallback: 'pack',
125
+ maxLength: AUTO_PACK_NAME_MAX_LENGTH,
126
+ });
127
+ const normalizedBase = base.toLowerCase();
128
+ const existingNames = packs
129
+ .map((pack) => normalizeAutoPackName(pack?.name, { fallback: '', maxLength: AUTO_PACK_NAME_MAX_LENGTH }))
130
+ .filter(Boolean)
131
+ .map((name) => name.toLowerCase());
132
+ const existingSet = new Set(existingNames);
133
+ const usedIndexes = new Set();
134
+ const matcher = new RegExp(`^${escapeRegex(normalizedBase)}(\\d+)?$`, 'i');
135
+
136
+ for (const name of existingNames) {
137
+ const match = name.match(matcher);
138
+ if (!match) continue;
139
+
140
+ if (!match[1]) {
141
+ usedIndexes.add(1);
142
+ continue;
143
+ }
144
+
145
+ const parsedIndex = Number(match[1]);
146
+ if (Number.isInteger(parsedIndex) && parsedIndex > 0) {
147
+ usedIndexes.add(parsedIndex);
148
+ }
149
+ }
150
+
151
+ let index = 1;
152
+ while (index < 10_000) {
153
+ const candidate = buildAutoPackCandidate(base, index);
154
+ if (!usedIndexes.has(index) && !existingSet.has(candidate.toLowerCase())) {
155
+ return candidate;
156
+ }
157
+ index += 1;
158
+ }
159
+
160
+ const fallbackIndex = Math.max(1, packs.length + 1);
161
+ return buildAutoPackCandidate(base, fallbackIndex);
162
+ };
163
+
164
+ /**
165
+ * Cria coletor automático de figurinhas para packs.
166
+ *
167
+ * @param {{
168
+ * enabled?: boolean,
169
+ * logger?: { info?: Function, warn?: Function, error?: Function, debug?: Function },
170
+ * stickerPackService?: object,
171
+ * saveStickerAssetFromBuffer?: Function,
172
+ * }} [options] Dependências/configurações de runtime.
173
+ * @returns {{ addStickerToAutoPack: Function }} API do coletor.
174
+ */
175
+ export function createAutoPackCollector(options = {}) {
176
+ const deps = {
177
+ logger: {
178
+ info: () => {},
179
+ warn: () => {},
180
+ error: () => {},
181
+ debug: () => {},
182
+ },
183
+ stickerPackService: null,
184
+ saveStickerAssetFromBuffer: null,
185
+ ...options,
186
+ };
187
+
188
+ const isEnabled = options.enabled ?? AUTO_COLLECT_ENABLED;
189
+
190
+ if (isEnabled) {
191
+ if (!deps.stickerPackService || typeof deps.stickerPackService.listPacks !== 'function') {
192
+ throw new Error('createAutoPackCollector: stickerPackService inválido.');
193
+ }
194
+
195
+ if (typeof deps.saveStickerAssetFromBuffer !== 'function') {
196
+ throw new Error('createAutoPackCollector: saveStickerAssetFromBuffer é obrigatório.');
197
+ }
198
+ }
199
+
200
+ const ensureAutoPackVisibility = async ({ ownerJid, pack }) => {
201
+ if (!pack) return pack;
202
+
203
+ if (normalizeVisibility(pack.visibility) === AUTO_PACK_TARGET_VISIBILITY) {
204
+ return pack;
205
+ }
206
+
207
+ if (typeof deps.stickerPackService.setPackVisibility !== 'function') {
208
+ return { ...pack, visibility: AUTO_PACK_TARGET_VISIBILITY };
209
+ }
210
+
211
+ try {
212
+ const updated = await deps.stickerPackService.setPackVisibility({
213
+ ownerJid,
214
+ identifier: pack.id || pack.pack_key,
215
+ visibility: AUTO_PACK_TARGET_VISIBILITY,
216
+ });
217
+
218
+ deps.logger.info('Visibilidade do pack automático ajustada para unlisted.', {
219
+ action: 'sticker_pack_auto_collect_visibility_adjusted',
220
+ owner_jid: ownerJid,
221
+ pack_id: updated?.id || pack.id || null,
222
+ });
223
+
224
+ return updated || { ...pack, visibility: AUTO_PACK_TARGET_VISIBILITY };
225
+ } catch (error) {
226
+ deps.logger.warn('Falha ao ajustar visibilidade do pack automático.', {
227
+ action: 'sticker_pack_auto_collect_visibility_adjust_failed',
228
+ owner_jid: ownerJid,
229
+ pack_id: pack.id || null,
230
+ error: error?.message,
231
+ });
232
+ return pack;
233
+ }
234
+ };
235
+
236
+ const ensureTargetPack = async ({ ownerJid, senderName }) => {
237
+ const packs = await deps.stickerPackService.listPacks({ ownerJid, limit: 30 });
238
+ if (packs.length > 0) {
239
+ // Prioriza pack gerenciado pelo usuário (pack atual/manual).
240
+ const userManagedPacks = packs.filter((entry) => isUserManagedPackCandidate(entry));
241
+ if (userManagedPacks.length > 0) {
242
+ return {
243
+ pack: userManagedPacks[0],
244
+ packs,
245
+ };
246
+ }
247
+
248
+ const managedAutoPacks = packs.filter((entry) => isAutoCollectorPack(entry));
249
+ const preferredPack = managedAutoPacks.find((entry) => normalizeVisibility(entry?.visibility) === AUTO_PACK_TARGET_VISIBILITY) || managedAutoPacks[0] || null;
250
+
251
+ if (preferredPack) {
252
+ const ensuredPack = await ensureAutoPackVisibility({ ownerJid, pack: preferredPack });
253
+ return {
254
+ pack: ensuredPack,
255
+ packs,
256
+ };
257
+ }
258
+ }
259
+
260
+ const created = await deps.stickerPackService.createPack({
261
+ ownerJid,
262
+ name: makeAutoPackName([]),
263
+ publisher: sanitizeText(senderName, 120, { allowEmpty: true }) || 'OmniZap',
264
+ description: buildAutoPackDescription(),
265
+ visibility: AUTO_PACK_TARGET_VISIBILITY,
266
+ isAutoPack: true,
267
+ });
268
+
269
+ return {
270
+ pack: created,
271
+ packs: [created],
272
+ };
273
+ };
274
+
275
+ const addStickerToAutoPack = async ({ ownerJid, senderName, stickerBuffer }) => {
276
+ if (!isEnabled) {
277
+ return { status: 'skipped', reason: 'disabled' };
278
+ }
279
+
280
+ if (!Buffer.isBuffer(stickerBuffer) || !stickerBuffer.length) {
281
+ return { status: 'skipped', reason: 'invalid_buffer' };
282
+ }
283
+
284
+ const asset = await deps.saveStickerAssetFromBuffer({
285
+ ownerJid,
286
+ buffer: stickerBuffer,
287
+ mimetype: 'image/webp',
288
+ });
289
+
290
+ const { pack: targetPack, packs } = await ensureTargetPack({ ownerJid, senderName });
291
+
292
+ try {
293
+ const updated = await deps.stickerPackService.addStickerToPack({
294
+ ownerJid,
295
+ identifier: targetPack.id,
296
+ asset,
297
+ });
298
+
299
+ deps.logger.info('Figurinha adicionada automaticamente ao pack.', {
300
+ action: 'sticker_pack_auto_collect',
301
+ owner_jid: ownerJid,
302
+ pack_id: updated.id,
303
+ sticker_id: asset.id,
304
+ });
305
+
306
+ return {
307
+ status: 'added',
308
+ pack: updated,
309
+ asset,
310
+ };
311
+ } catch (error) {
312
+ if (error instanceof StickerPackError && error.code === STICKER_PACK_ERROR_CODES.DUPLICATE_STICKER) {
313
+ return {
314
+ status: 'duplicate',
315
+ pack: targetPack,
316
+ asset,
317
+ };
318
+ }
319
+
320
+ if (error instanceof StickerPackError && error.code === STICKER_PACK_ERROR_CODES.PACK_LIMIT_REACHED) {
321
+ const created = await deps.stickerPackService.createPack({
322
+ ownerJid,
323
+ name: makeAutoPackName(packs),
324
+ publisher: sanitizeText(senderName, 120, { allowEmpty: true }) || targetPack.publisher || 'OmniZap',
325
+ description: buildAutoPackDescription(),
326
+ visibility: AUTO_PACK_TARGET_VISIBILITY,
327
+ isAutoPack: true,
328
+ });
329
+
330
+ const updated = await deps.stickerPackService.addStickerToPack({
331
+ ownerJid,
332
+ identifier: created.id,
333
+ asset,
334
+ });
335
+
336
+ deps.logger.info('Figurinha adicionada ao novo pack automático após limite.', {
337
+ action: 'sticker_pack_auto_collect_rollover',
338
+ owner_jid: ownerJid,
339
+ pack_id: updated.id,
340
+ sticker_id: asset.id,
341
+ });
342
+
343
+ return {
344
+ status: 'added',
345
+ pack: updated,
346
+ asset,
347
+ };
348
+ }
349
+
350
+ throw error;
351
+ }
352
+ };
353
+
354
+ return {
355
+ addStickerToAutoPack,
356
+ };
357
+ }