@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,1823 @@
|
|
|
1
|
+
import { handleMenuAdmCommand } from '../menuModule/menus.js';
|
|
2
|
+
import { downloadMediaMessage, getJidServer, isLidJid, isSameJidUser, isWhatsAppJid, LID_USER_JID_SERVERS, normalizeJid, WHATSAPP_USER_JID_SERVERS } from '../../config/index.js';
|
|
3
|
+
import { isUserAdmin, createGroup, acceptGroupInvite, getGroupInfo, getGroupRequestParticipantsList, updateGroupAddMode, updateGroupSettings, updateGroupParticipants, leaveGroup, getGroupInviteCode, revokeGroupInviteCode, getGroupInfoFromInvite, updateGroupRequestParticipants, updateGroupSubject, updateGroupDescription, toggleEphemeral } from '../../config/index.js';
|
|
4
|
+
import groupConfigStore from '../../store/groupConfigStore.js';
|
|
5
|
+
import premiumUserStore from '../../store/premiumUserStore.js';
|
|
6
|
+
import logger from '#logger';
|
|
7
|
+
import { KNOWN_NETWORKS } from '../../utils/antiLink/antiLinkModule.js';
|
|
8
|
+
import { getNewsStatusForGroup, startNewsBroadcastForGroup, stopNewsBroadcastForGroup } from '../../services/messaging/newsBroadcastService.js';
|
|
9
|
+
import { sendAndStore } from '../../services/messaging/messagePersistenceService.js';
|
|
10
|
+
import { clearCaptchasForGroup } from '../../services/messaging/captchaService.js';
|
|
11
|
+
import { getAdminJid, isAdminSenderAsync } from '../../config/index.js';
|
|
12
|
+
import { extractUserIdInfo, resolveUserId } from '../../config/index.js';
|
|
13
|
+
import { DEFAULT_STICKER_FOCUS_CHAT_WINDOW_MINUTES, DEFAULT_STICKER_FOCUS_MESSAGE_COOLDOWN_MINUTES, MAX_STICKER_FOCUS_CHAT_WINDOW_MINUTES, MAX_STICKER_FOCUS_MESSAGE_COOLDOWN_MINUTES, MIN_STICKER_FOCUS_CHAT_WINDOW_MINUTES, MIN_STICKER_FOCUS_MESSAGE_COOLDOWN_MINUTES, clampStickerFocusChatWindowMinutes, clampStickerFocusMessageCooldownMinutes, resolveStickerFocusState } from '../../services/sticker/stickerFocusService.js';
|
|
14
|
+
import { getAdminTextConfig, getAdminUsageText, isAdminCommandName, resolveAdminCommandName } from './adminConfigRuntime.js';
|
|
15
|
+
import { explicarComando, gerarFaqAutomatica, responderPergunta, startAdminAiHelpScheduler } from './adminAiHelpService.js';
|
|
16
|
+
const OWNER_JID = getAdminJid();
|
|
17
|
+
const DEFAULT_COMMAND_PREFIX = process.env.COMMAND_PREFIX || '/';
|
|
18
|
+
const ADMIN_TEXTS = getAdminTextConfig();
|
|
19
|
+
const GROUP_ONLY_COMMAND_MESSAGE = ADMIN_TEXTS.group_only_command_message;
|
|
20
|
+
const NO_PERMISSION_COMMAND_MESSAGE = ADMIN_TEXTS.no_permission_command_message;
|
|
21
|
+
const OWNER_ONLY_COMMAND_MESSAGE = ADMIN_TEXTS.owner_only_command_message;
|
|
22
|
+
const USER_JID_SERVERS = new Set([...WHATSAPP_USER_JID_SERVERS, ...LID_USER_JID_SERVERS]);
|
|
23
|
+
const normalizePhoneDigits = (value) => String(value || '').replace(/\D+/g, '');
|
|
24
|
+
|
|
25
|
+
const LEGACY_ADMIN_ROUTE_BY_CANONICAL = {
|
|
26
|
+
menuadmin: 'menuadm',
|
|
27
|
+
autofigurinha: 'autosticker',
|
|
28
|
+
modofigurinha: 'stickermode',
|
|
29
|
+
janelachat: 'chatwindow',
|
|
30
|
+
limitefigurinha: 'stickermsglimit',
|
|
31
|
+
novogrupo: 'newgroup',
|
|
32
|
+
adicionar: 'add',
|
|
33
|
+
banir: 'ban',
|
|
34
|
+
promover: 'up',
|
|
35
|
+
rebaixar: 'down',
|
|
36
|
+
assunto: 'setsubject',
|
|
37
|
+
descricao: 'setdesc',
|
|
38
|
+
configgrupo: 'setgroup',
|
|
39
|
+
sair: 'leave',
|
|
40
|
+
convite: 'invite',
|
|
41
|
+
revogarconvite: 'revoke',
|
|
42
|
+
entrar: 'join',
|
|
43
|
+
infoconvite: 'infofrominvite',
|
|
44
|
+
metadados: 'metadata',
|
|
45
|
+
solicitacoes: 'requests',
|
|
46
|
+
atualizarsolicitacoes: 'updaterequests',
|
|
47
|
+
autosolicitacoes: 'autorequests',
|
|
48
|
+
temporarias: 'temp',
|
|
49
|
+
modoadicao: 'addmode',
|
|
50
|
+
prefixo: 'prefix',
|
|
51
|
+
boasvindas: 'welcome',
|
|
52
|
+
despedida: 'farewell',
|
|
53
|
+
};
|
|
54
|
+
startAdminAiHelpScheduler();
|
|
55
|
+
|
|
56
|
+
const normalizeParticipantJid = (value) => {
|
|
57
|
+
const raw = String(value || '').trim();
|
|
58
|
+
if (!raw) return '';
|
|
59
|
+
|
|
60
|
+
const normalized = normalizeJid(raw);
|
|
61
|
+
if (normalized) {
|
|
62
|
+
const server = getJidServer(normalized);
|
|
63
|
+
if (USER_JID_SERVERS.has(server || '')) return normalized;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const digits = normalizePhoneDigits(raw);
|
|
67
|
+
if (digits.length >= 10 && digits.length <= 15) {
|
|
68
|
+
const phoneJid = normalizeJid(`${digits}@s.whatsapp.net`);
|
|
69
|
+
if (phoneJid) return phoneJid;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return '';
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const dedupeParticipantJids = (values = []) => {
|
|
76
|
+
const deduped = [];
|
|
77
|
+
for (const value of values) {
|
|
78
|
+
const normalized = normalizeParticipantJid(value);
|
|
79
|
+
if (!normalized) continue;
|
|
80
|
+
if (deduped.some((entry) => isSameJidUser(entry, normalized) || entry === normalized)) continue;
|
|
81
|
+
deduped.push(normalized);
|
|
82
|
+
}
|
|
83
|
+
return deduped;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const containsParticipantJid = (participants = [], targetJid = '') => {
|
|
87
|
+
const normalizedTarget = normalizeParticipantJid(targetJid);
|
|
88
|
+
if (!normalizedTarget) return false;
|
|
89
|
+
return participants.some((participantJid) => {
|
|
90
|
+
const normalizedParticipant = normalizeParticipantJid(participantJid);
|
|
91
|
+
if (!normalizedParticipant) return false;
|
|
92
|
+
return isSameJidUser(normalizedParticipant, normalizedTarget) || normalizedParticipant === normalizedTarget;
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const getParticipantJids = (messageInfo, args) => {
|
|
97
|
+
const mentionedJids = messageInfo.message?.extendedTextMessage?.contextInfo?.mentionedJid || [];
|
|
98
|
+
if (mentionedJids.length > 0) {
|
|
99
|
+
return dedupeParticipantJids(mentionedJids);
|
|
100
|
+
}
|
|
101
|
+
const repliedTo = messageInfo.message?.extendedTextMessage?.contextInfo?.participant;
|
|
102
|
+
if (repliedTo && args.length === 0) {
|
|
103
|
+
return dedupeParticipantJids([repliedTo]);
|
|
104
|
+
}
|
|
105
|
+
return dedupeParticipantJids(args);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const resolvePremiumTargetJid = async (targetJid) => {
|
|
109
|
+
const normalizedTarget = normalizeParticipantJid(targetJid);
|
|
110
|
+
if (!normalizedTarget) return '';
|
|
111
|
+
if (isWhatsAppJid(normalizedTarget)) return normalizedTarget;
|
|
112
|
+
if (!isLidJid(normalizedTarget)) return normalizedTarget;
|
|
113
|
+
|
|
114
|
+
const senderInfo = extractUserIdInfo({
|
|
115
|
+
lid: normalizedTarget,
|
|
116
|
+
participant: normalizedTarget,
|
|
117
|
+
jid: normalizedTarget,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
const resolved = await resolveUserId(senderInfo);
|
|
122
|
+
const normalizedResolved = normalizeParticipantJid(resolved);
|
|
123
|
+
if (normalizedResolved && isWhatsAppJid(normalizedResolved)) {
|
|
124
|
+
return normalizedResolved;
|
|
125
|
+
}
|
|
126
|
+
} catch (error) {
|
|
127
|
+
logger.warn('Falha ao resolver participante premium via lidMapService.', {
|
|
128
|
+
action: 'premium_target_resolve_failed',
|
|
129
|
+
targetJid: normalizedTarget,
|
|
130
|
+
error: error?.message,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return normalizedTarget;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const resolvePremiumTargetJids = async (targets = []) => {
|
|
138
|
+
const resolvedTargets = await Promise.all((targets || []).map((target) => resolvePremiumTargetJid(target)));
|
|
139
|
+
return dedupeParticipantJids(resolvedTargets);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const parsePositiveInteger = (value) => {
|
|
143
|
+
if (value === null || value === undefined || value === '') return null;
|
|
144
|
+
const numeric = Number(value);
|
|
145
|
+
if (!Number.isFinite(numeric)) return null;
|
|
146
|
+
const normalized = Math.floor(numeric);
|
|
147
|
+
if (normalized <= 0) return null;
|
|
148
|
+
return normalized;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const formatStickerFocusRule = ({ messageAllowanceCount, messageCooldownMinutes }) => {
|
|
152
|
+
const allowanceCount = Math.max(1, Math.floor(Number(messageAllowanceCount) || 1));
|
|
153
|
+
const cooldownMinutes = Math.max(1, Math.floor(Number(messageCooldownMinutes) || 1));
|
|
154
|
+
const messageLabel = allowanceCount === 1 ? 'mensagem' : 'mensagens';
|
|
155
|
+
return `${allowanceCount} ${messageLabel} a cada ${cooldownMinutes} min`;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const buildStickerFocusStatusText = ({ state, commandPrefix }) => {
|
|
159
|
+
const remainingMinutes = state.isChatWindowOpen ? Math.max(1, Math.ceil(state.chatWindowRemainingMs / (60 * 1000))) : 0;
|
|
160
|
+
const chatWindowStatus = state.isChatWindowOpen ? `aberta (restam ~${remainingMinutes} min)` : 'fechada';
|
|
161
|
+
|
|
162
|
+
return ['🖼️ *Status do modo Sticker*', '', `Modo sticker: *${state.enabled ? 'ativado' : 'desativado'}*`, `Janela de chat: *${chatWindowStatus}*`, `Regra fora da janela: *${formatStickerFocusRule(state)}*`, '', `Comandos:`, `${commandPrefix}stickermode <on|off|status>`, `${commandPrefix}chatwindow <on|off|status> [minutos]`, `${commandPrefix}stickermsglimit <minutos|status|reset>`].join('\n');
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
export const isAdminCommand = (command) => isAdminCommandName(command);
|
|
166
|
+
|
|
167
|
+
export async function handleAdminCommand({ command, args, text, sock, messageInfo, remoteJid, senderJid, botJid, isGroupMessage, expirationMessage, commandPrefix = DEFAULT_COMMAND_PREFIX }) {
|
|
168
|
+
const normalizedCommand = resolveAdminCommandName(command);
|
|
169
|
+
if (!normalizedCommand) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
const routeCommand = LEGACY_ADMIN_ROUTE_BY_CANONICAL[normalizedCommand] || normalizedCommand;
|
|
173
|
+
const senderIdentity = {
|
|
174
|
+
jid: senderJid || null,
|
|
175
|
+
participant: messageInfo?.key?.participant || null,
|
|
176
|
+
participantAlt: messageInfo?.key?.participantAlt || null,
|
|
177
|
+
remoteJidAlt: messageInfo?.key?.remoteJidAlt || null,
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
switch (routeCommand) {
|
|
181
|
+
case 'menuadm': {
|
|
182
|
+
if (!isGroupMessage) {
|
|
183
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
187
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
const subAction = String(args?.[0] || '')
|
|
191
|
+
.trim()
|
|
192
|
+
.toLowerCase();
|
|
193
|
+
const isOwner = Boolean(OWNER_JID && (await isAdminSenderAsync(senderIdentity)));
|
|
194
|
+
|
|
195
|
+
if (!subAction) {
|
|
196
|
+
await handleMenuAdmCommand(sock, remoteJid, messageInfo, expirationMessage, commandPrefix);
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (subAction === 'ajuda' || subAction === 'help') {
|
|
201
|
+
const targetCommand = String(args?.[1] || '')
|
|
202
|
+
.trim()
|
|
203
|
+
.toLowerCase();
|
|
204
|
+
if (!targetCommand) {
|
|
205
|
+
await sendAndStore(
|
|
206
|
+
sock,
|
|
207
|
+
remoteJid,
|
|
208
|
+
{
|
|
209
|
+
text: getAdminUsageText('menuadm', { commandPrefix, variant: 'help' }),
|
|
210
|
+
},
|
|
211
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
212
|
+
);
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const explanation = await explicarComando(targetCommand, {
|
|
217
|
+
commandPrefix,
|
|
218
|
+
isGroupMessage,
|
|
219
|
+
isSenderAdmin: true,
|
|
220
|
+
isSenderOwner: isOwner,
|
|
221
|
+
});
|
|
222
|
+
await sendAndStore(sock, remoteJid, { text: explanation.text }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (subAction === 'faq') {
|
|
227
|
+
const faqResult = await gerarFaqAutomatica({
|
|
228
|
+
commandPrefix,
|
|
229
|
+
force: true,
|
|
230
|
+
reason: 'menuadm_faq',
|
|
231
|
+
});
|
|
232
|
+
await sendAndStore(
|
|
233
|
+
sock,
|
|
234
|
+
remoteJid,
|
|
235
|
+
{
|
|
236
|
+
text: faqResult?.text || 'Nao foi possivel gerar a FAQ agora.',
|
|
237
|
+
},
|
|
238
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
239
|
+
);
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (subAction === 'perguntar' || subAction === 'ask' || subAction === 'pergunta') {
|
|
244
|
+
const question = args.slice(1).join(' ').trim();
|
|
245
|
+
if (!question) {
|
|
246
|
+
await sendAndStore(
|
|
247
|
+
sock,
|
|
248
|
+
remoteJid,
|
|
249
|
+
{
|
|
250
|
+
text: getAdminUsageText('menuadm', { commandPrefix, variant: 'ask' }),
|
|
251
|
+
},
|
|
252
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
253
|
+
);
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const answer = await responderPergunta(question, {
|
|
258
|
+
commandPrefix,
|
|
259
|
+
isGroupMessage,
|
|
260
|
+
isSenderAdmin: true,
|
|
261
|
+
isSenderOwner: isOwner,
|
|
262
|
+
});
|
|
263
|
+
await sendAndStore(sock, remoteJid, { text: answer.text }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
await sendAndStore(
|
|
268
|
+
sock,
|
|
269
|
+
remoteJid,
|
|
270
|
+
{
|
|
271
|
+
text: getAdminUsageText('menuadm', { commandPrefix, variant: 'default' }),
|
|
272
|
+
},
|
|
273
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
274
|
+
);
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
case 'premium': {
|
|
279
|
+
if (!OWNER_JID || !(await isAdminSenderAsync(senderIdentity))) {
|
|
280
|
+
await sendAndStore(sock, remoteJid, { text: OWNER_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const action = args[0]?.toLowerCase();
|
|
285
|
+
const actionArgs = args.slice(1);
|
|
286
|
+
if (!action || !['add', 'remove', 'list'].includes(action)) {
|
|
287
|
+
await sendAndStore(
|
|
288
|
+
sock,
|
|
289
|
+
remoteJid,
|
|
290
|
+
{
|
|
291
|
+
text: getAdminUsageText('premium', { commandPrefix, variant: 'invalid_action' }),
|
|
292
|
+
},
|
|
293
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
294
|
+
);
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (action === 'list') {
|
|
299
|
+
const premiumUsers = await premiumUserStore.getPremiumUsers();
|
|
300
|
+
const listText = premiumUsers.length > 0 ? premiumUsers.map((jid) => `• ${jid}`).join('\n') : 'Nenhum usuário premium cadastrado.';
|
|
301
|
+
await sendAndStore(sock, remoteJid, { text: `⭐ *Lista de usuários premium*\n\n${listText}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const participants = await resolvePremiumTargetJids(getParticipantJids(messageInfo, actionArgs));
|
|
306
|
+
if (participants.length === 0) {
|
|
307
|
+
await sendAndStore(
|
|
308
|
+
sock,
|
|
309
|
+
remoteJid,
|
|
310
|
+
{
|
|
311
|
+
text: getAdminUsageText('premium', { commandPrefix, variant: 'missing_targets' }),
|
|
312
|
+
},
|
|
313
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
314
|
+
);
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (action === 'add') {
|
|
319
|
+
const updated = await premiumUserStore.addPremiumUsers(participants);
|
|
320
|
+
await sendAndStore(
|
|
321
|
+
sock,
|
|
322
|
+
remoteJid,
|
|
323
|
+
{
|
|
324
|
+
text: `✅ Usuários adicionados à lista premium com sucesso.\nTotal atual de usuários premium: ${updated.length}`,
|
|
325
|
+
},
|
|
326
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
327
|
+
);
|
|
328
|
+
} else {
|
|
329
|
+
const updated = await premiumUserStore.removePremiumUsers(participants);
|
|
330
|
+
await sendAndStore(
|
|
331
|
+
sock,
|
|
332
|
+
remoteJid,
|
|
333
|
+
{
|
|
334
|
+
text: `✅ Usuários removidos da lista premium com sucesso.\nTotal atual de usuários premium: ${updated.length}`,
|
|
335
|
+
},
|
|
336
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
break;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
case 'nsfw': {
|
|
343
|
+
if (!isGroupMessage) {
|
|
344
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
348
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
349
|
+
break;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const action = args[0]?.toLowerCase();
|
|
353
|
+
if (!action || !['on', 'off', 'status'].includes(action)) {
|
|
354
|
+
await sendAndStore(
|
|
355
|
+
sock,
|
|
356
|
+
remoteJid,
|
|
357
|
+
{
|
|
358
|
+
text: getAdminUsageText('nsfw', { commandPrefix }),
|
|
359
|
+
},
|
|
360
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
361
|
+
);
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (action === 'status') {
|
|
366
|
+
const config = await groupConfigStore.getGroupConfig(remoteJid);
|
|
367
|
+
const enabled = Boolean(config.nsfwEnabled);
|
|
368
|
+
await sendAndStore(
|
|
369
|
+
sock,
|
|
370
|
+
remoteJid,
|
|
371
|
+
{
|
|
372
|
+
text: `🔞 Status do conteúdo NSFW neste grupo: *${enabled ? 'ativado' : 'desativado'}*.`,
|
|
373
|
+
},
|
|
374
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
375
|
+
);
|
|
376
|
+
break;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
const enabled = action === 'on';
|
|
380
|
+
await groupConfigStore.updateGroupConfig(remoteJid, { nsfwEnabled: enabled });
|
|
381
|
+
await sendAndStore(
|
|
382
|
+
sock,
|
|
383
|
+
remoteJid,
|
|
384
|
+
{
|
|
385
|
+
text: `🔞 Configuração NSFW atualizada: *${enabled ? 'ativado' : 'desativado'}* para este grupo.`,
|
|
386
|
+
},
|
|
387
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
388
|
+
);
|
|
389
|
+
break;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
case 'autosticker': {
|
|
393
|
+
if (!isGroupMessage) {
|
|
394
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
395
|
+
break;
|
|
396
|
+
}
|
|
397
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
398
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
399
|
+
break;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const action = args[0]?.toLowerCase();
|
|
403
|
+
if (!action || !['on', 'off', 'status'].includes(action)) {
|
|
404
|
+
await sendAndStore(
|
|
405
|
+
sock,
|
|
406
|
+
remoteJid,
|
|
407
|
+
{
|
|
408
|
+
text: getAdminUsageText('autosticker', { commandPrefix }),
|
|
409
|
+
},
|
|
410
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
411
|
+
);
|
|
412
|
+
break;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if (action === 'status') {
|
|
416
|
+
const config = await groupConfigStore.getGroupConfig(remoteJid);
|
|
417
|
+
const enabled = Boolean(config.autoStickerEnabled);
|
|
418
|
+
await sendAndStore(
|
|
419
|
+
sock,
|
|
420
|
+
remoteJid,
|
|
421
|
+
{
|
|
422
|
+
text: `🖼️ Status do AutoSticker neste grupo: *${enabled ? 'ativado' : 'desativado'}*.\n` + 'Quando ativo, imagens e vídeos enviados serão convertidos automaticamente em figurinha.',
|
|
423
|
+
},
|
|
424
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
425
|
+
);
|
|
426
|
+
break;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
const enabled = action === 'on';
|
|
430
|
+
await groupConfigStore.updateGroupConfig(remoteJid, { autoStickerEnabled: enabled });
|
|
431
|
+
await sendAndStore(
|
|
432
|
+
sock,
|
|
433
|
+
remoteJid,
|
|
434
|
+
{
|
|
435
|
+
text: enabled ? '✅ AutoSticker ativado neste grupo.\nEnvie uma imagem ou vídeo para conversão automática em figurinha.' : '🛑 AutoSticker desativado neste grupo.',
|
|
436
|
+
},
|
|
437
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
438
|
+
);
|
|
439
|
+
break;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
case 'stickermode': {
|
|
443
|
+
if (!isGroupMessage) {
|
|
444
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
448
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
449
|
+
break;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
const action = args[0]?.toLowerCase();
|
|
453
|
+
if (!action || !['on', 'off', 'status'].includes(action)) {
|
|
454
|
+
await sendAndStore(
|
|
455
|
+
sock,
|
|
456
|
+
remoteJid,
|
|
457
|
+
{
|
|
458
|
+
text: getAdminUsageText('stickermode', { commandPrefix }),
|
|
459
|
+
},
|
|
460
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
461
|
+
);
|
|
462
|
+
break;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
if (action === 'status') {
|
|
466
|
+
const config = await groupConfigStore.getGroupConfig(remoteJid);
|
|
467
|
+
const state = resolveStickerFocusState(config);
|
|
468
|
+
await sendAndStore(
|
|
469
|
+
sock,
|
|
470
|
+
remoteJid,
|
|
471
|
+
{
|
|
472
|
+
text: buildStickerFocusStatusText({ state, commandPrefix }),
|
|
473
|
+
},
|
|
474
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
475
|
+
);
|
|
476
|
+
break;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
const enabled = action === 'on';
|
|
480
|
+
await groupConfigStore.updateGroupConfig(remoteJid, {
|
|
481
|
+
stickerFocusEnabled: enabled,
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
if (enabled) {
|
|
485
|
+
const config = await groupConfigStore.getGroupConfig(remoteJid);
|
|
486
|
+
const state = resolveStickerFocusState(config);
|
|
487
|
+
const enabledText = ['✅ Modo sticker ativado neste grupo.', `Fora da janela de chat, cada usuário pode enviar *${formatStickerFocusRule(state)}*.`, `Use *${commandPrefix}chatwindow on* para abrir conversa livre temporária.`].join('\n');
|
|
488
|
+
await sendAndStore(sock, remoteJid, { text: enabledText }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
489
|
+
} else {
|
|
490
|
+
await sendAndStore(
|
|
491
|
+
sock,
|
|
492
|
+
remoteJid,
|
|
493
|
+
{
|
|
494
|
+
text: '🛑 Modo sticker desativado neste grupo.\nMensagens de texto voltaram ao comportamento normal.',
|
|
495
|
+
},
|
|
496
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
break;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
case 'chatwindow': {
|
|
504
|
+
if (!isGroupMessage) {
|
|
505
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
506
|
+
break;
|
|
507
|
+
}
|
|
508
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
509
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
510
|
+
break;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
const action = args[0]?.toLowerCase();
|
|
514
|
+
if (!action || !['on', 'off', 'status'].includes(action)) {
|
|
515
|
+
await sendAndStore(
|
|
516
|
+
sock,
|
|
517
|
+
remoteJid,
|
|
518
|
+
{
|
|
519
|
+
text: getAdminUsageText('chatwindow', { commandPrefix }),
|
|
520
|
+
},
|
|
521
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
522
|
+
);
|
|
523
|
+
break;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
if (action === 'status') {
|
|
527
|
+
const config = await groupConfigStore.getGroupConfig(remoteJid);
|
|
528
|
+
const state = resolveStickerFocusState(config);
|
|
529
|
+
const remainingMinutes = state.isChatWindowOpen ? Math.max(1, Math.ceil(state.chatWindowRemainingMs / (60 * 1000))) : 0;
|
|
530
|
+
await sendAndStore(
|
|
531
|
+
sock,
|
|
532
|
+
remoteJid,
|
|
533
|
+
{
|
|
534
|
+
text: `💬 Janela de chat está *${state.isChatWindowOpen ? 'aberta' : 'fechada'}*.` + (state.isChatWindowOpen ? `\nTempo restante: ~${remainingMinutes} min.` : '') + `\nModo sticker: *${state.enabled ? 'ativado' : 'desativado'}*.`,
|
|
535
|
+
},
|
|
536
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
537
|
+
);
|
|
538
|
+
break;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
if (action === 'off') {
|
|
542
|
+
await groupConfigStore.updateGroupConfig(remoteJid, {
|
|
543
|
+
stickerFocusChatWindowUntilMs: null,
|
|
544
|
+
});
|
|
545
|
+
await sendAndStore(
|
|
546
|
+
sock,
|
|
547
|
+
remoteJid,
|
|
548
|
+
{
|
|
549
|
+
text: '🛑 Janela de chat encerrada. O grupo voltou para o fluxo normal do modo sticker.',
|
|
550
|
+
},
|
|
551
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
552
|
+
);
|
|
553
|
+
break;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
const rawMinutes = args[1];
|
|
557
|
+
let minutes = DEFAULT_STICKER_FOCUS_CHAT_WINDOW_MINUTES;
|
|
558
|
+
if (rawMinutes !== undefined) {
|
|
559
|
+
const parsed = parsePositiveInteger(rawMinutes);
|
|
560
|
+
if (!parsed) {
|
|
561
|
+
await sendAndStore(
|
|
562
|
+
sock,
|
|
563
|
+
remoteJid,
|
|
564
|
+
{
|
|
565
|
+
text: `Informe minutos válidos entre ${MIN_STICKER_FOCUS_CHAT_WINDOW_MINUTES} e ${MAX_STICKER_FOCUS_CHAT_WINDOW_MINUTES}.`,
|
|
566
|
+
},
|
|
567
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
568
|
+
);
|
|
569
|
+
break;
|
|
570
|
+
}
|
|
571
|
+
if (parsed < MIN_STICKER_FOCUS_CHAT_WINDOW_MINUTES || parsed > MAX_STICKER_FOCUS_CHAT_WINDOW_MINUTES) {
|
|
572
|
+
await sendAndStore(
|
|
573
|
+
sock,
|
|
574
|
+
remoteJid,
|
|
575
|
+
{
|
|
576
|
+
text: `Tempo fora da faixa permitida. Use entre ${MIN_STICKER_FOCUS_CHAT_WINDOW_MINUTES} e ${MAX_STICKER_FOCUS_CHAT_WINDOW_MINUTES} minutos.`,
|
|
577
|
+
},
|
|
578
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
579
|
+
);
|
|
580
|
+
break;
|
|
581
|
+
}
|
|
582
|
+
minutes = clampStickerFocusChatWindowMinutes(parsed, DEFAULT_STICKER_FOCUS_CHAT_WINDOW_MINUTES);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
const untilMs = Date.now() + minutes * 60 * 1000;
|
|
586
|
+
await groupConfigStore.updateGroupConfig(remoteJid, {
|
|
587
|
+
stickerFocusChatWindowUntilMs: untilMs,
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
const config = await groupConfigStore.getGroupConfig(remoteJid);
|
|
591
|
+
const state = resolveStickerFocusState(config);
|
|
592
|
+
const openText = [`✅ Janela de chat aberta por *${minutes} min*.`, 'Durante esse período, mensagens ficam liberadas para todos.', `Modo sticker: *${state.enabled ? 'ativado' : 'desativado'}*.`].join('\n');
|
|
593
|
+
await sendAndStore(sock, remoteJid, { text: openText }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
594
|
+
break;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
case 'stickermsglimit': {
|
|
598
|
+
if (!isGroupMessage) {
|
|
599
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
600
|
+
break;
|
|
601
|
+
}
|
|
602
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
603
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
604
|
+
break;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
const rawValue = args[0];
|
|
608
|
+
const normalized = String(rawValue || '')
|
|
609
|
+
.trim()
|
|
610
|
+
.toLowerCase();
|
|
611
|
+
|
|
612
|
+
if (!normalized || normalized === 'status') {
|
|
613
|
+
const config = await groupConfigStore.getGroupConfig(remoteJid);
|
|
614
|
+
const state = resolveStickerFocusState(config);
|
|
615
|
+
await sendAndStore(
|
|
616
|
+
sock,
|
|
617
|
+
remoteJid,
|
|
618
|
+
{
|
|
619
|
+
text: `🧩 Regra atual por usuário fora da janela: *${formatStickerFocusRule(state)}*.` + `\nModo sticker: *${state.enabled ? 'ativado' : 'desativado'}*.` + `\nUse *${commandPrefix}stickermsglimit <minutos>* para alterar a janela.`,
|
|
620
|
+
},
|
|
621
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
622
|
+
);
|
|
623
|
+
break;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
if (['reset', 'default', 'padrao', 'padrão'].includes(normalized)) {
|
|
627
|
+
await groupConfigStore.updateGroupConfig(remoteJid, {
|
|
628
|
+
stickerFocusMessageCooldownMinutes: DEFAULT_STICKER_FOCUS_MESSAGE_COOLDOWN_MINUTES,
|
|
629
|
+
// compatibilidade com configuração antiga
|
|
630
|
+
stickerFocusTextCooldownMinutes: DEFAULT_STICKER_FOCUS_MESSAGE_COOLDOWN_MINUTES,
|
|
631
|
+
});
|
|
632
|
+
await sendAndStore(
|
|
633
|
+
sock,
|
|
634
|
+
remoteJid,
|
|
635
|
+
{
|
|
636
|
+
text: `✅ Intervalo restaurado para o padrão: *${DEFAULT_STICKER_FOCUS_MESSAGE_COOLDOWN_MINUTES} min*.`,
|
|
637
|
+
},
|
|
638
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
639
|
+
);
|
|
640
|
+
break;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
const parsed = parsePositiveInteger(rawValue);
|
|
644
|
+
if (!parsed) {
|
|
645
|
+
await sendAndStore(
|
|
646
|
+
sock,
|
|
647
|
+
remoteJid,
|
|
648
|
+
{
|
|
649
|
+
text: getAdminUsageText('stickermsglimit', { commandPrefix }),
|
|
650
|
+
},
|
|
651
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
652
|
+
);
|
|
653
|
+
break;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
if (parsed < MIN_STICKER_FOCUS_MESSAGE_COOLDOWN_MINUTES || parsed > MAX_STICKER_FOCUS_MESSAGE_COOLDOWN_MINUTES) {
|
|
657
|
+
await sendAndStore(
|
|
658
|
+
sock,
|
|
659
|
+
remoteJid,
|
|
660
|
+
{
|
|
661
|
+
text: `Informe um valor entre ${MIN_STICKER_FOCUS_MESSAGE_COOLDOWN_MINUTES} e ${MAX_STICKER_FOCUS_MESSAGE_COOLDOWN_MINUTES} minutos.`,
|
|
662
|
+
},
|
|
663
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
664
|
+
);
|
|
665
|
+
break;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
const minutes = clampStickerFocusMessageCooldownMinutes(parsed, DEFAULT_STICKER_FOCUS_MESSAGE_COOLDOWN_MINUTES);
|
|
669
|
+
await groupConfigStore.updateGroupConfig(remoteJid, {
|
|
670
|
+
stickerFocusMessageCooldownMinutes: minutes,
|
|
671
|
+
// compatibilidade com configuração antiga
|
|
672
|
+
stickerFocusTextCooldownMinutes: minutes,
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
await sendAndStore(
|
|
676
|
+
sock,
|
|
677
|
+
remoteJid,
|
|
678
|
+
{
|
|
679
|
+
text: `✅ Intervalo de mensagem por usuário atualizado para *${minutes} min* no modo sticker.`,
|
|
680
|
+
},
|
|
681
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
682
|
+
);
|
|
683
|
+
break;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
case 'newgroup': {
|
|
687
|
+
if (args.length < 2) {
|
|
688
|
+
await sendAndStore(
|
|
689
|
+
sock,
|
|
690
|
+
remoteJid,
|
|
691
|
+
{
|
|
692
|
+
text: getAdminUsageText('newgroup', { commandPrefix }),
|
|
693
|
+
},
|
|
694
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
695
|
+
);
|
|
696
|
+
break;
|
|
697
|
+
}
|
|
698
|
+
const title = args[0];
|
|
699
|
+
const participants = args.slice(1);
|
|
700
|
+
try {
|
|
701
|
+
const group = await createGroup(sock, title, participants);
|
|
702
|
+
await sendAndStore(sock, remoteJid, { text: `O grupo "${group.subject}" foi criado com sucesso.` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
703
|
+
} catch (error) {
|
|
704
|
+
await sendAndStore(sock, remoteJid, { text: `Não foi possível criar o grupo. Detalhes: ${error.message}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
705
|
+
}
|
|
706
|
+
break;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
case 'add': {
|
|
710
|
+
if (!isGroupMessage) {
|
|
711
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
712
|
+
break;
|
|
713
|
+
}
|
|
714
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
715
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
716
|
+
break;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
const participants = getParticipantJids(messageInfo, args);
|
|
720
|
+
if (participants.length === 0) {
|
|
721
|
+
await sendAndStore(
|
|
722
|
+
sock,
|
|
723
|
+
remoteJid,
|
|
724
|
+
{
|
|
725
|
+
text: getAdminUsageText('add', { commandPrefix, variant: 'missing_targets' }),
|
|
726
|
+
},
|
|
727
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
728
|
+
);
|
|
729
|
+
break;
|
|
730
|
+
}
|
|
731
|
+
try {
|
|
732
|
+
await updateGroupParticipants(sock, remoteJid, participants, 'add');
|
|
733
|
+
await sendAndStore(sock, remoteJid, { text: 'Participantes adicionados com sucesso.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
734
|
+
} catch (error) {
|
|
735
|
+
await sendAndStore(sock, remoteJid, { text: `Não foi possível adicionar participantes. Detalhes: ${error.message}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
736
|
+
}
|
|
737
|
+
break;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
case 'ban': {
|
|
741
|
+
if (!isGroupMessage) {
|
|
742
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
743
|
+
break;
|
|
744
|
+
}
|
|
745
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
746
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
747
|
+
break;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
const participants = getParticipantJids(messageInfo, args);
|
|
751
|
+
if (participants.length === 0) {
|
|
752
|
+
await sendAndStore(
|
|
753
|
+
sock,
|
|
754
|
+
remoteJid,
|
|
755
|
+
{
|
|
756
|
+
text: getAdminUsageText('ban', { commandPrefix, variant: 'missing_targets' }),
|
|
757
|
+
},
|
|
758
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
759
|
+
);
|
|
760
|
+
break;
|
|
761
|
+
}
|
|
762
|
+
if (containsParticipantJid(participants, botJid)) {
|
|
763
|
+
await sendAndStore(sock, remoteJid, { text: 'Operação cancelada: o bot não pode remover a própria conta.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
764
|
+
break;
|
|
765
|
+
}
|
|
766
|
+
try {
|
|
767
|
+
await updateGroupParticipants(sock, remoteJid, participants, 'remove');
|
|
768
|
+
await sendAndStore(sock, remoteJid, { text: 'Participantes removidos com sucesso.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
769
|
+
const repliedTo = messageInfo.message?.extendedTextMessage?.contextInfo;
|
|
770
|
+
if (repliedTo && containsParticipantJid(participants, repliedTo.participant)) {
|
|
771
|
+
await sendAndStore(sock, remoteJid, {
|
|
772
|
+
delete: messageInfo.message?.extendedTextMessage?.contextInfo?.key,
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
} catch (error) {
|
|
776
|
+
await sendAndStore(sock, remoteJid, { text: `Não foi possível remover participantes. Detalhes: ${error.message}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
777
|
+
}
|
|
778
|
+
break;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
case 'up': {
|
|
782
|
+
if (!isGroupMessage) {
|
|
783
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
784
|
+
break;
|
|
785
|
+
}
|
|
786
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
787
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
788
|
+
break;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
const participants = getParticipantJids(messageInfo, args);
|
|
792
|
+
if (participants.length === 0) {
|
|
793
|
+
await sendAndStore(
|
|
794
|
+
sock,
|
|
795
|
+
remoteJid,
|
|
796
|
+
{
|
|
797
|
+
text: getAdminUsageText('up', { commandPrefix, variant: 'missing_targets' }),
|
|
798
|
+
},
|
|
799
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
800
|
+
);
|
|
801
|
+
break;
|
|
802
|
+
}
|
|
803
|
+
if (containsParticipantJid(participants, botJid)) {
|
|
804
|
+
await sendAndStore(sock, remoteJid, { text: 'Operação cancelada: o bot não pode promover a própria conta.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
805
|
+
break;
|
|
806
|
+
}
|
|
807
|
+
try {
|
|
808
|
+
await updateGroupParticipants(sock, remoteJid, participants, 'promote');
|
|
809
|
+
await sendAndStore(sock, remoteJid, { text: 'Participantes promovidos a administradores com sucesso.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
810
|
+
} catch (error) {
|
|
811
|
+
await sendAndStore(sock, remoteJid, { text: `Não foi possível promover participantes. Detalhes: ${error.message}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
812
|
+
}
|
|
813
|
+
break;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
case 'down': {
|
|
817
|
+
if (!isGroupMessage) {
|
|
818
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
819
|
+
break;
|
|
820
|
+
}
|
|
821
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
822
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
823
|
+
break;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
const participants = getParticipantJids(messageInfo, args);
|
|
827
|
+
if (participants.length === 0) {
|
|
828
|
+
await sendAndStore(
|
|
829
|
+
sock,
|
|
830
|
+
remoteJid,
|
|
831
|
+
{
|
|
832
|
+
text: getAdminUsageText('down', { commandPrefix, variant: 'missing_targets' }),
|
|
833
|
+
},
|
|
834
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
835
|
+
);
|
|
836
|
+
break;
|
|
837
|
+
}
|
|
838
|
+
if (containsParticipantJid(participants, botJid)) {
|
|
839
|
+
await sendAndStore(sock, remoteJid, { text: 'Operação cancelada: o bot não pode rebaixar a própria conta.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
840
|
+
break;
|
|
841
|
+
}
|
|
842
|
+
try {
|
|
843
|
+
await updateGroupParticipants(sock, remoteJid, participants, 'demote');
|
|
844
|
+
await sendAndStore(sock, remoteJid, { text: 'Administradores rebaixados para participantes com sucesso.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
845
|
+
} catch (error) {
|
|
846
|
+
await sendAndStore(sock, remoteJid, { text: `Não foi possível rebaixar administradores. Detalhes: ${error.message}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
847
|
+
}
|
|
848
|
+
break;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
case 'setsubject': {
|
|
852
|
+
if (!isGroupMessage) {
|
|
853
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
854
|
+
break;
|
|
855
|
+
}
|
|
856
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
857
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
858
|
+
break;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
if (args.length < 1) {
|
|
862
|
+
await sendAndStore(
|
|
863
|
+
sock,
|
|
864
|
+
remoteJid,
|
|
865
|
+
{
|
|
866
|
+
text: getAdminUsageText('setsubject', { commandPrefix }),
|
|
867
|
+
},
|
|
868
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
869
|
+
);
|
|
870
|
+
break;
|
|
871
|
+
}
|
|
872
|
+
const newSubject = args.join(' ');
|
|
873
|
+
try {
|
|
874
|
+
await updateGroupSubject(sock, remoteJid, newSubject);
|
|
875
|
+
await sendAndStore(sock, remoteJid, { text: `O assunto do grupo foi atualizado para "${newSubject}" com sucesso.` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
876
|
+
} catch (error) {
|
|
877
|
+
await sendAndStore(sock, remoteJid, { text: `Não foi possível alterar o assunto do grupo. Detalhes: ${error.message}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
878
|
+
}
|
|
879
|
+
break;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
case 'setdesc': {
|
|
883
|
+
if (!isGroupMessage) {
|
|
884
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
885
|
+
break;
|
|
886
|
+
}
|
|
887
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
888
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
889
|
+
break;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
if (args.length < 1) {
|
|
893
|
+
await sendAndStore(
|
|
894
|
+
sock,
|
|
895
|
+
remoteJid,
|
|
896
|
+
{
|
|
897
|
+
text: getAdminUsageText('setdesc', { commandPrefix }),
|
|
898
|
+
},
|
|
899
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
900
|
+
);
|
|
901
|
+
break;
|
|
902
|
+
}
|
|
903
|
+
const newDescription = args.join(' ');
|
|
904
|
+
try {
|
|
905
|
+
await updateGroupDescription(sock, remoteJid, newDescription);
|
|
906
|
+
await sendAndStore(sock, remoteJid, { text: 'Descrição do grupo atualizada com sucesso.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
907
|
+
} catch (error) {
|
|
908
|
+
await sendAndStore(sock, remoteJid, { text: `Não foi possível alterar a descrição do grupo. Detalhes: ${error.message}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
909
|
+
}
|
|
910
|
+
break;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
case 'setgroup': {
|
|
914
|
+
if (!isGroupMessage) {
|
|
915
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
916
|
+
break;
|
|
917
|
+
}
|
|
918
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
919
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
920
|
+
break;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
if (args.length < 1 || !['announcement', 'not_announcement', 'locked', 'unlocked'].includes(args[0])) {
|
|
924
|
+
await sendAndStore(
|
|
925
|
+
sock,
|
|
926
|
+
remoteJid,
|
|
927
|
+
{
|
|
928
|
+
text: getAdminUsageText('setgroup', { commandPrefix }),
|
|
929
|
+
},
|
|
930
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
931
|
+
);
|
|
932
|
+
break;
|
|
933
|
+
}
|
|
934
|
+
const setting = args[0];
|
|
935
|
+
try {
|
|
936
|
+
await updateGroupSettings(sock, remoteJid, setting);
|
|
937
|
+
await sendAndStore(sock, remoteJid, { text: `Configuração do grupo atualizada com sucesso para: "${setting}".` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
938
|
+
} catch (error) {
|
|
939
|
+
await sendAndStore(sock, remoteJid, { text: `Não foi possível alterar a configuração do grupo. Detalhes: ${error.message}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
940
|
+
}
|
|
941
|
+
break;
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
case 'leave': {
|
|
945
|
+
if (!isGroupMessage) {
|
|
946
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
947
|
+
break;
|
|
948
|
+
}
|
|
949
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
950
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
951
|
+
break;
|
|
952
|
+
}
|
|
953
|
+
try {
|
|
954
|
+
await leaveGroup(sock, remoteJid);
|
|
955
|
+
await sendAndStore(sock, remoteJid, { text: 'Saída do grupo concluída com sucesso.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
956
|
+
} catch (error) {
|
|
957
|
+
await sendAndStore(sock, remoteJid, { text: `Não foi possível sair do grupo. Detalhes: ${error.message}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
958
|
+
}
|
|
959
|
+
break;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
case 'invite': {
|
|
963
|
+
if (!isGroupMessage) {
|
|
964
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
965
|
+
break;
|
|
966
|
+
}
|
|
967
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
968
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
969
|
+
break;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
try {
|
|
973
|
+
const code = await getGroupInviteCode(sock, remoteJid);
|
|
974
|
+
await sendAndStore(
|
|
975
|
+
sock,
|
|
976
|
+
remoteJid,
|
|
977
|
+
{
|
|
978
|
+
text: `Código de convite atual do grupo:
|
|
979
|
+
${code}`,
|
|
980
|
+
},
|
|
981
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
982
|
+
);
|
|
983
|
+
} catch (error) {
|
|
984
|
+
await sendAndStore(sock, remoteJid, { text: `Não foi possível obter o código de convite. Detalhes: ${error.message}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
985
|
+
}
|
|
986
|
+
break;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
case 'revoke': {
|
|
990
|
+
if (!isGroupMessage) {
|
|
991
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
992
|
+
break;
|
|
993
|
+
}
|
|
994
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
995
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
996
|
+
break;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
try {
|
|
1000
|
+
const code = await revokeGroupInviteCode(sock, remoteJid);
|
|
1001
|
+
await sendAndStore(sock, remoteJid, { text: `Código de convite anterior revogado com sucesso.\nNovo código: ${code}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1002
|
+
} catch (error) {
|
|
1003
|
+
await sendAndStore(sock, remoteJid, { text: `Não foi possível revogar o código de convite. Detalhes: ${error.message}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1004
|
+
}
|
|
1005
|
+
break;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
case 'join': {
|
|
1009
|
+
if (args.length < 1) {
|
|
1010
|
+
await sendAndStore(
|
|
1011
|
+
sock,
|
|
1012
|
+
remoteJid,
|
|
1013
|
+
{
|
|
1014
|
+
text: getAdminUsageText('join', { commandPrefix }),
|
|
1015
|
+
},
|
|
1016
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1017
|
+
);
|
|
1018
|
+
break;
|
|
1019
|
+
}
|
|
1020
|
+
const code = args[0];
|
|
1021
|
+
try {
|
|
1022
|
+
const response = await acceptGroupInvite(sock, code);
|
|
1023
|
+
await sendAndStore(sock, remoteJid, { text: `Entrada no grupo concluída com sucesso.\nIdentificador retornado: ${response}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1024
|
+
} catch (error) {
|
|
1025
|
+
await sendAndStore(sock, remoteJid, { text: `Não foi possível entrar no grupo. Detalhes: ${error.message}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1026
|
+
}
|
|
1027
|
+
break;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
case 'infofrominvite': {
|
|
1031
|
+
if (args.length < 1) {
|
|
1032
|
+
await sendAndStore(
|
|
1033
|
+
sock,
|
|
1034
|
+
remoteJid,
|
|
1035
|
+
{
|
|
1036
|
+
text: getAdminUsageText('infofrominvite', { commandPrefix }),
|
|
1037
|
+
},
|
|
1038
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1039
|
+
);
|
|
1040
|
+
break;
|
|
1041
|
+
}
|
|
1042
|
+
const code = args[0];
|
|
1043
|
+
try {
|
|
1044
|
+
const response = await getGroupInfoFromInvite(sock, code);
|
|
1045
|
+
await sendAndStore(
|
|
1046
|
+
sock,
|
|
1047
|
+
remoteJid,
|
|
1048
|
+
{
|
|
1049
|
+
text: `Informações obtidas pelo convite:
|
|
1050
|
+
${JSON.stringify(response, null, 2)}`,
|
|
1051
|
+
},
|
|
1052
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1053
|
+
);
|
|
1054
|
+
} catch (error) {
|
|
1055
|
+
await sendAndStore(sock, remoteJid, { text: `Não foi possível obter informações do grupo. Detalhes: ${error.message}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1056
|
+
}
|
|
1057
|
+
break;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
case 'metadata': {
|
|
1061
|
+
const groupId = args[0] || remoteJid;
|
|
1062
|
+
if (!(await isUserAdmin(groupId, senderJid))) {
|
|
1063
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1064
|
+
break;
|
|
1065
|
+
}
|
|
1066
|
+
try {
|
|
1067
|
+
const metadata = getGroupInfo(groupId);
|
|
1068
|
+
await sendAndStore(
|
|
1069
|
+
sock,
|
|
1070
|
+
remoteJid,
|
|
1071
|
+
{
|
|
1072
|
+
text: `Metadados do grupo:
|
|
1073
|
+
${JSON.stringify(metadata, null, 2)}`,
|
|
1074
|
+
},
|
|
1075
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1076
|
+
);
|
|
1077
|
+
} catch (error) {
|
|
1078
|
+
await sendAndStore(sock, remoteJid, { text: `Não foi possível obter metadados do grupo. Detalhes: ${error.message}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1079
|
+
}
|
|
1080
|
+
break;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
case 'requests': {
|
|
1084
|
+
if (!isGroupMessage) {
|
|
1085
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1086
|
+
break;
|
|
1087
|
+
}
|
|
1088
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
1089
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1090
|
+
break;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
try {
|
|
1094
|
+
const response = await getGroupRequestParticipantsList(sock, remoteJid);
|
|
1095
|
+
await sendAndStore(
|
|
1096
|
+
sock,
|
|
1097
|
+
remoteJid,
|
|
1098
|
+
{
|
|
1099
|
+
text: `Solicitações de entrada pendentes:
|
|
1100
|
+
${JSON.stringify(response, null, 2)}`,
|
|
1101
|
+
},
|
|
1102
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1103
|
+
);
|
|
1104
|
+
} catch (error) {
|
|
1105
|
+
await sendAndStore(sock, remoteJid, { text: `Não foi possível listar solicitações de entrada. Detalhes: ${error.message}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1106
|
+
}
|
|
1107
|
+
break;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
case 'updaterequests': {
|
|
1111
|
+
if (!isGroupMessage) {
|
|
1112
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1113
|
+
break;
|
|
1114
|
+
}
|
|
1115
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
1116
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1117
|
+
break;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
if (args.length < 1 || !['approve', 'reject'].includes(args[0])) {
|
|
1121
|
+
await sendAndStore(
|
|
1122
|
+
sock,
|
|
1123
|
+
remoteJid,
|
|
1124
|
+
{
|
|
1125
|
+
text: getAdminUsageText('updaterequests', {
|
|
1126
|
+
commandPrefix,
|
|
1127
|
+
variant: 'invalid_action',
|
|
1128
|
+
}),
|
|
1129
|
+
},
|
|
1130
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1131
|
+
);
|
|
1132
|
+
break;
|
|
1133
|
+
}
|
|
1134
|
+
const action = args[0];
|
|
1135
|
+
const participants = getParticipantJids(messageInfo, args.slice(1));
|
|
1136
|
+
if (participants.length === 0) {
|
|
1137
|
+
await sendAndStore(
|
|
1138
|
+
sock,
|
|
1139
|
+
remoteJid,
|
|
1140
|
+
{
|
|
1141
|
+
text: getAdminUsageText('updaterequests', {
|
|
1142
|
+
commandPrefix,
|
|
1143
|
+
variant: 'missing_targets',
|
|
1144
|
+
}),
|
|
1145
|
+
},
|
|
1146
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1147
|
+
);
|
|
1148
|
+
break;
|
|
1149
|
+
}
|
|
1150
|
+
try {
|
|
1151
|
+
const response = await updateGroupRequestParticipants(sock, remoteJid, participants, action);
|
|
1152
|
+
await sendAndStore(
|
|
1153
|
+
sock,
|
|
1154
|
+
remoteJid,
|
|
1155
|
+
{
|
|
1156
|
+
text: `Solicitações de entrada atualizadas com sucesso:
|
|
1157
|
+
${JSON.stringify(response, null, 2)}`,
|
|
1158
|
+
},
|
|
1159
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1160
|
+
);
|
|
1161
|
+
} catch (error) {
|
|
1162
|
+
await sendAndStore(
|
|
1163
|
+
sock,
|
|
1164
|
+
remoteJid,
|
|
1165
|
+
{
|
|
1166
|
+
text: `Não foi possível atualizar solicitações de entrada. Detalhes: ${error.message}`,
|
|
1167
|
+
},
|
|
1168
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1169
|
+
);
|
|
1170
|
+
}
|
|
1171
|
+
break;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
case 'autorequests': {
|
|
1175
|
+
if (!isGroupMessage) {
|
|
1176
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1177
|
+
break;
|
|
1178
|
+
}
|
|
1179
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
1180
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1181
|
+
break;
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
const action = args[0]?.toLowerCase();
|
|
1185
|
+
if (!action || !['on', 'off', 'status'].includes(action)) {
|
|
1186
|
+
await sendAndStore(sock, remoteJid, { text: getAdminUsageText('autorequests', { commandPrefix }) }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1187
|
+
break;
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
if (action === 'status') {
|
|
1191
|
+
const config = await groupConfigStore.getGroupConfig(remoteJid);
|
|
1192
|
+
const enabled = Boolean(config.autoApproveRequestsEnabled);
|
|
1193
|
+
await sendAndStore(
|
|
1194
|
+
sock,
|
|
1195
|
+
remoteJid,
|
|
1196
|
+
{
|
|
1197
|
+
text: `🤖 Auto-aprovação de solicitações: *${enabled ? 'ativada' : 'desativada'}*.\n` + 'Quando ativo, o bot aprova automaticamente novas solicitações de entrada.',
|
|
1198
|
+
},
|
|
1199
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1200
|
+
);
|
|
1201
|
+
break;
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
const enabled = action === 'on';
|
|
1205
|
+
await groupConfigStore.updateGroupConfig(remoteJid, {
|
|
1206
|
+
autoApproveRequestsEnabled: enabled,
|
|
1207
|
+
});
|
|
1208
|
+
await sendAndStore(
|
|
1209
|
+
sock,
|
|
1210
|
+
remoteJid,
|
|
1211
|
+
{
|
|
1212
|
+
text: enabled ? '✅ Auto-aprovação de solicitações ativada para este grupo.' : '🛑 Auto-aprovação de solicitações desativada para este grupo.',
|
|
1213
|
+
},
|
|
1214
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1215
|
+
);
|
|
1216
|
+
break;
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
case 'temp': {
|
|
1220
|
+
if (!isGroupMessage) {
|
|
1221
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1222
|
+
break;
|
|
1223
|
+
}
|
|
1224
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
1225
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1226
|
+
break;
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
if (args.length < 1) {
|
|
1230
|
+
await sendAndStore(
|
|
1231
|
+
sock,
|
|
1232
|
+
remoteJid,
|
|
1233
|
+
{
|
|
1234
|
+
text: getAdminUsageText('temp', { commandPrefix }),
|
|
1235
|
+
},
|
|
1236
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1237
|
+
);
|
|
1238
|
+
break;
|
|
1239
|
+
}
|
|
1240
|
+
const duration = parseInt(args[0]);
|
|
1241
|
+
try {
|
|
1242
|
+
await toggleEphemeral(sock, remoteJid, duration);
|
|
1243
|
+
await sendAndStore(sock, remoteJid, { text: `Configuração de mensagens temporárias atualizada para ${duration} segundos.` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1244
|
+
} catch (error) {
|
|
1245
|
+
await sendAndStore(sock, remoteJid, { text: `Não foi possível atualizar mensagens efêmeras. Detalhes: ${error.message}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1246
|
+
}
|
|
1247
|
+
break;
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
case 'addmode': {
|
|
1251
|
+
if (!isGroupMessage) {
|
|
1252
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1253
|
+
break;
|
|
1254
|
+
}
|
|
1255
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
1256
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1257
|
+
break;
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
if (args.length < 1 || !['all_member_add', 'admin_add'].includes(args[0])) {
|
|
1261
|
+
await sendAndStore(
|
|
1262
|
+
sock,
|
|
1263
|
+
remoteJid,
|
|
1264
|
+
{
|
|
1265
|
+
text: getAdminUsageText('addmode', { commandPrefix }),
|
|
1266
|
+
},
|
|
1267
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1268
|
+
);
|
|
1269
|
+
break;
|
|
1270
|
+
}
|
|
1271
|
+
const mode = args[0];
|
|
1272
|
+
try {
|
|
1273
|
+
await updateGroupAddMode(sock, remoteJid, mode);
|
|
1274
|
+
await sendAndStore(sock, remoteJid, { text: `Modo de adição de membros atualizado com sucesso para: ${mode}.` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1275
|
+
} catch (error) {
|
|
1276
|
+
await sendAndStore(
|
|
1277
|
+
sock,
|
|
1278
|
+
remoteJid,
|
|
1279
|
+
{
|
|
1280
|
+
text: `Não foi possível atualizar o modo de adição de membros. Detalhes: ${error.message}`,
|
|
1281
|
+
},
|
|
1282
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1283
|
+
);
|
|
1284
|
+
}
|
|
1285
|
+
break;
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
case 'prefix': {
|
|
1289
|
+
if (!isGroupMessage) {
|
|
1290
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1291
|
+
break;
|
|
1292
|
+
}
|
|
1293
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
1294
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1295
|
+
break;
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
const rawPrefix = args[0]?.trim();
|
|
1299
|
+
const normalizedKeyword = rawPrefix?.toLowerCase();
|
|
1300
|
+
const usageText = getAdminUsageText('prefix', { commandPrefix });
|
|
1301
|
+
|
|
1302
|
+
if (!rawPrefix) {
|
|
1303
|
+
await sendAndStore(sock, remoteJid, { text: usageText }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1304
|
+
break;
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
if (['status', 'info'].includes(normalizedKeyword)) {
|
|
1308
|
+
const config = await groupConfigStore.getGroupConfig(remoteJid);
|
|
1309
|
+
const customPrefix = typeof config.commandPrefix === 'string' ? config.commandPrefix.trim() : '';
|
|
1310
|
+
const currentPrefix = customPrefix || DEFAULT_COMMAND_PREFIX;
|
|
1311
|
+
const isCustom = Boolean(customPrefix && customPrefix !== DEFAULT_COMMAND_PREFIX);
|
|
1312
|
+
await sendAndStore(
|
|
1313
|
+
sock,
|
|
1314
|
+
remoteJid,
|
|
1315
|
+
{
|
|
1316
|
+
text: [`🔧 Prefixo ativo neste grupo: *${currentPrefix}*`, `Prefixo padrão global: *${DEFAULT_COMMAND_PREFIX}*`, isCustom ? '✅ Este grupo utiliza um prefixo personalizado.' : 'ℹ️ Este grupo utiliza o prefixo padrão.'].join('\n'),
|
|
1317
|
+
},
|
|
1318
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1319
|
+
);
|
|
1320
|
+
break;
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
if (['reset', 'default', 'padrao', 'padrão'].includes(normalizedKeyword)) {
|
|
1324
|
+
await groupConfigStore.updateGroupConfig(remoteJid, { commandPrefix: null });
|
|
1325
|
+
await sendAndStore(
|
|
1326
|
+
sock,
|
|
1327
|
+
remoteJid,
|
|
1328
|
+
{
|
|
1329
|
+
text: `✅ Prefixo restaurado para o padrão global: *${DEFAULT_COMMAND_PREFIX}*`,
|
|
1330
|
+
},
|
|
1331
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1332
|
+
);
|
|
1333
|
+
break;
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
if (rawPrefix.length > 5) {
|
|
1337
|
+
await sendAndStore(sock, remoteJid, { text: '⚠️ Prefixo inválido: utilize no máximo 5 caracteres.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1338
|
+
break;
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
if (/\s/.test(rawPrefix)) {
|
|
1342
|
+
await sendAndStore(sock, remoteJid, { text: '⚠️ Prefixo inválido: não utilize espaços.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1343
|
+
break;
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
const newPrefix = rawPrefix;
|
|
1347
|
+
if (newPrefix === DEFAULT_COMMAND_PREFIX) {
|
|
1348
|
+
await groupConfigStore.updateGroupConfig(remoteJid, { commandPrefix: null });
|
|
1349
|
+
await sendAndStore(
|
|
1350
|
+
sock,
|
|
1351
|
+
remoteJid,
|
|
1352
|
+
{
|
|
1353
|
+
text: `✅ Prefixo atualizado para o padrão global: *${DEFAULT_COMMAND_PREFIX}*`,
|
|
1354
|
+
},
|
|
1355
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1356
|
+
);
|
|
1357
|
+
break;
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
await groupConfigStore.updateGroupConfig(remoteJid, { commandPrefix: newPrefix });
|
|
1361
|
+
await sendAndStore(sock, remoteJid, { text: `✅ Prefixo deste grupo atualizado para: *${newPrefix}*` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1362
|
+
break;
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
case 'welcome': {
|
|
1366
|
+
if (!isGroupMessage) {
|
|
1367
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1368
|
+
break;
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
const subCommandMatch = text.trimStart().match(/^(\S+)([\s\S]*)$/);
|
|
1372
|
+
const subCommand = subCommandMatch ? subCommandMatch[1].toLowerCase() : '';
|
|
1373
|
+
const messageOrPath = subCommandMatch ? subCommandMatch[2].trimStart() : '';
|
|
1374
|
+
|
|
1375
|
+
if (!subCommand || !['on', 'off', 'set'].includes(subCommand)) {
|
|
1376
|
+
await sendAndStore(
|
|
1377
|
+
sock,
|
|
1378
|
+
remoteJid,
|
|
1379
|
+
{
|
|
1380
|
+
text: getAdminUsageText('welcome', { commandPrefix }),
|
|
1381
|
+
},
|
|
1382
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1383
|
+
);
|
|
1384
|
+
break;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
1388
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1389
|
+
break;
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
try {
|
|
1393
|
+
if (subCommand === 'on') {
|
|
1394
|
+
await groupConfigStore.updateGroupConfig(remoteJid, { welcomeMessageEnabled: true });
|
|
1395
|
+
await sendAndStore(sock, remoteJid, { text: 'Mensagens de boas-vindas ativadas com sucesso para este grupo.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1396
|
+
} else if (subCommand === 'off') {
|
|
1397
|
+
await groupConfigStore.updateGroupConfig(remoteJid, { welcomeMessageEnabled: false });
|
|
1398
|
+
await sendAndStore(sock, remoteJid, { text: 'Mensagens de boas-vindas desativadas com sucesso para este grupo.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1399
|
+
} else if (subCommand === 'set') {
|
|
1400
|
+
if (!messageOrPath && !(messageInfo.message.imageMessage || messageInfo.message.videoMessage)) {
|
|
1401
|
+
await sendAndStore(
|
|
1402
|
+
sock,
|
|
1403
|
+
remoteJid,
|
|
1404
|
+
{
|
|
1405
|
+
text: getAdminUsageText('welcome', {
|
|
1406
|
+
commandPrefix,
|
|
1407
|
+
variant: 'missing_content',
|
|
1408
|
+
}),
|
|
1409
|
+
},
|
|
1410
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1411
|
+
);
|
|
1412
|
+
break;
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
const quotedMessage = messageInfo.message?.extendedTextMessage?.contextInfo?.quotedMessage;
|
|
1416
|
+
let mediaToDownload = null;
|
|
1417
|
+
let mediaType = null;
|
|
1418
|
+
|
|
1419
|
+
if (messageInfo.message.imageMessage) {
|
|
1420
|
+
mediaToDownload = messageInfo.message.imageMessage;
|
|
1421
|
+
mediaType = 'image';
|
|
1422
|
+
} else if (messageInfo.message.videoMessage) {
|
|
1423
|
+
mediaToDownload = messageInfo.message.videoMessage;
|
|
1424
|
+
mediaType = 'video';
|
|
1425
|
+
} else if (quotedMessage) {
|
|
1426
|
+
if (quotedMessage.imageMessage) {
|
|
1427
|
+
mediaToDownload = quotedMessage.imageMessage;
|
|
1428
|
+
mediaType = 'image';
|
|
1429
|
+
} else if (quotedMessage.videoMessage) {
|
|
1430
|
+
mediaToDownload = quotedMessage.videoMessage;
|
|
1431
|
+
mediaType = 'video';
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
if (mediaToDownload) {
|
|
1436
|
+
const downloadedMediaPath = await downloadMediaMessage(mediaToDownload, mediaType, './temp');
|
|
1437
|
+
if (downloadedMediaPath) {
|
|
1438
|
+
await groupConfigStore.updateGroupConfig(remoteJid, {
|
|
1439
|
+
welcomeMedia: downloadedMediaPath,
|
|
1440
|
+
});
|
|
1441
|
+
await sendAndStore(sock, remoteJid, { text: `Mídia de boas-vindas configurada com sucesso: ${downloadedMediaPath}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1442
|
+
} else {
|
|
1443
|
+
await sendAndStore(
|
|
1444
|
+
sock,
|
|
1445
|
+
remoteJid,
|
|
1446
|
+
{
|
|
1447
|
+
text: 'Não foi possível processar a mídia informada. Tente novamente em instantes.',
|
|
1448
|
+
},
|
|
1449
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1450
|
+
);
|
|
1451
|
+
}
|
|
1452
|
+
} else if (messageOrPath.startsWith('/') || messageOrPath.startsWith('.') || messageOrPath.startsWith('~')) {
|
|
1453
|
+
await groupConfigStore.updateGroupConfig(remoteJid, {
|
|
1454
|
+
welcomeMedia: messageOrPath,
|
|
1455
|
+
});
|
|
1456
|
+
await sendAndStore(sock, remoteJid, { text: `Mídia de boas-vindas configurada com sucesso: ${messageOrPath}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1457
|
+
} else {
|
|
1458
|
+
await groupConfigStore.updateGroupConfig(remoteJid, {
|
|
1459
|
+
welcomeMessage: messageOrPath,
|
|
1460
|
+
});
|
|
1461
|
+
await sendAndStore(sock, remoteJid, { text: `Mensagem de boas-vindas configurada com sucesso: ${messageOrPath}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
} catch (error) {
|
|
1465
|
+
await sendAndStore(
|
|
1466
|
+
sock,
|
|
1467
|
+
remoteJid,
|
|
1468
|
+
{
|
|
1469
|
+
text: `Não foi possível configurar mensagens de boas-vindas. Detalhes: ${error.message}`,
|
|
1470
|
+
},
|
|
1471
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1472
|
+
);
|
|
1473
|
+
}
|
|
1474
|
+
break;
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
case 'farewell': {
|
|
1478
|
+
if (!isGroupMessage) {
|
|
1479
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1480
|
+
break;
|
|
1481
|
+
}
|
|
1482
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
1483
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1484
|
+
break;
|
|
1485
|
+
}
|
|
1486
|
+
const subCommandMatch = text.trimStart().match(/^(\S+)([\s\S]*)$/);
|
|
1487
|
+
const subCommand = subCommandMatch ? subCommandMatch[1].toLowerCase() : '';
|
|
1488
|
+
const messageOrPath = subCommandMatch ? subCommandMatch[2].trimStart() : '';
|
|
1489
|
+
|
|
1490
|
+
if (!subCommand || !['on', 'off', 'set'].includes(subCommand)) {
|
|
1491
|
+
await sendAndStore(
|
|
1492
|
+
sock,
|
|
1493
|
+
remoteJid,
|
|
1494
|
+
{
|
|
1495
|
+
text: getAdminUsageText('farewell', { commandPrefix }),
|
|
1496
|
+
},
|
|
1497
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1498
|
+
);
|
|
1499
|
+
break;
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
try {
|
|
1503
|
+
if (subCommand === 'on') {
|
|
1504
|
+
await groupConfigStore.updateGroupConfig(remoteJid, { farewellMessageEnabled: true });
|
|
1505
|
+
await sendAndStore(sock, remoteJid, { text: 'Mensagens de saída ativadas com sucesso para este grupo.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1506
|
+
} else if (subCommand === 'off') {
|
|
1507
|
+
await groupConfigStore.updateGroupConfig(remoteJid, { farewellMessageEnabled: false });
|
|
1508
|
+
await sendAndStore(sock, remoteJid, { text: 'Mensagens de saída desativadas com sucesso para este grupo.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1509
|
+
} else if (subCommand === 'set') {
|
|
1510
|
+
if (!messageOrPath && !(messageInfo.message.imageMessage || messageInfo.message.videoMessage)) {
|
|
1511
|
+
await sendAndStore(
|
|
1512
|
+
sock,
|
|
1513
|
+
remoteJid,
|
|
1514
|
+
{
|
|
1515
|
+
text: getAdminUsageText('farewell', {
|
|
1516
|
+
commandPrefix,
|
|
1517
|
+
variant: 'missing_content',
|
|
1518
|
+
}),
|
|
1519
|
+
},
|
|
1520
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1521
|
+
);
|
|
1522
|
+
break;
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
const quotedMessage = messageInfo.message?.extendedTextMessage?.contextInfo?.quotedMessage;
|
|
1526
|
+
let mediaToDownload = null;
|
|
1527
|
+
let mediaType = null;
|
|
1528
|
+
|
|
1529
|
+
if (messageInfo.message.imageMessage) {
|
|
1530
|
+
mediaToDownload = messageInfo.message.imageMessage;
|
|
1531
|
+
mediaType = 'image';
|
|
1532
|
+
} else if (messageInfo.message.videoMessage) {
|
|
1533
|
+
mediaToDownload = messageInfo.message.videoMessage;
|
|
1534
|
+
mediaType = 'video';
|
|
1535
|
+
} else if (quotedMessage) {
|
|
1536
|
+
if (quotedMessage.imageMessage) {
|
|
1537
|
+
mediaToDownload = quotedMessage.imageMessage;
|
|
1538
|
+
mediaType = 'image';
|
|
1539
|
+
} else if (quotedMessage.videoMessage) {
|
|
1540
|
+
mediaToDownload = quotedMessage.videoMessage;
|
|
1541
|
+
mediaType = 'video';
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
if (mediaToDownload) {
|
|
1546
|
+
const downloadedMediaPath = await downloadMediaMessage(mediaToDownload, mediaType, './temp');
|
|
1547
|
+
if (downloadedMediaPath) {
|
|
1548
|
+
await groupConfigStore.updateGroupConfig(remoteJid, {
|
|
1549
|
+
farewellMedia: downloadedMediaPath,
|
|
1550
|
+
});
|
|
1551
|
+
await sendAndStore(sock, remoteJid, { text: `Mídia de saída configurada com sucesso: ${downloadedMediaPath}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1552
|
+
} else {
|
|
1553
|
+
await sendAndStore(
|
|
1554
|
+
sock,
|
|
1555
|
+
remoteJid,
|
|
1556
|
+
{
|
|
1557
|
+
text: 'Não foi possível processar a mídia informada. Tente novamente em instantes.',
|
|
1558
|
+
},
|
|
1559
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1560
|
+
);
|
|
1561
|
+
}
|
|
1562
|
+
} else if (messageOrPath.startsWith('/') || messageOrPath.startsWith('.') || messageOrPath.startsWith('~')) {
|
|
1563
|
+
await groupConfigStore.updateGroupConfig(remoteJid, {
|
|
1564
|
+
farewellMedia: messageOrPath,
|
|
1565
|
+
});
|
|
1566
|
+
await sendAndStore(sock, remoteJid, { text: `Mídia de saída configurada com sucesso: ${messageOrPath}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1567
|
+
} else {
|
|
1568
|
+
await groupConfigStore.updateGroupConfig(remoteJid, {
|
|
1569
|
+
farewellMessage: messageOrPath,
|
|
1570
|
+
});
|
|
1571
|
+
await sendAndStore(sock, remoteJid, { text: `Mensagem de saída configurada com sucesso: ${messageOrPath}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
} catch (error) {
|
|
1575
|
+
await sendAndStore(sock, remoteJid, { text: `Não foi possível configurar mensagens de saída. Detalhes: ${error.message}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1576
|
+
}
|
|
1577
|
+
break;
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
case 'captcha': {
|
|
1581
|
+
if (!isGroupMessage) {
|
|
1582
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1583
|
+
break;
|
|
1584
|
+
}
|
|
1585
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
1586
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1587
|
+
break;
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
const action = args[0]?.toLowerCase();
|
|
1591
|
+
if (!action || !['on', 'off', 'status'].includes(action)) {
|
|
1592
|
+
await sendAndStore(sock, remoteJid, { text: getAdminUsageText('captcha', { commandPrefix }) }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1593
|
+
break;
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
if (action === 'status') {
|
|
1597
|
+
const config = await groupConfigStore.getGroupConfig(remoteJid);
|
|
1598
|
+
const enabled = Boolean(config.captchaEnabled);
|
|
1599
|
+
await sendAndStore(
|
|
1600
|
+
sock,
|
|
1601
|
+
remoteJid,
|
|
1602
|
+
{
|
|
1603
|
+
text: `🤖 Captcha neste grupo: *${enabled ? 'ativado' : 'desativado'}*.\n` + 'Quando ativo, novos membros precisam reagir ou enviar uma mensagem em até 5 minutos.',
|
|
1604
|
+
},
|
|
1605
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1606
|
+
);
|
|
1607
|
+
break;
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
const enabled = action === 'on';
|
|
1611
|
+
await groupConfigStore.updateGroupConfig(remoteJid, { captchaEnabled: enabled });
|
|
1612
|
+
if (!enabled) {
|
|
1613
|
+
clearCaptchasForGroup(remoteJid, 'disabled');
|
|
1614
|
+
}
|
|
1615
|
+
await sendAndStore(
|
|
1616
|
+
sock,
|
|
1617
|
+
remoteJid,
|
|
1618
|
+
{
|
|
1619
|
+
text: enabled ? '✅ Captcha ativado. Novos membros terão 5 minutos para reagir ou enviar mensagem.' : '🛑 Captcha desativado para este grupo.',
|
|
1620
|
+
},
|
|
1621
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1622
|
+
);
|
|
1623
|
+
break;
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
case 'antilink': {
|
|
1627
|
+
if (!isGroupMessage) {
|
|
1628
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1629
|
+
break;
|
|
1630
|
+
}
|
|
1631
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
1632
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1633
|
+
break;
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
const subCommand = args[0] ? args[0].toLowerCase() : '';
|
|
1637
|
+
const currentConfig = await groupConfigStore.getGroupConfig(remoteJid);
|
|
1638
|
+
const allowedNetworks = currentConfig.antilinkAllowedNetworks || [];
|
|
1639
|
+
const allowedDomains = currentConfig.antilinkAllowedDomains || [];
|
|
1640
|
+
const availableNetworks = Object.keys(KNOWN_NETWORKS).sort();
|
|
1641
|
+
|
|
1642
|
+
const parseNetworks = (inputArgs) => {
|
|
1643
|
+
const raw = inputArgs.flatMap((value) => value.split(','));
|
|
1644
|
+
return raw.map((value) => value.trim().toLowerCase()).filter(Boolean);
|
|
1645
|
+
};
|
|
1646
|
+
|
|
1647
|
+
const formatNetworkList = (networks) => (networks.length ? networks.join(', ') : 'nenhuma');
|
|
1648
|
+
|
|
1649
|
+
if (!['on', 'off'].includes(subCommand)) {
|
|
1650
|
+
if (subCommand === 'list') {
|
|
1651
|
+
const status = currentConfig.antilinkEnabled ? 'ativado' : 'desativado';
|
|
1652
|
+
await sendAndStore(
|
|
1653
|
+
sock,
|
|
1654
|
+
remoteJid,
|
|
1655
|
+
{
|
|
1656
|
+
text: `📋 *Antilink - Configuração atual*\n` + `Status: *${status}*\n\n` + `✅ *Redes permitidas*\n${formatNetworkList(allowedNetworks)}\n\n` + `✅ *Domínios permitidos*\n${formatNetworkList(allowedDomains)}\n\n` + `🧭 *Redes disponíveis*\n${availableNetworks.join(', ')}`,
|
|
1657
|
+
},
|
|
1658
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1659
|
+
);
|
|
1660
|
+
break;
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
if (subCommand === 'allow' || subCommand === 'disallow') {
|
|
1664
|
+
const requestedNetworks = parseNetworks(args.slice(1));
|
|
1665
|
+
const validNetworks = requestedNetworks.filter((name) => KNOWN_NETWORKS[name]);
|
|
1666
|
+
const invalidNetworks = requestedNetworks.filter((name) => !KNOWN_NETWORKS[name]);
|
|
1667
|
+
|
|
1668
|
+
if (validNetworks.length === 0) {
|
|
1669
|
+
await sendAndStore(
|
|
1670
|
+
sock,
|
|
1671
|
+
remoteJid,
|
|
1672
|
+
{
|
|
1673
|
+
text: `${getAdminUsageText('antilink', { commandPrefix, variant: subCommand })}\n` + `Redes disponíveis: ${availableNetworks.join(', ')}`,
|
|
1674
|
+
},
|
|
1675
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1676
|
+
);
|
|
1677
|
+
break;
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
const updatedNetworks = subCommand === 'allow' ? Array.from(new Set([...allowedNetworks, ...validNetworks])) : allowedNetworks.filter((name) => !validNetworks.includes(name));
|
|
1681
|
+
|
|
1682
|
+
await groupConfigStore.updateGroupConfig(remoteJid, {
|
|
1683
|
+
antilinkAllowedNetworks: updatedNetworks,
|
|
1684
|
+
});
|
|
1685
|
+
|
|
1686
|
+
const invalidNote = invalidNetworks.length ? `\nIgnorados: ${invalidNetworks.join(', ')}` : '';
|
|
1687
|
+
await sendAndStore(
|
|
1688
|
+
sock,
|
|
1689
|
+
remoteJid,
|
|
1690
|
+
{
|
|
1691
|
+
text: `Redes permitidas atualizadas: ${formatNetworkList(updatedNetworks)}${invalidNote}`,
|
|
1692
|
+
},
|
|
1693
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1694
|
+
);
|
|
1695
|
+
break;
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
if (subCommand === 'add' || subCommand === 'remove') {
|
|
1699
|
+
const requestedDomains = parseNetworks(args.slice(1));
|
|
1700
|
+
const normalizedDomains = requestedDomains.map((domain) =>
|
|
1701
|
+
domain
|
|
1702
|
+
.replace(/^https?:\/\//, '')
|
|
1703
|
+
.replace(/^www\./, '')
|
|
1704
|
+
.replace(/\/.*$/, ''),
|
|
1705
|
+
);
|
|
1706
|
+
|
|
1707
|
+
if (normalizedDomains.length === 0) {
|
|
1708
|
+
await sendAndStore(
|
|
1709
|
+
sock,
|
|
1710
|
+
remoteJid,
|
|
1711
|
+
{
|
|
1712
|
+
text: getAdminUsageText('antilink', { commandPrefix, variant: subCommand }),
|
|
1713
|
+
},
|
|
1714
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1715
|
+
);
|
|
1716
|
+
break;
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
const updatedDomains = subCommand === 'add' ? Array.from(new Set([...allowedDomains, ...normalizedDomains])) : allowedDomains.filter((domain) => !normalizedDomains.includes(domain));
|
|
1720
|
+
|
|
1721
|
+
await groupConfigStore.updateGroupConfig(remoteJid, {
|
|
1722
|
+
antilinkAllowedDomains: updatedDomains,
|
|
1723
|
+
});
|
|
1724
|
+
await sendAndStore(sock, remoteJid, { text: `Domínios permitidos atualizados: ${formatNetworkList(updatedDomains)}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1725
|
+
break;
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
const status = currentConfig.antilinkEnabled ? 'ativado' : 'desativado';
|
|
1729
|
+
await sendAndStore(
|
|
1730
|
+
sock,
|
|
1731
|
+
remoteJid,
|
|
1732
|
+
{
|
|
1733
|
+
text: `📌 *Guia de uso do Antilink*\n` + `Status atual: *${status}*\n\n` + `✅ *${commandPrefix}antilink on*\nAtiva o bloqueio de links no grupo.\n\n` + `⛔ *${commandPrefix}antilink off*\nDesativa o bloqueio de links no grupo.\n\n` + `📋 *${commandPrefix}antilink list*\nExibe as redes e os domínios permitidos.\n\n` + `➕ *${commandPrefix}antilink allow <rede>*\nPermite uma rede conhecida (ex.: youtube, instagram).\n\n` + `➖ *${commandPrefix}antilink disallow <rede>*\nRemove uma rede conhecida da lista permitida.\n\n` + `🌐 *${commandPrefix}antilink add <dominio>*\nPermite um domínio específico (ex.: exemplo.com).\n\n` + `🗑️ *${commandPrefix}antilink remove <dominio>*\nRemove um domínio específico da lista permitida.\n\n` + `ℹ️ Dica: use *${commandPrefix}antilink list* para consultar as redes disponíveis.`,
|
|
1734
|
+
},
|
|
1735
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1736
|
+
);
|
|
1737
|
+
break;
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
try {
|
|
1741
|
+
const isEnabled = subCommand === 'on';
|
|
1742
|
+
await groupConfigStore.updateGroupConfig(remoteJid, { antilinkEnabled: isEnabled });
|
|
1743
|
+
await sendAndStore(
|
|
1744
|
+
sock,
|
|
1745
|
+
remoteJid,
|
|
1746
|
+
{
|
|
1747
|
+
text: `✅ Recurso Antilink ${isEnabled ? 'ativado' : 'desativado'} com sucesso neste grupo.`,
|
|
1748
|
+
},
|
|
1749
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1750
|
+
);
|
|
1751
|
+
} catch (error) {
|
|
1752
|
+
logger.error('Erro ao configurar o antilink:', {
|
|
1753
|
+
error: error.message,
|
|
1754
|
+
groupId: remoteJid,
|
|
1755
|
+
});
|
|
1756
|
+
await sendAndStore(sock, remoteJid, { text: `Não foi possível configurar o antilink. Detalhes: ${error.message}` }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1757
|
+
}
|
|
1758
|
+
break;
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
case 'noticias': {
|
|
1762
|
+
if (!isGroupMessage) {
|
|
1763
|
+
await sendAndStore(sock, remoteJid, { text: GROUP_ONLY_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1764
|
+
break;
|
|
1765
|
+
}
|
|
1766
|
+
if (!(await isUserAdmin(remoteJid, senderIdentity))) {
|
|
1767
|
+
await sendAndStore(sock, remoteJid, { text: NO_PERMISSION_COMMAND_MESSAGE }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1768
|
+
break;
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
const action = args[0]?.toLowerCase();
|
|
1772
|
+
if (!action || !['on', 'off', 'status'].includes(action)) {
|
|
1773
|
+
await sendAndStore(
|
|
1774
|
+
sock,
|
|
1775
|
+
remoteJid,
|
|
1776
|
+
{
|
|
1777
|
+
text: getAdminUsageText('noticias', { commandPrefix }),
|
|
1778
|
+
},
|
|
1779
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1780
|
+
);
|
|
1781
|
+
break;
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
if (action === 'status') {
|
|
1785
|
+
const status = await getNewsStatusForGroup(remoteJid);
|
|
1786
|
+
const enabledText = status.enabled ? 'ATIVADO' : 'DESATIVADO';
|
|
1787
|
+
const lastSent = status.lastSentAt ? `\nÚltimo envio: ${status.lastSentAt}` : '';
|
|
1788
|
+
await sendAndStore(
|
|
1789
|
+
sock,
|
|
1790
|
+
remoteJid,
|
|
1791
|
+
{
|
|
1792
|
+
text: `📰 Status de notícias neste grupo: *${enabledText.toLowerCase()}*.\nTotal de envios: ${status.sentCount}.${lastSent}`,
|
|
1793
|
+
},
|
|
1794
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1795
|
+
);
|
|
1796
|
+
break;
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
const enableNews = action === 'on';
|
|
1800
|
+
await groupConfigStore.updateGroupConfig(remoteJid, { newsEnabled: enableNews });
|
|
1801
|
+
if (enableNews) {
|
|
1802
|
+
startNewsBroadcastForGroup(remoteJid);
|
|
1803
|
+
await sendAndStore(
|
|
1804
|
+
sock,
|
|
1805
|
+
remoteJid,
|
|
1806
|
+
{
|
|
1807
|
+
text: '📰 Envio automático de notícias ativado. As atualizações serão enviadas com intervalo aproximado de 1 a 2 minutos.',
|
|
1808
|
+
},
|
|
1809
|
+
{ quoted: messageInfo, ephemeralExpiration: expirationMessage },
|
|
1810
|
+
);
|
|
1811
|
+
} else {
|
|
1812
|
+
stopNewsBroadcastForGroup(remoteJid);
|
|
1813
|
+
await sendAndStore(sock, remoteJid, { text: '🛑 Envio automático de notícias desativado para este grupo.' }, { quoted: messageInfo, ephemeralExpiration: expirationMessage });
|
|
1814
|
+
}
|
|
1815
|
+
break;
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
default:
|
|
1819
|
+
break;
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
return true;
|
|
1823
|
+
}
|