@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,692 @@
|
|
|
1
|
+
import { baileysGroupsLogger as logger } from './loggerConfig.js';
|
|
2
|
+
import { findById, findAll, TABLES } from '../../database/index.js';
|
|
3
|
+
import { isGroupJid, isLidJid, isSameJidUser, isWhatsAppJid, normalizeJid } from './baileysConfig.js';
|
|
4
|
+
import { parseParticipantsFromDb } from '../services/group/groupMetadataService.js';
|
|
5
|
+
import { extractUserIdInfo, resolveUserIdCached } from './baileysConfig.js';
|
|
6
|
+
import { getActiveSocket, runSocketMethod } from './baileysConfig.js';
|
|
7
|
+
|
|
8
|
+
const USER_ID_DIGITS_MIN = 10;
|
|
9
|
+
const USER_ID_DIGITS_MAX = 15;
|
|
10
|
+
const GROUP_ID_SUFFIX = '@g.us';
|
|
11
|
+
|
|
12
|
+
const _toNonEmptyString = (value) => {
|
|
13
|
+
if (typeof value !== 'string') return '';
|
|
14
|
+
return value.trim();
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const _normalizeAnyJid = (value) => {
|
|
18
|
+
const raw = _toNonEmptyString(value);
|
|
19
|
+
if (!raw) return '';
|
|
20
|
+
if (!raw.includes('@')) return raw;
|
|
21
|
+
return normalizeJid(raw) || raw;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const _normalizeGroupId = (groupId) => {
|
|
25
|
+
const normalized = _normalizeAnyJid(groupId);
|
|
26
|
+
if (!normalized) return '';
|
|
27
|
+
if (isGroupJid(normalized)) return normalized;
|
|
28
|
+
if (normalized.endsWith(GROUP_ID_SUFFIX)) return normalized;
|
|
29
|
+
return '';
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const _normalizeUserIdCandidate = (value) => {
|
|
33
|
+
const raw = _toNonEmptyString(value);
|
|
34
|
+
if (!raw) return '';
|
|
35
|
+
|
|
36
|
+
const jidCandidate = _normalizeAnyJid(raw);
|
|
37
|
+
if (jidCandidate && (isWhatsAppJid(jidCandidate) || isLidJid(jidCandidate))) {
|
|
38
|
+
return jidCandidate;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const digits = _normalizeDigits(raw);
|
|
42
|
+
if (digits.length >= USER_ID_DIGITS_MIN && digits.length <= USER_ID_DIGITS_MAX) {
|
|
43
|
+
return normalizeJid(`${digits}@s.whatsapp.net`) || `${digits}@s.whatsapp.net`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return jidCandidate;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const _collectUserIdCandidates = (value) => {
|
|
50
|
+
if (!value) return [];
|
|
51
|
+
|
|
52
|
+
const candidates = [];
|
|
53
|
+
const pushCandidate = (candidate) => {
|
|
54
|
+
const normalized = _normalizeUserIdCandidate(candidate);
|
|
55
|
+
if (!normalized) return;
|
|
56
|
+
if (candidates.some((existing) => _areUserIdsEquivalent(existing, normalized))) return;
|
|
57
|
+
candidates.push(normalized);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const info = extractUserIdInfo(value);
|
|
61
|
+
pushCandidate(resolveUserIdCached(info));
|
|
62
|
+
pushCandidate(info.jid);
|
|
63
|
+
pushCandidate(info.lid);
|
|
64
|
+
pushCandidate(info.participantAlt);
|
|
65
|
+
pushCandidate(info.raw);
|
|
66
|
+
|
|
67
|
+
if (typeof value === 'object') {
|
|
68
|
+
pushCandidate(value.id);
|
|
69
|
+
pushCandidate(value.jid);
|
|
70
|
+
pushCandidate(value.lid);
|
|
71
|
+
pushCandidate(value.participant);
|
|
72
|
+
pushCandidate(value.participantAlt);
|
|
73
|
+
pushCandidate(value.remoteJid);
|
|
74
|
+
pushCandidate(value.remoteJidAlt);
|
|
75
|
+
} else {
|
|
76
|
+
pushCandidate(value);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return candidates;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const _extractParticipantCandidates = (participant) => {
|
|
83
|
+
if (!participant) return [];
|
|
84
|
+
const raw = typeof participant === 'string' ? { id: participant } : participant;
|
|
85
|
+
|
|
86
|
+
const info = extractUserIdInfo(raw);
|
|
87
|
+
const candidates = [];
|
|
88
|
+
const pushCandidate = (candidate) => {
|
|
89
|
+
const normalized = _normalizeUserIdCandidate(candidate);
|
|
90
|
+
if (!normalized) return;
|
|
91
|
+
if (candidates.some((existing) => _areUserIdsEquivalent(existing, normalized))) return;
|
|
92
|
+
candidates.push(normalized);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
pushCandidate(resolveUserIdCached(info));
|
|
96
|
+
pushCandidate(raw.id);
|
|
97
|
+
pushCandidate(raw.jid);
|
|
98
|
+
pushCandidate(raw.lid);
|
|
99
|
+
pushCandidate(raw.participant);
|
|
100
|
+
pushCandidate(raw.participantAlt);
|
|
101
|
+
pushCandidate(info.jid);
|
|
102
|
+
pushCandidate(info.lid);
|
|
103
|
+
pushCandidate(info.participantAlt);
|
|
104
|
+
pushCandidate(info.raw);
|
|
105
|
+
|
|
106
|
+
return candidates;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const _resolveCanonicalCachedUserId = (value) => {
|
|
110
|
+
const normalized = _normalizeUserIdCandidate(value);
|
|
111
|
+
if (!normalized) return '';
|
|
112
|
+
const resolved = resolveUserIdCached({
|
|
113
|
+
jid: normalized,
|
|
114
|
+
lid: normalized,
|
|
115
|
+
participantAlt: normalized,
|
|
116
|
+
});
|
|
117
|
+
return _normalizeUserIdCandidate(resolved || normalized);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const _areUserIdsEquivalent = (leftValue, rightValue) => {
|
|
121
|
+
const left = _normalizeUserIdCandidate(leftValue);
|
|
122
|
+
const right = _normalizeUserIdCandidate(rightValue);
|
|
123
|
+
if (!left || !right) return false;
|
|
124
|
+
if (left === right) return true;
|
|
125
|
+
|
|
126
|
+
if (left.includes('@') && right.includes('@')) {
|
|
127
|
+
try {
|
|
128
|
+
if (isSameJidUser(left, right)) return true;
|
|
129
|
+
} catch {
|
|
130
|
+
// ignora erro de comparação em JID inválido e segue para os fallbacks
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const leftCanonical = _resolveCanonicalCachedUserId(left);
|
|
135
|
+
const rightCanonical = _resolveCanonicalCachedUserId(right);
|
|
136
|
+
if (leftCanonical && rightCanonical && leftCanonical === rightCanonical) return true;
|
|
137
|
+
|
|
138
|
+
const leftDigits = _normalizeDigits(left);
|
|
139
|
+
const rightDigits = _normalizeDigits(right);
|
|
140
|
+
if (!leftDigits || !rightDigits) return false;
|
|
141
|
+
|
|
142
|
+
return leftDigits === rightDigits || leftDigits.endsWith(rightDigits) || rightDigits.endsWith(leftDigits);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const _isParticipantAdmin = (participant) => Boolean(participant && (participant.admin === 'admin' || participant.admin === 'superadmin' || participant.isAdmin === true));
|
|
146
|
+
|
|
147
|
+
const _isSocketLike = (value, methodName) => {
|
|
148
|
+
if (!value || typeof value !== 'object') return false;
|
|
149
|
+
if (methodName && typeof value[methodName] === 'function') return true;
|
|
150
|
+
if (typeof value.sendMessage === 'function') return true;
|
|
151
|
+
if (value.ws || value.ev) return true;
|
|
152
|
+
return false;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const _resolveSocketAndArgs = (methodName, inputArgs = []) => {
|
|
156
|
+
const [firstArg, ...remaining] = inputArgs;
|
|
157
|
+
if (_isSocketLike(firstArg, methodName)) {
|
|
158
|
+
return {
|
|
159
|
+
sock: firstArg,
|
|
160
|
+
args: remaining,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
sock: null,
|
|
166
|
+
args: inputArgs,
|
|
167
|
+
};
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const _normalizeParticipantsInput = (participants = []) => {
|
|
171
|
+
if (!Array.isArray(participants)) return [];
|
|
172
|
+
const normalized = [];
|
|
173
|
+
for (const participant of participants) {
|
|
174
|
+
const candidate = extractUserId(participant) || _normalizeUserIdCandidate(participant);
|
|
175
|
+
if (!candidate) continue;
|
|
176
|
+
if (normalized.some((existing) => _areUserIdsEquivalent(existing, candidate))) continue;
|
|
177
|
+
normalized.push(candidate);
|
|
178
|
+
}
|
|
179
|
+
return normalized;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const _normalizeNumberOrNull = (value) => {
|
|
183
|
+
const parsed = Number(value);
|
|
184
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Valida um ID de grupo ou usuário.
|
|
189
|
+
* @param {string} id - O ID a ser validado.
|
|
190
|
+
* @param {string} type - O tipo de ID ('Grupo' ou 'Usuário').
|
|
191
|
+
* @returns {boolean} True se o ID for válido, false caso contrário.
|
|
192
|
+
*/
|
|
193
|
+
export function _isValidId(id, type = 'ID') {
|
|
194
|
+
const normalized = _toNonEmptyString(id);
|
|
195
|
+
if (!normalized) {
|
|
196
|
+
logger.warn(`Tentativa de operação com ${type} inválido.`, { id });
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (type === 'Grupo' && !_normalizeGroupId(normalized)) {
|
|
201
|
+
logger.warn('Tentativa de operação com ID de grupo inválido.', { id });
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Retorna todos os dados de um grupo específico.
|
|
210
|
+
* @param {string} groupId - O ID do grupo.
|
|
211
|
+
* @returns {object|null} Os dados do grupo ou null se não encontrado ou se o ID for inválido.
|
|
212
|
+
*/
|
|
213
|
+
export async function getGroupInfo(groupId) {
|
|
214
|
+
return await getGroupInfoAsync(groupId);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Retorna o assunto (nome) de um grupo específico.
|
|
219
|
+
* @param {string} groupId - O ID do grupo.
|
|
220
|
+
* @returns {string|null} O assunto do grupo ou null se não encontrado.
|
|
221
|
+
*/
|
|
222
|
+
export async function getGroupSubject(groupId) {
|
|
223
|
+
const group = await getGroupInfoAsync(groupId);
|
|
224
|
+
return group?.subject || null;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Retorna a lista de participantes de um grupo específico.
|
|
229
|
+
* @param {string} groupId - O ID do grupo.
|
|
230
|
+
* @returns {Array<object>|null} A lista de participantes ou null se não encontrado.
|
|
231
|
+
*/
|
|
232
|
+
export async function getGroupParticipants(groupId) {
|
|
233
|
+
return await getGroupParticipantsAsync(groupId);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Extrai o ID do usuário (canônico quando possível).
|
|
238
|
+
* @param {object|string} userObj - Objeto de mensagem ou string do ID.
|
|
239
|
+
* @returns {string|null} O ID do usuário ou null se não encontrado.
|
|
240
|
+
*/
|
|
241
|
+
export function extractUserId(userObj) {
|
|
242
|
+
const candidates = _collectUserIdCandidates(userObj);
|
|
243
|
+
return candidates[0] || null;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Verifica se um usuário é administrador em um grupo específico.
|
|
248
|
+
* Aceita tanto string quanto objeto de mensagem para userId.
|
|
249
|
+
* @param {string} groupId - O ID do grupo.
|
|
250
|
+
* @param {string|object} userIdOrObj - O ID do usuário ou objeto de mensagem.
|
|
251
|
+
* @returns {boolean} True se o usuário for admin, false caso contrário.
|
|
252
|
+
*/
|
|
253
|
+
export async function isUserAdmin(groupId, userIdOrObj) {
|
|
254
|
+
return await isUserAdminAsync(groupId, userIdOrObj);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export function _normalizeDigits(str) {
|
|
258
|
+
if (!str || typeof str !== 'string') return '';
|
|
259
|
+
return str.replace(/\D/g, '');
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export function _matchesParticipantId(participant, userIdOrObj) {
|
|
263
|
+
if (!participant || !userIdOrObj) return false;
|
|
264
|
+
const participantCandidates = _extractParticipantCandidates(participant);
|
|
265
|
+
if (!participantCandidates.length) return false;
|
|
266
|
+
|
|
267
|
+
const userCandidates = _collectUserIdCandidates(userIdOrObj);
|
|
268
|
+
if (!userCandidates.length) return false;
|
|
269
|
+
|
|
270
|
+
return participantCandidates.some((participantId) => userCandidates.some((userId) => _areUserIdsEquivalent(participantId, userId)));
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Busca as informações do grupo no banco de dados.
|
|
275
|
+
* @param {string} groupId
|
|
276
|
+
* @returns {Promise<object|null>} objeto do grupo ou null
|
|
277
|
+
*/
|
|
278
|
+
export async function getGroupInfoAsync(groupId) {
|
|
279
|
+
const normalizedGroupId = _normalizeGroupId(groupId);
|
|
280
|
+
if (!_isValidId(normalizedGroupId, 'Grupo')) return null;
|
|
281
|
+
|
|
282
|
+
try {
|
|
283
|
+
const row = await findById(TABLES.GROUPS_METADATA, normalizedGroupId);
|
|
284
|
+
if (!row) return null;
|
|
285
|
+
const data = Array.isArray(row) ? row[0] : row;
|
|
286
|
+
if (!data) return null;
|
|
287
|
+
|
|
288
|
+
const participants = parseParticipantsFromDb(data.participants || data.participants_json || null);
|
|
289
|
+
const creation = _normalizeNumberOrNull(data.creation);
|
|
290
|
+
const ephemeralDuration = _normalizeNumberOrNull(data.ephemeral_duration ?? data.ephemeralDuration);
|
|
291
|
+
|
|
292
|
+
const group = {
|
|
293
|
+
id: _normalizeGroupId(data.id) || normalizedGroupId,
|
|
294
|
+
subject: data.subject || data.name || null,
|
|
295
|
+
desc: data.description || data.desc || null,
|
|
296
|
+
owner: _normalizeUserIdCandidate(data.owner_jid || data.owner) || null,
|
|
297
|
+
creation,
|
|
298
|
+
participants: Array.isArray(participants) ? participants : [],
|
|
299
|
+
restrict: Boolean(data.restrict),
|
|
300
|
+
announce: Boolean(data.announce),
|
|
301
|
+
isCommunity: Boolean(data.is_community ?? data.isCommunity),
|
|
302
|
+
addressingMode: data.addressing_mode || data.addressingMode || null,
|
|
303
|
+
ephemeralDuration,
|
|
304
|
+
};
|
|
305
|
+
group.size = group.participants.length;
|
|
306
|
+
return group;
|
|
307
|
+
} catch (error) {
|
|
308
|
+
logger.error(`Erro ao buscar grupo do DB ${normalizedGroupId}: ${error.message}`, { error });
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
export async function getGroupParticipantsAsync(groupId) {
|
|
314
|
+
const group = await getGroupInfoAsync(groupId);
|
|
315
|
+
return group ? group.participants : null;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export async function isUserAdminAsync(groupId, userIdOrObj) {
|
|
319
|
+
const normalizedGroupId = _normalizeGroupId(groupId);
|
|
320
|
+
const userCandidates = _collectUserIdCandidates(userIdOrObj);
|
|
321
|
+
if (!_isValidId(normalizedGroupId, 'Grupo') || userCandidates.length === 0) return false;
|
|
322
|
+
|
|
323
|
+
const participants = await getGroupParticipantsAsync(normalizedGroupId);
|
|
324
|
+
if (!participants || participants.length === 0) return false;
|
|
325
|
+
|
|
326
|
+
return participants.some((participant) => _isParticipantAdmin(participant) && userCandidates.some((candidate) => _matchesParticipantId(participant, candidate)));
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export async function getGroupAdminsAsync(groupId) {
|
|
330
|
+
const normalizedGroupId = _normalizeGroupId(groupId);
|
|
331
|
+
if (!_isValidId(normalizedGroupId, 'Grupo')) return [];
|
|
332
|
+
const participants = await getGroupParticipantsAsync(normalizedGroupId);
|
|
333
|
+
if (!participants || participants.length === 0) return [];
|
|
334
|
+
|
|
335
|
+
const admins = [];
|
|
336
|
+
return participants
|
|
337
|
+
.filter((participant) => _isParticipantAdmin(participant))
|
|
338
|
+
.map((participant) => participant.id || participant.jid || participant.lid || null)
|
|
339
|
+
.reduce((acc, candidate) => {
|
|
340
|
+
const normalized = _normalizeUserIdCandidate(candidate);
|
|
341
|
+
if (!normalized) return acc;
|
|
342
|
+
if (acc.some((existing) => _areUserIdsEquivalent(existing, normalized))) return acc;
|
|
343
|
+
acc.push(normalized);
|
|
344
|
+
return acc;
|
|
345
|
+
}, admins);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Retorna todos os IDs de grupo disponíveis.
|
|
350
|
+
* @returns {Array<string>} Uma lista de IDs de grupo.
|
|
351
|
+
*/
|
|
352
|
+
export async function getAllGroupIds() {
|
|
353
|
+
try {
|
|
354
|
+
const rows = await findAll(TABLES.GROUPS_METADATA, 10000, 0);
|
|
355
|
+
if (!rows || !Array.isArray(rows)) return [];
|
|
356
|
+
const ids = [];
|
|
357
|
+
for (const row of rows) {
|
|
358
|
+
const candidate = row?.id || row?.[Object.keys(row || {})[0]];
|
|
359
|
+
const normalized = _normalizeGroupId(candidate);
|
|
360
|
+
if (!normalized) continue;
|
|
361
|
+
if (ids.includes(normalized)) continue;
|
|
362
|
+
ids.push(normalized);
|
|
363
|
+
}
|
|
364
|
+
return ids;
|
|
365
|
+
} catch (error) {
|
|
366
|
+
logger.error('Erro ao buscar todos os IDs de grupos do DB', { error });
|
|
367
|
+
return [];
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Retorna o proprietário de um grupo específico.
|
|
373
|
+
* @param {string} groupId - O ID do grupo.
|
|
374
|
+
* @returns {string|null} O ID do proprietário do grupo ou null se não encontrado.
|
|
375
|
+
*/
|
|
376
|
+
export async function getGroupOwner(groupId) {
|
|
377
|
+
const group = await getGroupInfoAsync(groupId);
|
|
378
|
+
return group?.owner || null;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Retorna o timestamp de criação de um grupo específico.
|
|
383
|
+
* @param {string} groupId - O ID do grupo.
|
|
384
|
+
* @returns {number|null} O timestamp de criação do grupo ou null se não encontrado.
|
|
385
|
+
*/
|
|
386
|
+
export async function getGroupCreationTime(groupId) {
|
|
387
|
+
const group = await getGroupInfoAsync(groupId);
|
|
388
|
+
return group?.creation || null;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Retorna a descrição de um grupo específico.
|
|
393
|
+
* @param {string} groupId - O ID do grupo.
|
|
394
|
+
* @returns {string|null} A descrição do grupo ou null se não encontrado.
|
|
395
|
+
*/
|
|
396
|
+
export async function getGroupDescription(groupId) {
|
|
397
|
+
const group = await getGroupInfoAsync(groupId);
|
|
398
|
+
return group?.desc || null;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Retorna o número de participantes de um grupo específico.
|
|
403
|
+
* @param {string} groupId - O ID do grupo.
|
|
404
|
+
* @returns {number|null} O número de participantes do grupo ou null se não encontrado.
|
|
405
|
+
*/
|
|
406
|
+
export async function getGroupSize(groupId) {
|
|
407
|
+
const group = await getGroupInfoAsync(groupId);
|
|
408
|
+
return group?.size || null;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Verifica se um grupo é restrito.
|
|
413
|
+
* @param {string} groupId - O ID do grupo.
|
|
414
|
+
* @returns {boolean} True se o grupo for restrito, false caso contrário.
|
|
415
|
+
*/
|
|
416
|
+
export async function isGroupRestricted(groupId) {
|
|
417
|
+
const group = await getGroupInfoAsync(groupId);
|
|
418
|
+
return !!group?.restrict;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Verifica se um grupo é apenas para anúncios.
|
|
423
|
+
* @param {string} groupId - O ID do grupo.
|
|
424
|
+
* @returns {boolean} True se o grupo for apenas para anúncios, false caso contrário.
|
|
425
|
+
*/
|
|
426
|
+
export async function isGroupAnnounceOnly(groupId) {
|
|
427
|
+
const group = await getGroupInfoAsync(groupId);
|
|
428
|
+
return !!group?.announce;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Verifica se um grupo é uma comunidade.
|
|
433
|
+
* @param {string} groupId - O ID do grupo.
|
|
434
|
+
* @returns {boolean} True se o grupo for uma comunidade, false caso contrário.
|
|
435
|
+
*/
|
|
436
|
+
export async function isGroupCommunity(groupId) {
|
|
437
|
+
const group = await getGroupInfoAsync(groupId);
|
|
438
|
+
return !!group?.isCommunity;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Retorna uma lista de IDs dos administradores de um grupo específico.
|
|
443
|
+
* @param {string} groupId - O ID do grupo.
|
|
444
|
+
* @returns {Array<string>} Uma lista de IDs dos administradores do grupo.
|
|
445
|
+
*/
|
|
446
|
+
export async function getGroupAdmins(groupId) {
|
|
447
|
+
return await getGroupAdminsAsync(groupId);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Executa uma função de grupo de forma segura, validando os parâmetros e tratando erros.
|
|
452
|
+
* @param {object} sock - A instância do socket Baileys.
|
|
453
|
+
* @param {string} functionName - O nome da função a ser executada.
|
|
454
|
+
* @param {Array} args - Os argumentos para a função.
|
|
455
|
+
* @param {string} errorMessage - A mensagem de erro a ser registrada.
|
|
456
|
+
*/
|
|
457
|
+
export async function _safeGroupApiCall(sock, functionName, args, errorMessage) {
|
|
458
|
+
const safeFunctionName = _toNonEmptyString(functionName);
|
|
459
|
+
const safeArgs = Array.isArray(args) ? args : [];
|
|
460
|
+
const socket = _isSocketLike(sock, safeFunctionName) ? sock : getActiveSocket();
|
|
461
|
+
|
|
462
|
+
if (!safeFunctionName) {
|
|
463
|
+
throw new Error('Nome da função de grupo inválido.');
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
try {
|
|
467
|
+
if (socket?.ws) {
|
|
468
|
+
return await runSocketMethod(socket, safeFunctionName, ...safeArgs);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
const directMethod = socket?.[safeFunctionName];
|
|
472
|
+
if (typeof directMethod !== 'function') {
|
|
473
|
+
throw new Error(`Método "${safeFunctionName}" não disponível no socket informado.`);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
return await directMethod.apply(socket, safeArgs);
|
|
477
|
+
} catch (error) {
|
|
478
|
+
logger.error(errorMessage, {
|
|
479
|
+
function: safeFunctionName,
|
|
480
|
+
args: safeArgs,
|
|
481
|
+
socketProvided: Boolean(sock),
|
|
482
|
+
error: error.message,
|
|
483
|
+
stack: error.stack,
|
|
484
|
+
});
|
|
485
|
+
throw error;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
export async function createGroup(sockOrTitle, titleOrParticipants, participantsMaybe) {
|
|
490
|
+
const { sock, args } = _resolveSocketAndArgs('groupCreate', [sockOrTitle, titleOrParticipants, participantsMaybe]);
|
|
491
|
+
const [title, participants] = args;
|
|
492
|
+
if (typeof title !== 'string' || title.trim() === '' || !Array.isArray(participants)) {
|
|
493
|
+
throw new Error('Título ou participantes inválidos.');
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
const normalizedParticipants = _normalizeParticipantsInput(participants);
|
|
497
|
+
if (normalizedParticipants.length === 0) {
|
|
498
|
+
throw new Error('Nenhum participante válido informado para criar grupo.');
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
const cleanTitle = title.trim();
|
|
502
|
+
const result = await _safeGroupApiCall(sock, 'groupCreate', [cleanTitle, normalizedParticipants], 'Erro ao criar grupo');
|
|
503
|
+
logger.info(`Grupo "${cleanTitle}" criado com sucesso.`, { id: result?.id || null });
|
|
504
|
+
return result;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
export async function updateGroupParticipants(sockOrGroupId, groupIdOrParticipants, participantsOrAction, actionMaybe) {
|
|
508
|
+
const { sock, args } = _resolveSocketAndArgs('groupParticipantsUpdate', [sockOrGroupId, groupIdOrParticipants, participantsOrAction, actionMaybe]);
|
|
509
|
+
const [groupId, participants, action] = args;
|
|
510
|
+
|
|
511
|
+
const normalizedGroupId = _normalizeGroupId(groupId);
|
|
512
|
+
const normalizedParticipants = _normalizeParticipantsInput(participants);
|
|
513
|
+
const normalizedAction = _toNonEmptyString(action).toLowerCase();
|
|
514
|
+
|
|
515
|
+
if (!_isValidId(normalizedGroupId, 'Grupo') || normalizedParticipants.length === 0 || !normalizedAction) {
|
|
516
|
+
throw new Error('Argumentos inválidos para atualizar participantes.');
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
return _safeGroupApiCall(sock, 'groupParticipantsUpdate', [normalizedGroupId, normalizedParticipants, normalizedAction], `Erro ao ${normalizedAction} participantes no grupo ${normalizedGroupId}`);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
export async function updateGroupSubject(sockOrGroupId, groupIdOrSubject, subjectMaybe) {
|
|
523
|
+
const { sock, args } = _resolveSocketAndArgs('groupUpdateSubject', [sockOrGroupId, groupIdOrSubject, subjectMaybe]);
|
|
524
|
+
const [groupId, subject] = args;
|
|
525
|
+
|
|
526
|
+
const normalizedGroupId = _normalizeGroupId(groupId);
|
|
527
|
+
const normalizedSubject = _toNonEmptyString(subject);
|
|
528
|
+
|
|
529
|
+
if (!_isValidId(normalizedGroupId, 'Grupo') || !normalizedSubject) {
|
|
530
|
+
throw new Error('Argumentos inválidos para atualizar assunto do grupo.');
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
return _safeGroupApiCall(sock, 'groupUpdateSubject', [normalizedGroupId, normalizedSubject], `Erro ao atualizar assunto do grupo ${normalizedGroupId}`);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
export async function updateGroupDescription(sockOrGroupId, groupIdOrDescription, descriptionMaybe) {
|
|
537
|
+
const { sock, args } = _resolveSocketAndArgs('groupUpdateDescription', [sockOrGroupId, groupIdOrDescription, descriptionMaybe]);
|
|
538
|
+
const [groupId, description] = args;
|
|
539
|
+
|
|
540
|
+
const normalizedGroupId = _normalizeGroupId(groupId);
|
|
541
|
+
if (!_isValidId(normalizedGroupId, 'Grupo') || typeof description !== 'string') {
|
|
542
|
+
throw new Error('ID de grupo inválido.');
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
return _safeGroupApiCall(sock, 'groupUpdateDescription', [normalizedGroupId, description], `Erro ao atualizar descrição do grupo ${normalizedGroupId}`);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
export async function updateGroupSettings(sockOrGroupId, groupIdOrSetting, settingMaybe) {
|
|
549
|
+
const { sock, args } = _resolveSocketAndArgs('groupSettingUpdate', [sockOrGroupId, groupIdOrSetting, settingMaybe]);
|
|
550
|
+
const [groupId, setting] = args;
|
|
551
|
+
|
|
552
|
+
const normalizedGroupId = _normalizeGroupId(groupId);
|
|
553
|
+
const normalizedSetting = _toNonEmptyString(setting);
|
|
554
|
+
|
|
555
|
+
if (!_isValidId(normalizedGroupId, 'Grupo') || !normalizedSetting) {
|
|
556
|
+
throw new Error('Argumentos inválidos para atualizar configurações do grupo.');
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
return _safeGroupApiCall(sock, 'groupSettingUpdate', [normalizedGroupId, normalizedSetting], `Erro ao atualizar configurações do grupo ${normalizedGroupId}`);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
export async function leaveGroup(sockOrGroupId, groupIdMaybe) {
|
|
563
|
+
const { sock, args } = _resolveSocketAndArgs('groupLeave', [sockOrGroupId, groupIdMaybe]);
|
|
564
|
+
const [groupId] = args;
|
|
565
|
+
const normalizedGroupId = _normalizeGroupId(groupId);
|
|
566
|
+
|
|
567
|
+
if (!_isValidId(normalizedGroupId, 'Grupo')) {
|
|
568
|
+
throw new Error('ID de grupo inválido.');
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
return _safeGroupApiCall(sock, 'groupLeave', [normalizedGroupId], `Erro ao sair do grupo ${normalizedGroupId}`);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
export async function getGroupInviteCode(sockOrGroupId, groupIdMaybe) {
|
|
575
|
+
const { sock, args } = _resolveSocketAndArgs('groupInviteCode', [sockOrGroupId, groupIdMaybe]);
|
|
576
|
+
const [groupId] = args;
|
|
577
|
+
const normalizedGroupId = _normalizeGroupId(groupId);
|
|
578
|
+
|
|
579
|
+
if (!_isValidId(normalizedGroupId, 'Grupo')) {
|
|
580
|
+
throw new Error('ID de grupo inválido.');
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
return _safeGroupApiCall(sock, 'groupInviteCode', [normalizedGroupId], `Erro ao obter código de convite do grupo ${normalizedGroupId}`);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
export async function revokeGroupInviteCode(sockOrGroupId, groupIdMaybe) {
|
|
587
|
+
const { sock, args } = _resolveSocketAndArgs('groupRevokeInvite', [sockOrGroupId, groupIdMaybe]);
|
|
588
|
+
const [groupId] = args;
|
|
589
|
+
const normalizedGroupId = _normalizeGroupId(groupId);
|
|
590
|
+
|
|
591
|
+
if (!_isValidId(normalizedGroupId, 'Grupo')) {
|
|
592
|
+
throw new Error('ID de grupo inválido.');
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
return _safeGroupApiCall(sock, 'groupRevokeInvite', [normalizedGroupId], `Erro ao revogar código de convite do grupo ${normalizedGroupId}`);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
export async function acceptGroupInvite(sockOrCode, codeMaybe) {
|
|
599
|
+
const { sock, args } = _resolveSocketAndArgs('groupAcceptInvite', [sockOrCode, codeMaybe]);
|
|
600
|
+
const [code] = args;
|
|
601
|
+
const normalizedCode = _toNonEmptyString(code);
|
|
602
|
+
|
|
603
|
+
if (!normalizedCode) {
|
|
604
|
+
throw new Error('Código de convite inválido.');
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
return _safeGroupApiCall(sock, 'groupAcceptInvite', [normalizedCode], 'Erro ao aceitar convite de grupo');
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
export async function getGroupInfoFromInvite(sockOrCode, codeMaybe) {
|
|
611
|
+
const { sock, args } = _resolveSocketAndArgs('groupGetInviteInfo', [sockOrCode, codeMaybe]);
|
|
612
|
+
const [code] = args;
|
|
613
|
+
const normalizedCode = _toNonEmptyString(code);
|
|
614
|
+
|
|
615
|
+
if (!normalizedCode) {
|
|
616
|
+
throw new Error('Código de convite inválido.');
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
return _safeGroupApiCall(sock, 'groupGetInviteInfo', [normalizedCode], 'Erro ao obter informações do convite');
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
export async function getGroupMetadata(sockOrGroupId, groupIdMaybe) {
|
|
623
|
+
const { sock, args } = _resolveSocketAndArgs('groupMetadata', [sockOrGroupId, groupIdMaybe]);
|
|
624
|
+
const [groupId] = args;
|
|
625
|
+
const normalizedGroupId = _normalizeGroupId(groupId);
|
|
626
|
+
|
|
627
|
+
if (!_isValidId(normalizedGroupId, 'Grupo')) {
|
|
628
|
+
throw new Error('ID de grupo inválido.');
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
return _safeGroupApiCall(sock, 'groupMetadata', [normalizedGroupId], `Erro ao obter metadados do grupo ${normalizedGroupId}`);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
export async function getGroupRequestParticipantsList(sockOrGroupId, groupIdMaybe) {
|
|
635
|
+
const { sock, args } = _resolveSocketAndArgs('groupRequestParticipantsList', [sockOrGroupId, groupIdMaybe]);
|
|
636
|
+
const [groupId] = args;
|
|
637
|
+
const normalizedGroupId = _normalizeGroupId(groupId);
|
|
638
|
+
|
|
639
|
+
if (!_isValidId(normalizedGroupId, 'Grupo')) {
|
|
640
|
+
throw new Error('ID de grupo inválido.');
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
return _safeGroupApiCall(sock, 'groupRequestParticipantsList', [normalizedGroupId], `Erro ao listar solicitações de entrada no grupo ${normalizedGroupId}`);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
export async function updateGroupRequestParticipants(sockOrGroupId, groupIdOrParticipants, participantsOrAction, actionMaybe) {
|
|
647
|
+
const { sock, args } = _resolveSocketAndArgs('groupRequestParticipantsUpdate', [sockOrGroupId, groupIdOrParticipants, participantsOrAction, actionMaybe]);
|
|
648
|
+
const [groupId, participants, action] = args;
|
|
649
|
+
|
|
650
|
+
const normalizedGroupId = _normalizeGroupId(groupId);
|
|
651
|
+
const normalizedParticipants = _normalizeParticipantsInput(participants);
|
|
652
|
+
const normalizedAction = _toNonEmptyString(action).toLowerCase();
|
|
653
|
+
|
|
654
|
+
if (!_isValidId(normalizedGroupId, 'Grupo') || normalizedParticipants.length === 0 || !normalizedAction) {
|
|
655
|
+
throw new Error('Argumentos inválidos para atualizar solicitações de entrada.');
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
return _safeGroupApiCall(sock, 'groupRequestParticipantsUpdate', [normalizedGroupId, normalizedParticipants, normalizedAction], `Erro ao atualizar solicitações de entrada no grupo ${normalizedGroupId}`);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
export async function getAllParticipatingGroups(sock) {
|
|
662
|
+
const socket = _isSocketLike(sock, 'groupFetchAllParticipating') ? sock : null;
|
|
663
|
+
return _safeGroupApiCall(socket, 'groupFetchAllParticipating', [], 'Erro ao obter todos os grupos participantes');
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
export async function toggleEphemeral(sockOrGroupId, groupIdOrDuration, durationMaybe) {
|
|
667
|
+
const { sock, args } = _resolveSocketAndArgs('groupToggleEphemeral', [sockOrGroupId, groupIdOrDuration, durationMaybe]);
|
|
668
|
+
const [groupId, duration] = args;
|
|
669
|
+
|
|
670
|
+
const normalizedGroupId = _normalizeGroupId(groupId);
|
|
671
|
+
const normalizedDuration = Number(duration);
|
|
672
|
+
|
|
673
|
+
if (!_isValidId(normalizedGroupId, 'Grupo') || !Number.isFinite(normalizedDuration)) {
|
|
674
|
+
throw new Error('Argumentos inválidos para alternar mensagens efêmeras.');
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
return _safeGroupApiCall(sock, 'groupToggleEphemeral', [normalizedGroupId, normalizedDuration], `Erro ao alternar mensagens efêmeras no grupo ${normalizedGroupId}`);
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
export async function updateGroupAddMode(sockOrGroupId, groupIdOrMode, modeMaybe) {
|
|
681
|
+
const { sock, args } = _resolveSocketAndArgs('groupMemberAddMode', [sockOrGroupId, groupIdOrMode, modeMaybe]);
|
|
682
|
+
const [groupId, mode] = args;
|
|
683
|
+
|
|
684
|
+
const normalizedGroupId = _normalizeGroupId(groupId);
|
|
685
|
+
const normalizedMode = _toNonEmptyString(mode);
|
|
686
|
+
|
|
687
|
+
if (!_isValidId(normalizedGroupId, 'Grupo') || !normalizedMode) {
|
|
688
|
+
throw new Error('Argumentos inválidos para atualizar modo de adição.');
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
return _safeGroupApiCall(sock, 'groupMemberAddMode', [normalizedGroupId, normalizedMode], `Erro ao atualizar modo de adição no grupo ${normalizedGroupId}`);
|
|
692
|
+
}
|