@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.
- package/.clusterfuzzlite/Dockerfile +10 -0
- package/.env.example +907 -0
- package/.github/codeql/codeql-config.yml +10 -0
- package/.github/dependabot.yml +35 -0
- package/.github/workflows/ci.yml +73 -0
- package/.github/workflows/codeql.yml +106 -0
- package/.github/workflows/db-migration-check.yml +98 -0
- package/.github/workflows/dependency-review.yml +22 -0
- package/.github/workflows/deploy.yml +95 -0
- package/.github/workflows/release.yml +106 -0
- package/.github/workflows/security-attest-provenance.yml +51 -0
- package/.github/workflows/security-gitleaks.yml +34 -0
- package/.github/workflows/security-runner-hardening.yml +31 -0
- package/.github/workflows/security-scorecard.yml +44 -0
- package/.github/workflows/security-zap-baseline.yml +44 -0
- package/.github/workflows/security-zap-full-scan.yml +43 -0
- package/.github/workflows/security-zizmor.yml +36 -0
- package/.github/workflows/wiki-sync.yml +44 -0
- package/.gitleaks.toml +15 -0
- package/.prettierrc +34 -0
- package/CODE_OF_CONDUCT.md +114 -0
- package/LICENSE +56 -0
- package/README.md +110 -0
- package/SECURITY.md +110 -0
- package/app/config/index.js +4 -0
- package/app/configParts/adminIdentity.js +92 -0
- package/app/configParts/baileysConfig.js +1818 -0
- package/app/configParts/groupUtils.js +692 -0
- package/app/configParts/loggerConfig.js +394 -0
- package/app/configParts/messagePersistenceService.js +305 -0
- package/app/connection/baileysCompatibility.test.js +40 -0
- package/app/connection/baileysDbAuthState.js +344 -0
- package/app/connection/socketController.js +2243 -0
- package/app/controllers/messageController.js +7 -0
- package/app/controllers/messagePipeline/commandMiddleware.js +146 -0
- package/app/controllers/messagePipeline/conversationMiddleware.js +183 -0
- package/app/controllers/messagePipeline/messagePipelineMiddlewares.test.js +522 -0
- package/app/controllers/messagePipeline/postProcessingMiddleware.js +41 -0
- package/app/controllers/messagePipeline/preProcessingMiddlewares.js +166 -0
- package/app/controllers/messageProcessingPipeline.js +699 -0
- package/app/modules/adminModule/AGENT.md +4056 -0
- package/app/modules/adminModule/adminAiHelpService.js +56 -0
- package/app/modules/adminModule/adminConfigRuntime.js +177 -0
- package/app/modules/adminModule/commandConfig.json +7122 -0
- package/app/modules/adminModule/groupCommandHandlers.js +1823 -0
- package/app/modules/adminModule/groupCommandHandlers.test.js +350 -0
- package/app/modules/adminModule/groupEventHandlers.js +399 -0
- package/app/modules/aiModule/AGENT.md +547 -0
- package/app/modules/aiModule/aiAiHelpService.js +14 -0
- package/app/modules/aiModule/aiConfigRuntime.js +135 -0
- package/app/modules/aiModule/catCommand.js +967 -0
- package/app/modules/aiModule/commandConfig.json +981 -0
- package/app/modules/analyticsModule/messageAnalysisEventRepository.js +83 -0
- package/app/modules/gameModule/AGENT.md +196 -0
- package/app/modules/gameModule/commandConfig.json +366 -0
- package/app/modules/gameModule/diceCommand.js +42 -0
- package/app/modules/gameModule/gameAiHelpService.js +14 -0
- package/app/modules/gameModule/gameConfigRuntime.js +68 -0
- package/app/modules/menuModule/AGENT.md +205 -0
- package/app/modules/menuModule/commandConfig.json +366 -0
- package/app/modules/menuModule/common.js +316 -0
- package/app/modules/menuModule/menuAiHelpService.js +14 -0
- package/app/modules/menuModule/menuConfigRuntime.js +68 -0
- package/app/modules/menuModule/menus.js +66 -0
- package/app/modules/playModule/AGENT.md +321 -0
- package/app/modules/playModule/commandConfig.json +584 -0
- package/app/modules/playModule/playAiHelpService.js +14 -0
- package/app/modules/playModule/playCommand.js +1417 -0
- package/app/modules/playModule/playConfigRuntime.js +68 -0
- package/app/modules/quoteModule/AGENT.md +199 -0
- package/app/modules/quoteModule/commandConfig.json +366 -0
- package/app/modules/quoteModule/quoteAiHelpService.js +14 -0
- package/app/modules/quoteModule/quoteCommand.js +842 -0
- package/app/modules/quoteModule/quoteConfigRuntime.js +68 -0
- package/app/modules/rpgPokemonModule/AGENT.md +229 -0
- package/app/modules/rpgPokemonModule/commandConfig.json +386 -0
- package/app/modules/rpgPokemonModule/rpgBattleCanvasRenderer.js +795 -0
- package/app/modules/rpgPokemonModule/rpgBattleService.js +2110 -0
- package/app/modules/rpgPokemonModule/rpgBattleService.test.js +770 -0
- package/app/modules/rpgPokemonModule/rpgEvolutionUtils.js +22 -0
- package/app/modules/rpgPokemonModule/rpgPokemonAiHelpService.js +14 -0
- package/app/modules/rpgPokemonModule/rpgPokemonCommand.js +174 -0
- package/app/modules/rpgPokemonModule/rpgPokemonConfigRuntime.js +68 -0
- package/app/modules/rpgPokemonModule/rpgPokemonDomain.js +192 -0
- package/app/modules/rpgPokemonModule/rpgPokemonDomain.test.js +93 -0
- package/app/modules/rpgPokemonModule/rpgPokemonEvolution.test.js +46 -0
- package/app/modules/rpgPokemonModule/rpgPokemonMessages.js +746 -0
- package/app/modules/rpgPokemonModule/rpgPokemonRepository.js +1847 -0
- package/app/modules/rpgPokemonModule/rpgPokemonService.js +6839 -0
- package/app/modules/rpgPokemonModule/rpgProfileCanvasRenderer.js +354 -0
- package/app/modules/statsModule/AGENT.md +320 -0
- package/app/modules/statsModule/commandConfig.json +540 -0
- package/app/modules/statsModule/globalRankingCommand.js +64 -0
- package/app/modules/statsModule/rankingCommand.js +41 -0
- package/app/modules/statsModule/rankingCommon.js +1305 -0
- package/app/modules/statsModule/statsAiHelpService.js +14 -0
- package/app/modules/statsModule/statsConfigRuntime.js +68 -0
- package/app/modules/stickerModule/AGENT.md +692 -0
- package/app/modules/stickerModule/addStickerMetadata.js +239 -0
- package/app/modules/stickerModule/commandConfig.json +1216 -0
- package/app/modules/stickerModule/convertToWebp.js +367 -0
- package/app/modules/stickerModule/stickerAiHelpService.js +14 -0
- package/app/modules/stickerModule/stickerCommand.js +446 -0
- package/app/modules/stickerModule/stickerConfigRuntime.js +68 -0
- package/app/modules/stickerModule/stickerConvertCommand.js +159 -0
- package/app/modules/stickerModule/stickerTextCommand.js +653 -0
- package/app/modules/stickerPackModule/AGENT.md +215 -0
- package/app/modules/stickerPackModule/autoPackCollectorRuntime.js +20 -0
- package/app/modules/stickerPackModule/autoPackCollectorService.js +357 -0
- package/app/modules/stickerPackModule/commandConfig.json +387 -0
- package/app/modules/stickerPackModule/domainEventOutboxRepository.js +227 -0
- package/app/modules/stickerPackModule/domainEvents.js +52 -0
- package/app/modules/stickerPackModule/semanticReclassificationEngine.js +429 -0
- package/app/modules/stickerPackModule/semanticReclassificationEngine.test.js +75 -0
- package/app/modules/stickerPackModule/semanticThemeClusterService.js +544 -0
- package/app/modules/stickerPackModule/stickerAssetClassificationRepository.js +400 -0
- package/app/modules/stickerPackModule/stickerAssetRepository.js +400 -0
- package/app/modules/stickerPackModule/stickerAssetReprocessQueueRepository.js +175 -0
- package/app/modules/stickerPackModule/stickerAutoPackByTagsRuntime.js +3702 -0
- package/app/modules/stickerPackModule/stickerClassificationBackgroundRuntime.js +559 -0
- package/app/modules/stickerPackModule/stickerClassificationService.js +557 -0
- package/app/modules/stickerPackModule/stickerDedicatedTaskWorkerRuntime.js +249 -0
- package/app/modules/stickerPackModule/stickerDomainEventBus.js +65 -0
- package/app/modules/stickerPackModule/stickerDomainEventConsumerRuntime.js +208 -0
- package/app/modules/stickerPackModule/stickerMarketplaceDriftService.js +99 -0
- package/app/modules/stickerPackModule/stickerObjectStorageService.js +285 -0
- package/app/modules/stickerPackModule/stickerPackAiHelpService.js +14 -0
- package/app/modules/stickerPackModule/stickerPackCommandHandlers.js +1148 -0
- package/app/modules/stickerPackModule/stickerPackConfigRuntime.js +68 -0
- package/app/modules/stickerPackModule/stickerPackEngagementRepository.js +152 -0
- package/app/modules/stickerPackModule/stickerPackErrors.js +30 -0
- package/app/modules/stickerPackModule/stickerPackInteractionEventRepository.js +101 -0
- package/app/modules/stickerPackModule/stickerPackItemRepository.js +432 -0
- package/app/modules/stickerPackModule/stickerPackMarketplaceService.js +313 -0
- package/app/modules/stickerPackModule/stickerPackMessageService.js +268 -0
- package/app/modules/stickerPackModule/stickerPackRepository.js +450 -0
- package/app/modules/stickerPackModule/stickerPackScoreSnapshotRepository.js +179 -0
- package/app/modules/stickerPackModule/stickerPackScoreSnapshotRuntime.js +271 -0
- package/app/modules/stickerPackModule/stickerPackService.js +733 -0
- package/app/modules/stickerPackModule/stickerPackServiceRuntime.js +32 -0
- package/app/modules/stickerPackModule/stickerPackUtils.js +107 -0
- package/app/modules/stickerPackModule/stickerStorageService.js +559 -0
- package/app/modules/stickerPackModule/stickerWorkerPipelineRuntime.js +242 -0
- package/app/modules/stickerPackModule/stickerWorkerTaskQueueRepository.js +242 -0
- package/app/modules/systemMetricsModule/AGENT.md +193 -0
- package/app/modules/systemMetricsModule/commandConfig.json +344 -0
- package/app/modules/systemMetricsModule/pingCommand.js +399 -0
- package/app/modules/systemMetricsModule/systemMetricsAiHelpService.js +14 -0
- package/app/modules/systemMetricsModule/systemMetricsConfigRuntime.js +68 -0
- package/app/modules/tiktokModule/AGENT.md +196 -0
- package/app/modules/tiktokModule/commandConfig.json +366 -0
- package/app/modules/tiktokModule/tiktokAiHelpService.js +14 -0
- package/app/modules/tiktokModule/tiktokCommand.js +716 -0
- package/app/modules/tiktokModule/tiktokConfigRuntime.js +68 -0
- package/app/modules/userModule/AGENT.md +200 -0
- package/app/modules/userModule/commandConfig.json +386 -0
- package/app/modules/userModule/userAiHelpService.js +14 -0
- package/app/modules/userModule/userCommand.js +1155 -0
- package/app/modules/userModule/userConfigRuntime.js +68 -0
- package/app/modules/waifuPicsModule/AGENT.md +431 -0
- package/app/modules/waifuPicsModule/commandConfig.json +780 -0
- package/app/modules/waifuPicsModule/waifuPicsAiHelpService.js +14 -0
- package/app/modules/waifuPicsModule/waifuPicsCommand.js +586 -0
- package/app/modules/waifuPicsModule/waifuPicsConfigRuntime.js +68 -0
- package/app/observability/metrics.js +766 -0
- package/app/services/ai/aiHelpResponseCacheRepository.js +280 -0
- package/app/services/ai/aiLearningRepository.js +400 -0
- package/app/services/ai/commandConfigEnrichmentRepository.js +769 -0
- package/app/services/ai/commandConfigEnrichmentService.js +452 -0
- package/app/services/ai/commandConfigValidationService.js +443 -0
- package/app/services/ai/commandToolBuilderService.js +192 -0
- package/app/services/ai/conversationRouterService.js +516 -0
- package/app/services/ai/geminiService.js +115 -0
- package/app/services/ai/geminiService.test.js +87 -0
- package/app/services/ai/globalModuleAiHelpService.js +1412 -0
- package/app/services/ai/globalToolCallingService.js +203 -0
- package/app/services/ai/messageCommandExecutionService.js +391 -0
- package/app/services/ai/moduleAiHelpCoreService.js +1099 -0
- package/app/services/ai/moduleAiHelpWrapperFactory.js +65 -0
- package/app/services/ai/moduleCommandConfigRuntimeService.js +113 -0
- package/app/services/ai/moduleToolExecutorService.js +464 -0
- package/app/services/ai/moduleToolRegistryService.js +178 -0
- package/app/services/ai/toolCandidateSelectorService.js +781 -0
- package/app/services/auth/googleWebLinkService.js +80 -0
- package/app/services/auth/whatsappLoginLinkService.js +230 -0
- package/app/services/external/pokeApiService.js +398 -0
- package/app/services/group/groupMetadataService.js +311 -0
- package/app/services/infra/dbWriteQueue.js +874 -0
- package/app/services/infra/featureFlagService.js +131 -0
- package/app/services/infra/queueUtils.js +55 -0
- package/app/services/messaging/captchaService.js +491 -0
- package/app/services/messaging/messagePersistenceService.js +1 -0
- package/app/services/messaging/newsBroadcastService.js +347 -0
- package/app/services/sticker/stickerFocusService.js +347 -0
- package/app/services/sticker/stickerFocusService.test.js +43 -0
- package/app/store/aiPromptStore.js +38 -0
- package/app/store/conversationSessionStore.js +131 -0
- package/app/store/groupConfigStore.js +58 -0
- package/app/store/premiumUserStore.js +54 -0
- package/app/utils/antiLink/antiLinkModule.js +700 -0
- package/app/utils/http/getImageBufferModule.js +18 -0
- package/app/utils/json/jsonSanitizer.js +113 -0
- package/app/utils/json/jsonSanitizer.test.js +40 -0
- package/app/utils/systemMetrics/systemMetricsModule.js +88 -0
- package/app/workers/aiLearningWorker.js +605 -0
- package/app/workers/commandConfigEnrichmentWorker.js +242 -0
- package/database/index.js +2075 -0
- package/database/init.js +151 -0
- package/database/migrations/.gitkeep +0 -0
- package/database/migrations/20260307_d0_hardening_down.sql +64 -0
- package/database/migrations/20260307_d0_hardening_up.sql +79 -0
- package/database/migrations/20260307_d1_terms_acceptance_down.sql +11 -0
- package/database/migrations/20260307_d1_terms_acceptance_up.sql +37 -0
- package/database/migrations/20260307_d2_auth_hardening_down.sql +75 -0
- package/database/migrations/20260307_d2_auth_hardening_up.sql +100 -0
- package/database/migrations/20260314_d7_canonical_sender_down.sql +53 -0
- package/database/migrations/20260314_d7_canonical_sender_up.sql +114 -0
- package/database/migrations/20260406_d30_security_analytics_down.sql +95 -0
- package/database/migrations/20260406_d30_security_analytics_up.sql +292 -0
- package/database/migrations/20260407_d31_web_google_session_token_hardening_down.sql +2 -0
- package/database/migrations/20260407_d31_web_google_session_token_hardening_up.sql +17 -0
- package/database/migrations/20260408_d32_ai_help_response_cache_down.sql +1 -0
- package/database/migrations/20260408_d32_ai_help_response_cache_up.sql +22 -0
- package/database/migrations/20260409_d33_ai_learning_tables_down.sql +4 -0
- package/database/migrations/20260409_d33_ai_learning_tables_up.sql +52 -0
- package/database/migrations/20260410_d34_command_config_enrichment_down.sql +3 -0
- package/database/migrations/20260410_d34_command_config_enrichment_up.sql +48 -0
- package/database/schema.sql +1186 -0
- package/docker-compose.yml +104 -0
- package/docs/audits/stickerCatalogController-out-of-scope.md +103 -0
- package/docs/audits/stickerCatalogController-symbols.md +58 -0
- package/docs/compliance/acceptable-use-policy-2026-03-07.md +35 -0
- package/docs/compliance/dpa-b2b-standard-2026-03-07.md +80 -0
- package/docs/compliance/monthly-compliance-checklist-2026-03-07.md +88 -0
- package/docs/compliance/notice-and-takedown-policy-2026-03-07.md +34 -0
- package/docs/compliance/privacy-policy-2026-03-07.md +75 -0
- package/docs/compliance/subprocessors-inventory-2026-03-07.md +16 -0
- package/docs/database/production-db-evolution-runbook-2026q1.md +365 -0
- package/docs/security/dsar-lgpd-runbook-2026-03-07.md +86 -0
- package/docs/security/incident-response-lgpd-anpd-runbook-2026-03-07.md +77 -0
- package/docs/security/network-hardening-runbook-2026-03-07.md +137 -0
- package/docs/seo/omnizap-seo-playbook-br-2026-02-28.md +238 -0
- package/docs/seo/satellite-page-template.md +116 -0
- package/docs/seo/satellite-pages-phase1.json +364 -0
- package/docs/wiki/Home.md +120 -0
- package/docs/wiki/pair-extraordinaire-2026-03-08.md +3 -0
- package/docs/wiki/recent-changes-2026-03-08.md +47 -0
- package/ecosystem.prod.config.cjs +135 -0
- package/eslint.config.js +89 -0
- package/index.js +488 -0
- package/ml/clip_classifier/Dockerfile +18 -0
- package/ml/clip_classifier/README.md +118 -0
- package/ml/clip_classifier/adaptive_scoring.py +40 -0
- package/ml/clip_classifier/classifier.py +654 -0
- package/ml/clip_classifier/embedding_store.py +481 -0
- package/ml/clip_classifier/env_loader.py +15 -0
- package/ml/clip_classifier/llm_label_expander.py +144 -0
- package/ml/clip_classifier/main.py +213 -0
- package/ml/clip_classifier/requirements.txt +10 -0
- package/ml/clip_classifier/similarity_engine.py +74 -0
- package/new-logo.png +0 -0
- package/observability/alert-rules.yml +60 -0
- package/observability/grafana/dashboards/omnizap-mysql.json +136 -0
- package/observability/grafana/dashboards/omnizap-overview.json +170 -0
- package/observability/grafana/provisioning/dashboards/dashboards.yml +11 -0
- package/observability/grafana/provisioning/datasources/datasources.yml +15 -0
- package/observability/loki-config.yml +38 -0
- package/observability/mysql-setup.sql +46 -0
- package/observability/prometheus.yml +35 -0
- package/observability/promtail-config.yml +84 -0
- package/observability/sticker-catalog-slo.md +83 -0
- package/observability/sticker-scale-hardening-rollout.md +128 -0
- package/package.json +144 -0
- package/public/apple-touch-icon.png +0 -0
- package/public/assets/css/commands-react.input.css +71 -0
- package/public/assets/css/create-pack-react.input.css +31 -0
- package/public/assets/css/home-react.input.css +106 -0
- package/public/assets/css/login-react.input.css +58 -0
- package/public/assets/css/stickers-react.input.css +18 -0
- package/public/assets/css/terms-react.input.css +115 -0
- package/public/assets/css/user-react.input.css +57 -0
- package/public/assets/images/brand-icon-192.png +0 -0
- package/public/assets/images/brand-logo-128.webp +0 -0
- package/public/assets/images/hero-banner-1280.jpg +0 -0
- package/public/comandos/commands-catalog.json +4517 -0
- package/public/css/api-docs.css +161 -0
- package/public/css/stickers-admin.css +1288 -0
- package/public/css/styles.css +679 -0
- package/public/css/systemadm/admin.css +474 -0
- package/public/css/systemadm/base.css +73 -0
- package/public/css/systemadm/components.css +662 -0
- package/public/css/systemadm/layout.css +229 -0
- package/public/css/systemadm/tokens.css +56 -0
- 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 +235 -0
- package/public/js/apps/commandsReactApp.js +528 -0
- package/public/js/apps/createPackApp.js +1646 -0
- package/public/js/apps/homeReactApp.js +942 -0
- package/public/js/apps/loginReactApp.js +496 -0
- package/public/js/apps/stickersAdminApp.js +1753 -0
- package/public/js/apps/stickersApp.js +3797 -0
- package/public/js/apps/termsReactApp.js +528 -0
- package/public/js/apps/userApp.js +2540 -0
- package/public/js/apps/userProfile/actions.js +66 -0
- package/public/js/apps/userReactApp.js +547 -0
- package/public/js/catalog.js +950 -0
- package/public/pages/api-docs.html +40 -0
- package/public/pages/aup.html +158 -0
- package/public/pages/comandos.html +41 -0
- package/public/pages/dpa.html +227 -0
- package/public/pages/home.html +45 -0
- package/public/pages/licenca.html +182 -0
- package/public/pages/login.html +40 -0
- package/public/pages/notice-and-takedown.html +234 -0
- package/public/pages/politica-de-privacidade.html +251 -0
- package/public/pages/seo-bot-whatsapp-para-grupo.html +350 -0
- package/public/pages/seo-bot-whatsapp-sem-programar.html +350 -0
- package/public/pages/seo-como-automatizar-avisos-no-whatsapp.html +350 -0
- package/public/pages/seo-como-criar-comandos-whatsapp.html +350 -0
- package/public/pages/seo-como-evitar-spam-no-whatsapp.html +350 -0
- package/public/pages/seo-como-moderar-grupo-whatsapp.html +350 -0
- package/public/pages/seo-como-organizar-comunidade-whatsapp.html +350 -0
- package/public/pages/seo-melhor-bot-whatsapp-para-grupos.html +350 -0
- package/public/pages/stickers-admin.html +31 -0
- package/public/pages/stickers-create.html +41 -0
- package/public/pages/stickers.html +45 -0
- package/public/pages/suboperadores.html +237 -0
- package/public/pages/termos-de-uso-texto-integral.html +241 -0
- package/public/pages/termos-de-uso.html +41 -0
- package/public/pages/user-password-reset.html +32 -0
- package/public/pages/user-systemadm.html +508 -0
- package/public/pages/user.html +39 -0
- package/public/robots.txt +9 -0
- package/public/site.webmanifest +24 -0
- package/public/sitemap.xml +98 -0
- package/schemas/command-config.schema.json +582 -0
- package/scripts/baileys-compat-smoke.mjs +12 -0
- package/scripts/cache-bust.mjs +142 -0
- package/scripts/deploy.sh +916 -0
- package/scripts/email-broadcast-terms-update.mjs +170 -0
- package/scripts/enrich-command-discovery-fields.mjs +286 -0
- package/scripts/generate-command-config-schema.mjs +273 -0
- package/scripts/generate-commands-catalog.mjs +308 -0
- package/scripts/generate-module-agents.mjs +631 -0
- package/scripts/generate-seo-satellite-pages.mjs +400 -0
- package/scripts/github-deploy-notify.mjs +174 -0
- package/scripts/github-release-notify.mjs +219 -0
- package/scripts/release.sh +599 -0
- package/scripts/run-codeql-local.sh +116 -0
- package/scripts/run-prettier-all.mjs +25 -0
- package/scripts/security-smoketest.mjs +581 -0
- package/scripts/sticker-catalog-loadtest.mjs +210 -0
- package/scripts/sticker-worker-task.mjs +119 -0
- package/scripts/sync-readme-snapshot.mjs +133 -0
- package/scripts/validate-command-config-schema.mjs +130 -0
- package/scripts/validate-command-configs.mjs +15 -0
- package/scripts/wiki-sync.sh +191 -0
- package/server/auth/googleWebAuth/googleWebAuthRuntime.js +62 -0
- package/server/auth/googleWebAuth/googleWebAuthService.js +807 -0
- package/server/auth/jwt/webJwtService.js +147 -0
- package/server/auth/stickerCatalogAuthContext.js +165 -0
- package/server/auth/termsAcceptance/termsAcceptanceHandler.js +189 -0
- package/server/auth/userPassword/index.js +14 -0
- package/server/auth/userPassword/userPasswordAuthService.js +422 -0
- package/server/auth/userPassword/userPasswordCrypto.js +199 -0
- package/server/auth/userPassword/userPasswordCrypto.test.js +76 -0
- package/server/auth/userPassword/userPasswordRecoveryService.js +728 -0
- package/server/auth/validation/authSchemas.js +236 -0
- package/server/auth/webAccount/webAccountHandlers.js +1434 -0
- package/server/controllers/admin/adminBanService.js +138 -0
- package/server/controllers/admin/adminPanelHandlers.js +2083 -0
- package/server/controllers/admin/stickerCatalogAdminContext.js +17 -0
- package/server/controllers/admin/systemAdminController.js +201 -0
- package/server/controllers/email/emailAutomationController.js +239 -0
- package/server/controllers/metricsController.js +21 -0
- package/server/controllers/seo/stickerCatalogSeoContext.js +514 -0
- package/server/controllers/sticker/nonCatalogHandlers.js +303 -0
- package/server/controllers/sticker/stickerCatalogController.js +4700 -0
- package/server/controllers/system/contactController.js +115 -0
- package/server/controllers/system/githubController.js +137 -0
- package/server/controllers/system/stickerCatalogSystemContext.js +758 -0
- package/server/controllers/system/storageController.js +154 -0
- package/server/controllers/system/systemController.js +135 -0
- package/server/controllers/system/systemMetricsController.js +156 -0
- package/server/controllers/system/visitController.js +90 -0
- package/server/controllers/userController.js +145 -0
- package/server/email/emailAutomationRuntime.js +225 -0
- package/server/email/emailAutomationService.js +125 -0
- package/server/email/emailOutboxRepository.js +282 -0
- package/server/email/emailTemplateService.js +480 -0
- package/server/email/emailTransportService.js +156 -0
- package/server/http/clientIp.js +95 -0
- package/server/http/httpRequestUtils.js +262 -0
- package/server/http/httpRequestUtils.test.js +80 -0
- package/server/http/httpServer.js +180 -0
- package/server/http/requestContext.js +20 -0
- package/server/http/siteRoutingUtils.js +87 -0
- package/server/index.js +1 -0
- package/server/middleware/cachePolicy.js +26 -0
- package/server/middleware/cachePolicyHelpers.js +1 -0
- package/server/middleware/endpointRateLimit.js +181 -0
- package/server/middleware/rateLimit.js +70 -0
- package/server/middleware/requireAdminAuth.js +48 -0
- package/server/middleware/securityHeaders.js +97 -0
- package/server/routes/admin/systemAdminRouter.js +64 -0
- package/server/routes/email/emailAutomationRouter.js +46 -0
- package/server/routes/health/healthRouter.js +41 -0
- package/server/routes/indexRouter.js +234 -0
- package/server/routes/metrics/metricsRouter.js +58 -0
- package/server/routes/static/staticPageRouter.js +134 -0
- package/server/routes/sticker/catalogHandlers/catalogAdminHttp.js +105 -0
- package/server/routes/sticker/catalogHandlers/catalogAuthHttp.js +77 -0
- package/server/routes/sticker/catalogHandlers/catalogPublicHttp.js +120 -0
- package/server/routes/sticker/catalogHandlers/catalogUploadHttp.js +83 -0
- package/server/routes/sticker/catalogRouter.js +77 -0
- package/server/routes/sticker/stickerApiRouter.js +84 -0
- package/server/routes/sticker/stickerDataRouter.js +145 -0
- package/server/routes/sticker/stickerSiteRouter.js +43 -0
- package/server/routes/user/userApiPaths.js +66 -0
- package/server/routes/user/userRouter.js +65 -0
- package/server/utils/safePath.js +26 -0
- package/utils/logger/loggerModule.js +35 -0
- 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
|
+
}
|