@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,942 @@
|
|
|
1
|
+
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { createRoot } from 'react-dom/client';
|
|
3
|
+
import htm from 'htm';
|
|
4
|
+
|
|
5
|
+
const html = htm.bind(React.createElement);
|
|
6
|
+
|
|
7
|
+
const FALLBACK_THUMB_URL = '/assets/images/brand-logo-128.webp';
|
|
8
|
+
const HOME_BOOTSTRAP_ENDPOINT = '/api/home-bootstrap';
|
|
9
|
+
const COMMANDS_CATALOG_ENDPOINT = '/comandos/commands-catalog.json';
|
|
10
|
+
const SOCIAL_PROOF_REFRESH_MS = 15_000;
|
|
11
|
+
const COUNTUP_DURATION_MS = 1200;
|
|
12
|
+
const COUNTABLE_METRICS = ['users', 'messages', 'commands', 'packs', 'stickers'];
|
|
13
|
+
const REVEAL_STAGGER_MS = 60;
|
|
14
|
+
const MAX_REVEAL_DELAY_MS = 400;
|
|
15
|
+
|
|
16
|
+
const DEFAULT_METRICS = {
|
|
17
|
+
users: '50k+',
|
|
18
|
+
messages: '100M+',
|
|
19
|
+
commands: '1,7 mil',
|
|
20
|
+
packs: '10k+',
|
|
21
|
+
stickers: '500k+',
|
|
22
|
+
latency: '...',
|
|
23
|
+
status: 'online',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const NAV_ITEMS = [
|
|
27
|
+
{ href: '#recursos', label: 'Recursos' },
|
|
28
|
+
{ href: '/comandos/', label: 'Biblioteca de Comandos' },
|
|
29
|
+
{ href: '#guias', label: 'Guias' },
|
|
30
|
+
{ href: '/api-docs/', label: 'API Docs' },
|
|
31
|
+
{ href: '#faq', label: 'FAQ' },
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
const GUIDES = [
|
|
35
|
+
{ href: '/seo/bot-whatsapp-para-grupo/', title: 'Bot para Grupos', desc: 'Guia de entrada rápida para iniciantes.' },
|
|
36
|
+
{ href: '/seo/como-moderar-grupo-whatsapp/', title: 'Guia de Moderação', desc: 'Como manter seu grupo limpo e seguro.' },
|
|
37
|
+
{ href: '/seo/como-evitar-spam-no-whatsapp/', title: 'Anti-Spam 101', desc: 'Proteja sua comunidade de bots invasores.' },
|
|
38
|
+
{ href: '/seo/melhor-bot-whatsapp-para-grupos/', title: 'Comparativo', desc: 'Por que o OmniZap é a melhor escolha.' },
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
const FAQS = [
|
|
42
|
+
{ q: 'Preciso saber programar?', a: 'Não. O bot é plug-and-play. Basta adicionar ao grupo e enviar /iniciar.' },
|
|
43
|
+
{ q: 'É seguro para meus dados?', a: 'Sim. Seguimos a LGPD rigorosamente. Veja nossa política de privacidade para detalhes.' },
|
|
44
|
+
{ q: 'Funciona em comunidades?', a: 'Com certeza! O OmniZap escala perfeitamente de pequenos grupos a grandes comunidades.' },
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
const FEATURES = [
|
|
48
|
+
{ title: 'IA Generativa', desc: 'Respostas inteligentes e comandos de visão computacional direto no chat.', icon: '🤖' },
|
|
49
|
+
{ title: 'Gestão de Packs', desc: 'Crie e organize coleções de figurinhas via web ou comandos.', icon: '🎨' },
|
|
50
|
+
{ title: 'Moderação 24/7', desc: 'Anti-link, captcha e proteção automática contra spam em tempo real.', icon: '🛡️' },
|
|
51
|
+
{ title: 'Engajamento', desc: 'Rankings, jogos e sistemas de reputação para sua comunidade.', icon: '📈' },
|
|
52
|
+
{ title: 'Multi-Mídia', desc: 'Download de vídeos, músicas e conversões instantâneas.', icon: '🎵' },
|
|
53
|
+
{ title: 'Privacidade', desc: 'Segurança total e conformidade com LGPD para seus dados.', icon: '🔐' },
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
const STEPS = [
|
|
57
|
+
{ step: '01', title: 'Adicione o Bot', desc: 'Clique em Adicionar e escolha seu grupo ou chat privado.' },
|
|
58
|
+
{ step: '02', title: 'Envie /iniciar', desc: 'O bot irá configurar o ambiente e liberar os comandos básicos.' },
|
|
59
|
+
{ step: '03', title: 'Explore a IA', desc: 'Use comandos como /ia ou /s para sentir o poder da automação.' },
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
const COMMAND_BLOCKS = [
|
|
63
|
+
{
|
|
64
|
+
title: 'Figurinhas',
|
|
65
|
+
items: [
|
|
66
|
+
['/s', 'Cria figurinha'],
|
|
67
|
+
['/st', 'Figurinha rápida'],
|
|
68
|
+
['/pack create', 'Cria pack web'],
|
|
69
|
+
['/toimg', 'Sticker para imagem'],
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
title: 'Administração',
|
|
74
|
+
items: [
|
|
75
|
+
['/ban', 'Remove usuário'],
|
|
76
|
+
['/captcha', 'Ativa proteção'],
|
|
77
|
+
['/noticias', 'Broadcast de news'],
|
|
78
|
+
['/setgroup', 'Configura grupo'],
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
title: 'Utilidades',
|
|
83
|
+
items: [
|
|
84
|
+
['/play', 'Toca música'],
|
|
85
|
+
['/tiktok', 'Baixa vídeo'],
|
|
86
|
+
['/user perfil', 'Dados da conta'],
|
|
87
|
+
['/menu ia', 'Menu de IA'],
|
|
88
|
+
],
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
let homeBootstrapPayloadPromise = null;
|
|
93
|
+
|
|
94
|
+
const loadHomeBootstrapPayload = async () => {
|
|
95
|
+
const response = await fetch(HOME_BOOTSTRAP_ENDPOINT, { credentials: 'include' });
|
|
96
|
+
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
97
|
+
const payload = await response.json();
|
|
98
|
+
return payload?.data || {};
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const fetchHomeBootstrapPayload = async ({ forceRefresh = false } = {}) => {
|
|
102
|
+
if (forceRefresh) {
|
|
103
|
+
const freshData = await loadHomeBootstrapPayload();
|
|
104
|
+
homeBootstrapPayloadPromise = Promise.resolve(freshData);
|
|
105
|
+
return freshData;
|
|
106
|
+
}
|
|
107
|
+
if (!homeBootstrapPayloadPromise) {
|
|
108
|
+
homeBootstrapPayloadPromise = loadHomeBootstrapPayload().catch((err) => {
|
|
109
|
+
homeBootstrapPayloadPromise = null;
|
|
110
|
+
throw err;
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
return homeBootstrapPayloadPromise;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const shortNum = (value) =>
|
|
117
|
+
new Intl.NumberFormat('pt-BR', {
|
|
118
|
+
notation: Number(value) >= 1000 ? 'compact' : 'standard',
|
|
119
|
+
maximumFractionDigits: 1,
|
|
120
|
+
}).format(Math.max(0, Number(value) || 0));
|
|
121
|
+
|
|
122
|
+
const normalizeSearchText = (value) =>
|
|
123
|
+
String(value || '')
|
|
124
|
+
.normalize('NFD')
|
|
125
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
126
|
+
.toLowerCase()
|
|
127
|
+
.trim();
|
|
128
|
+
|
|
129
|
+
const scoreCommandMatch = (command, term) => {
|
|
130
|
+
const name = normalizeSearchText(command.name);
|
|
131
|
+
const description = normalizeSearchText(command.descricao);
|
|
132
|
+
const aliases = (command.aliases || []).map(normalizeSearchText).filter(Boolean);
|
|
133
|
+
const keywords = (command.keywords || []).map(normalizeSearchText).filter(Boolean);
|
|
134
|
+
|
|
135
|
+
if (name === term) return 120;
|
|
136
|
+
if (aliases.includes(term)) return 110;
|
|
137
|
+
if (name.startsWith(term)) return 95;
|
|
138
|
+
if (aliases.some((alias) => alias.startsWith(term))) return 85;
|
|
139
|
+
if (name.includes(term)) return 70;
|
|
140
|
+
if (aliases.some((alias) => alias.includes(term))) return 62;
|
|
141
|
+
if (keywords.some((keyword) => keyword.includes(term))) return 45;
|
|
142
|
+
if (description.includes(term)) return 35;
|
|
143
|
+
return 0;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const App = () => {
|
|
147
|
+
const [session, setSession] = useState(null);
|
|
148
|
+
const [botMenuUrl, setBotMenuUrl] = useState('/login/');
|
|
149
|
+
const [metrics, setMetrics] = useState(DEFAULT_METRICS);
|
|
150
|
+
const [commandBlocks, setCommandBlocks] = useState(COMMAND_BLOCKS);
|
|
151
|
+
const [fullCatalog, setFullCatalog] = useState(null);
|
|
152
|
+
const [searchTerm, setSearchTerm] = useState('');
|
|
153
|
+
const [simulationIndex, setSimulationIndex] = useState(0);
|
|
154
|
+
const counterValuesRef = useRef({ users: 0, messages: 0, commands: 0, packs: 0, stickers: 0 });
|
|
155
|
+
const counterFramesRef = useRef({});
|
|
156
|
+
|
|
157
|
+
const simulationMessages = [
|
|
158
|
+
{ visitor: 'Como faço stickers?', bot: 'Envie uma imagem com o comando /s e eu faço o resto! ✨' },
|
|
159
|
+
{ visitor: 'E pra moderar o grupo?', bot: 'Use /captcha ou /ban. Proteção 24/7 ativa. 🛡️' },
|
|
160
|
+
{ visitor: 'Baixa vídeo do TikTok?', bot: 'Sim! Mande o link e eu converto na hora. ⚡' },
|
|
161
|
+
{ visitor: 'Tem IA?', bot: 'Claro! Use /ia para conversar comigo agora. 🤖' },
|
|
162
|
+
];
|
|
163
|
+
|
|
164
|
+
const searchableCommands = useMemo(() => {
|
|
165
|
+
if (fullCatalog?.categories?.length) {
|
|
166
|
+
return fullCatalog.categories.flatMap((cat) =>
|
|
167
|
+
(cat.commands || []).map((cmd) => ({
|
|
168
|
+
key: `${cat.key || cat.label || 'cat'}:${cmd.name || cmd.key || ''}`,
|
|
169
|
+
name: String(cmd.name || ''),
|
|
170
|
+
descricao: String(cmd.descricao || ''),
|
|
171
|
+
aliases: Array.isArray(cmd.aliases) ? cmd.aliases : [],
|
|
172
|
+
keywords: Array.isArray(cmd.discovery?.keywords) ? cmd.discovery.keywords : [],
|
|
173
|
+
categoryLabel: String(cat.label || cmd.category_label || ''),
|
|
174
|
+
})),
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Fallback enquanto o catálogo completo não estiver disponível.
|
|
179
|
+
return commandBlocks.flatMap((block) =>
|
|
180
|
+
(block.items || []).map(([command, descricao], idx) => ({
|
|
181
|
+
key: `${block.title || 'cat'}:${idx}:${command || ''}`,
|
|
182
|
+
name: String(command || '').replace(/^\//, ''),
|
|
183
|
+
descricao: String(descricao || ''),
|
|
184
|
+
aliases: [],
|
|
185
|
+
keywords: [],
|
|
186
|
+
categoryLabel: String(block.title || ''),
|
|
187
|
+
})),
|
|
188
|
+
);
|
|
189
|
+
}, [fullCatalog, commandBlocks]);
|
|
190
|
+
|
|
191
|
+
const filteredCommandBlocks = useMemo(() => {
|
|
192
|
+
const rawTerm = String(searchTerm || '').trim();
|
|
193
|
+
const term = normalizeSearchText(rawTerm);
|
|
194
|
+
if (!term) return commandBlocks;
|
|
195
|
+
|
|
196
|
+
const rankedMatches = searchableCommands
|
|
197
|
+
.map((cmd) => ({ cmd, score: scoreCommandMatch(cmd, term) }))
|
|
198
|
+
.filter((entry) => entry.score > 0)
|
|
199
|
+
.sort((a, b) => b.score - a.score || a.cmd.name.localeCompare(b.cmd.name, 'pt-BR'));
|
|
200
|
+
|
|
201
|
+
if (!rankedMatches.length) {
|
|
202
|
+
return [
|
|
203
|
+
{
|
|
204
|
+
title: `Nenhum resultado para "${rawTerm}"`,
|
|
205
|
+
items: [['/menu', 'Tente termos como sticker, admin, musica ou IA']],
|
|
206
|
+
},
|
|
207
|
+
];
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const seen = new Set();
|
|
211
|
+
const items = [];
|
|
212
|
+
|
|
213
|
+
rankedMatches.forEach(({ cmd }) => {
|
|
214
|
+
if (items.length >= 12) return;
|
|
215
|
+
const dedupeKey = `${cmd.categoryLabel}|${cmd.name}`;
|
|
216
|
+
if (seen.has(dedupeKey)) return;
|
|
217
|
+
seen.add(dedupeKey);
|
|
218
|
+
|
|
219
|
+
const categorySuffix = cmd.categoryLabel ? ` • ${cmd.categoryLabel}` : '';
|
|
220
|
+
items.push([`/${cmd.name}`, `${cmd.descricao}${categorySuffix}`]);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
return [{ title: `Resultados para "${rawTerm}"`, items }];
|
|
224
|
+
}, [searchTerm, commandBlocks, searchableCommands]);
|
|
225
|
+
|
|
226
|
+
useEffect(() => {
|
|
227
|
+
const simInterval = setInterval(() => {
|
|
228
|
+
setSimulationIndex((prev) => (prev + 1) % simulationMessages.length);
|
|
229
|
+
}, 4000);
|
|
230
|
+
return () => clearInterval(simInterval);
|
|
231
|
+
}, []);
|
|
232
|
+
|
|
233
|
+
useEffect(() => {
|
|
234
|
+
let active = true;
|
|
235
|
+
const requestAnimation = typeof globalThis.requestAnimationFrame === 'function' ? globalThis.requestAnimationFrame.bind(globalThis) : null;
|
|
236
|
+
const cancelAnimation = typeof globalThis.cancelAnimationFrame === 'function' ? globalThis.cancelAnimationFrame.bind(globalThis) : null;
|
|
237
|
+
|
|
238
|
+
const animateCounter = (key, target) => {
|
|
239
|
+
if (!active || typeof requestAnimation !== 'function') {
|
|
240
|
+
setMetrics((m) => ({ ...m, [key]: shortNum(target) }));
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const startValue = counterValuesRef.current[key] || 0;
|
|
244
|
+
const startTime = performance.now();
|
|
245
|
+
|
|
246
|
+
const step = (now) => {
|
|
247
|
+
const progress = Math.min(1, (now - startTime) / COUNTUP_DURATION_MS);
|
|
248
|
+
const eased = 1 - Math.pow(1 - progress, 4); // Quart ease-out
|
|
249
|
+
const current = startValue + (target - startValue) * eased;
|
|
250
|
+
|
|
251
|
+
setMetrics((m) => ({ ...m, [key]: shortNum(current) }));
|
|
252
|
+
|
|
253
|
+
if (progress < 1) {
|
|
254
|
+
counterFramesRef.current[key] = requestAnimation(step);
|
|
255
|
+
} else {
|
|
256
|
+
counterValuesRef.current[key] = target;
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
if (typeof cancelAnimation === 'function') {
|
|
260
|
+
cancelAnimation(counterFramesRef.current[key]);
|
|
261
|
+
}
|
|
262
|
+
counterFramesRef.current[key] = requestAnimation(step);
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
const runLoad = async ({ forceRefresh = false } = {}) => {
|
|
266
|
+
try {
|
|
267
|
+
const data = await fetchHomeBootstrapPayload({ forceRefresh });
|
|
268
|
+
if (!active) return;
|
|
269
|
+
|
|
270
|
+
const realtime = data?.home_realtime || {};
|
|
271
|
+
const stats = data?.marketplace_stats?.data || data?.stats || {};
|
|
272
|
+
const summary = data?.system_summary || {};
|
|
273
|
+
const botContact = data?.bot_contact || {};
|
|
274
|
+
|
|
275
|
+
setSession(data?.session?.authenticated ? data.session : null);
|
|
276
|
+
|
|
277
|
+
// Tenta resolver a URL do bot de múltiplas fontes possíveis na resposta
|
|
278
|
+
const contactUrl = botContact?.urls?.menu || botContact?.url || '/login/';
|
|
279
|
+
setBotMenuUrl(contactUrl);
|
|
280
|
+
|
|
281
|
+
const targetValues = {
|
|
282
|
+
users: Number(realtime?.total_users || 0),
|
|
283
|
+
messages: Number(realtime?.total_messages || 0),
|
|
284
|
+
commands: Number(realtime?.total_commands || 0),
|
|
285
|
+
packs: Number(stats?.packs_total || stats?.total_packs || 0),
|
|
286
|
+
stickers: Number(stats?.stickers_total || stats?.total_stickers || 0),
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
COUNTABLE_METRICS.forEach((key) => animateCounter(key, targetValues[key]));
|
|
290
|
+
|
|
291
|
+
setMetrics((m) => ({
|
|
292
|
+
...m,
|
|
293
|
+
latency: realtime?.system_latency_ms ? `${Math.round(realtime.system_latency_ms)}ms` : '...',
|
|
294
|
+
status: (summary?.system_status || summary?.bot?.connection_status || 'online').toLowerCase(),
|
|
295
|
+
}));
|
|
296
|
+
|
|
297
|
+
// Início da parte que consome o catálogo
|
|
298
|
+
try {
|
|
299
|
+
const catalogRes = await fetch(COMMANDS_CATALOG_ENDPOINT);
|
|
300
|
+
if (catalogRes.ok) {
|
|
301
|
+
const catalog = await catalogRes.json();
|
|
302
|
+
setFullCatalog(catalog);
|
|
303
|
+
const featuredKeys = ['figurinhas', 'admin', 'midia']; // Featured categories from catalog
|
|
304
|
+
const blocks = (catalog.categories || [])
|
|
305
|
+
.filter((cat) => featuredKeys.includes(cat.key))
|
|
306
|
+
.sort((a, b) => featuredKeys.indexOf(a.key) - featuredKeys.indexOf(b.key))
|
|
307
|
+
.map((cat) => ({
|
|
308
|
+
title: cat.label,
|
|
309
|
+
items: (cat.commands || []).slice(0, 4).map((cmd) => [`/${cmd.name}`, cmd.descricao]),
|
|
310
|
+
}));
|
|
311
|
+
if (blocks.length > 0) setCommandBlocks(blocks);
|
|
312
|
+
}
|
|
313
|
+
} catch (catErr) {
|
|
314
|
+
console.warn('Catalog load error', catErr);
|
|
315
|
+
}
|
|
316
|
+
// Fim da parte que consome o catálogo
|
|
317
|
+
} catch (err) {
|
|
318
|
+
console.warn('Home bootstrap error', err);
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
runLoad();
|
|
323
|
+
const interval = setInterval(() => runLoad({ forceRefresh: true }), SOCIAL_PROOF_REFRESH_MS);
|
|
324
|
+
|
|
325
|
+
// Reveal Observer
|
|
326
|
+
const observer =
|
|
327
|
+
typeof globalThis.IntersectionObserver === 'function'
|
|
328
|
+
? new globalThis.IntersectionObserver(
|
|
329
|
+
(entries) => {
|
|
330
|
+
entries.forEach((entry) => {
|
|
331
|
+
if (entry.isIntersecting) {
|
|
332
|
+
entry.target.classList.add('is-visible');
|
|
333
|
+
observer.unobserve(entry.target);
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
},
|
|
337
|
+
{ threshold: 0.1, rootMargin: '0px 0px -50px 0px' },
|
|
338
|
+
)
|
|
339
|
+
: null;
|
|
340
|
+
|
|
341
|
+
document.querySelectorAll('[data-reveal]').forEach((el, i) => {
|
|
342
|
+
el.style.setProperty('--reveal-delay', `${Math.min(i * REVEAL_STAGGER_MS, MAX_REVEAL_DELAY_MS)}ms`);
|
|
343
|
+
if (observer) {
|
|
344
|
+
observer.observe(el);
|
|
345
|
+
} else {
|
|
346
|
+
el.classList.add('is-visible');
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
return () => {
|
|
351
|
+
active = false;
|
|
352
|
+
clearInterval(interval);
|
|
353
|
+
if (observer) observer.disconnect();
|
|
354
|
+
};
|
|
355
|
+
}, []);
|
|
356
|
+
|
|
357
|
+
const authInfo = useMemo(() => {
|
|
358
|
+
if (!session?.user) return { href: '/login/', label: 'Entrar', image: null };
|
|
359
|
+
return {
|
|
360
|
+
href: '/user/',
|
|
361
|
+
label: 'Perfil',
|
|
362
|
+
image: session.user.picture || FALLBACK_THUMB_URL,
|
|
363
|
+
};
|
|
364
|
+
}, [session]);
|
|
365
|
+
|
|
366
|
+
return html`
|
|
367
|
+
<style>
|
|
368
|
+
@keyframes marquee {
|
|
369
|
+
0% {
|
|
370
|
+
transform: translateX(0);
|
|
371
|
+
}
|
|
372
|
+
100% {
|
|
373
|
+
transform: translateX(-50%);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
.animate-marquee-infinite {
|
|
377
|
+
display: flex;
|
|
378
|
+
width: max-content;
|
|
379
|
+
animation: marquee 40s linear infinite;
|
|
380
|
+
}
|
|
381
|
+
@keyframes float {
|
|
382
|
+
0%,
|
|
383
|
+
100% {
|
|
384
|
+
transform: translateY(0) rotate(0deg);
|
|
385
|
+
}
|
|
386
|
+
50% {
|
|
387
|
+
transform: translateY(-20px) rotate(5deg);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
.animate-float {
|
|
391
|
+
animation: float 6s ease-in-out infinite;
|
|
392
|
+
}
|
|
393
|
+
@keyframes bounce-y {
|
|
394
|
+
0%,
|
|
395
|
+
100% {
|
|
396
|
+
transform: translateY(0);
|
|
397
|
+
opacity: 0.3;
|
|
398
|
+
}
|
|
399
|
+
50% {
|
|
400
|
+
transform: translateY(10px);
|
|
401
|
+
opacity: 1;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
.scroll-indicator-anim {
|
|
405
|
+
animation: bounce-y 2s infinite;
|
|
406
|
+
}
|
|
407
|
+
@keyframes gradient-x {
|
|
408
|
+
0%,
|
|
409
|
+
100% {
|
|
410
|
+
background-position: 0% 50%;
|
|
411
|
+
}
|
|
412
|
+
50% {
|
|
413
|
+
background-position: 100% 50%;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
.animate-gradient-x {
|
|
417
|
+
background-size: 200% 200%;
|
|
418
|
+
animation: gradient-x 15s ease infinite;
|
|
419
|
+
}
|
|
420
|
+
.no-scrollbar::-webkit-scrollbar {
|
|
421
|
+
display: none;
|
|
422
|
+
}
|
|
423
|
+
.no-scrollbar {
|
|
424
|
+
-ms-overflow-style: none;
|
|
425
|
+
scrollbar-width: none;
|
|
426
|
+
}
|
|
427
|
+
</style>
|
|
428
|
+
|
|
429
|
+
<div className="min-h-screen bg-[#020617] text-white font-sans selection:bg-primary selection:text-primary-content overflow-x-hidden">
|
|
430
|
+
<!-- Background Glow Orbs -->
|
|
431
|
+
<div className="fixed inset-0 pointer-events-none overflow-hidden z-0">
|
|
432
|
+
<div className="absolute top-[-10%] left-[-10%] w-[50%] h-[50%] bg-primary/10 blur-[120px] rounded-full animate-pulse"></div>
|
|
433
|
+
<div className="absolute bottom-[-10%] right-[-10%] w-[40%] h-[40%] bg-secondary/10 blur-[100px] rounded-full"></div>
|
|
434
|
+
<div className="absolute top-[40%] left-[20%] w-[20%] h-[20%] bg-emerald-500/5 blur-[80px] rounded-full animate-float"></div>
|
|
435
|
+
</div>
|
|
436
|
+
|
|
437
|
+
<!-- Navbar -->
|
|
438
|
+
<header className="sticky top-0 z-50 border-b border-white/5 bg-[#020617]/60 backdrop-blur-xl transition-all">
|
|
439
|
+
<div className="container mx-auto px-4">
|
|
440
|
+
<!-- Top Row: Logo & Auth -->
|
|
441
|
+
<div className="flex h-16 items-center justify-between gap-4">
|
|
442
|
+
<div className="flex-1">
|
|
443
|
+
<a href="/" className="flex items-center gap-2.5 hover:opacity-80 transition-opacity">
|
|
444
|
+
<img src="/assets/images/brand-logo-128.webp" className="w-8 h-8 sm:w-9 sm:h-9 rounded-xl shadow-sm" alt="Logo" />
|
|
445
|
+
<span className="text-base sm:text-lg font-black tracking-tight">OmniZap<span className="text-primary">.</span></span>
|
|
446
|
+
</a>
|
|
447
|
+
</div>
|
|
448
|
+
|
|
449
|
+
<!-- Desktop Nav Items (Middle) -->
|
|
450
|
+
<nav className="hidden lg:flex items-center gap-1 mx-4">${NAV_ITEMS.map((item) => html` <a href=${item.href} className="btn btn-ghost btn-sm rounded-lg font-medium text-white/50 hover:text-primary hover:bg-white/5 transition-all uppercase text-[10px] tracking-widest"> ${item.label} </a> `)}</nav>
|
|
451
|
+
|
|
452
|
+
<div className="flex items-center gap-2 sm:gap-4">
|
|
453
|
+
${session?.user
|
|
454
|
+
? html`
|
|
455
|
+
<a href="/user/" className="group relative flex items-center gap-3 pl-1 pr-4 py-1.5 rounded-2xl bg-white/5 border border-white/10 hover:border-primary/40 transition-all duration-300">
|
|
456
|
+
<div className="relative">
|
|
457
|
+
<img src=${authInfo.image} className="w-8 h-8 sm:w-9 sm:h-9 rounded-xl object-cover border border-white/10 group-hover:border-primary/50 transition-colors" />
|
|
458
|
+
<div className="absolute -bottom-1 -right-1 w-3 h-3 bg-success border-2 border-[#020617] rounded-full"></div>
|
|
459
|
+
</div>
|
|
460
|
+
<div className="hidden sm:flex flex-col items-start -gap-1">
|
|
461
|
+
<span className="text-[10px] font-black uppercase tracking-widest text-white/40 group-hover:text-primary transition-colors">${authInfo.label}</span>
|
|
462
|
+
<span className="text-[8px] font-bold text-white/20 uppercase tracking-tighter">Painel de Controle</span>
|
|
463
|
+
</div>
|
|
464
|
+
</a>
|
|
465
|
+
`
|
|
466
|
+
: html` <a href="/login/" className="btn btn-ghost btn-sm h-10 rounded-xl border border-white/10 hover:bg-white/5 px-4 font-bold text-[10px] uppercase tracking-widest text-white/70"> Entrar </a> `}
|
|
467
|
+
|
|
468
|
+
<a href=${botMenuUrl} className="btn btn-primary btn-sm h-10 rounded-xl shadow-lg shadow-primary/20 text-[10px] font-black uppercase tracking-widest px-5"> <span className="hidden xs:inline text-[9px]">Adicionar</span> Bot </a>
|
|
469
|
+
</div>
|
|
470
|
+
</div>
|
|
471
|
+
|
|
472
|
+
<!-- Bottom Row (Mobile Only): Horizontal Scroll Links -->
|
|
473
|
+
<nav className="flex lg:hidden items-center gap-3 overflow-x-auto no-scrollbar pb-4 -mx-4 px-4">${NAV_ITEMS.map((item) => html` <a href=${item.href} className="px-4 py-2 rounded-xl text-[10px] font-black uppercase tracking-widest whitespace-nowrap bg-white/5 border border-white/5 text-white/40 active:bg-primary/20 active:text-primary transition-all"> ${item.label} </a> `)}</nav>
|
|
474
|
+
</div>
|
|
475
|
+
</header>
|
|
476
|
+
|
|
477
|
+
<main className="relative z-10">
|
|
478
|
+
<!-- Hero Section -->
|
|
479
|
+
<section className="relative overflow-hidden py-10 lg:py-32 min-h-[70vh] lg:min-h-[80vh] flex items-center">
|
|
480
|
+
<div className="container mx-auto px-4 relative z-10">
|
|
481
|
+
<div className="grid lg:grid-cols-2 gap-12 items-center">
|
|
482
|
+
<div data-reveal="fade-right" className="text-center lg:text-left space-y-8">
|
|
483
|
+
<div className="inline-flex items-center gap-2 px-3 py-1.5 rounded-full bg-primary/10 border border-primary/20 text-primary text-[10px] sm:text-[11px] font-bold uppercase tracking-widest">
|
|
484
|
+
<span className="relative flex h-2 w-2">
|
|
485
|
+
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-primary opacity-75"></span>
|
|
486
|
+
<span className="relative inline-flex rounded-full h-2 w-2 bg-primary"></span>
|
|
487
|
+
</span>
|
|
488
|
+
Sistema Operacional · ${metrics.status}
|
|
489
|
+
</div>
|
|
490
|
+
|
|
491
|
+
<h1 className="text-[2.75rem] sm:text-6xl lg:text-8xl font-black leading-[1.1] sm:leading-[1.05] tracking-tighter text-balance">
|
|
492
|
+
Automatize seu <br className="hidden sm:block" />
|
|
493
|
+
<span className="text-transparent bg-clip-text bg-gradient-to-r from-primary via-emerald-400 to-secondary animate-gradient-x">WhatsApp</span>.
|
|
494
|
+
</h1>
|
|
495
|
+
|
|
496
|
+
<p className="text-base sm:text-xl text-white/50 max-w-xl mx-auto lg:mx-0 leading-relaxed font-medium">O bot mais poderoso do Brasil para gerenciar grupos, criar figurinhas e automatizar fluxos inteligentes via IA.</p>
|
|
497
|
+
|
|
498
|
+
<div className="flex flex-col sm:flex-row gap-4 justify-center lg:justify-start pt-4">
|
|
499
|
+
<a href=${botMenuUrl} className="btn btn-primary btn-lg rounded-2xl shadow-2xl shadow-primary/30 gap-3 group px-8 h-14 sm:h-16 text-base sm:text-lg font-black">
|
|
500
|
+
Adicionar ao WhatsApp
|
|
501
|
+
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 sm:h-6 sm:w-6 group-hover:translate-x-1 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="3" d="M13 7l5 5m0 0l-5 5m5-5H6" /></svg>
|
|
502
|
+
</a>
|
|
503
|
+
<a href="/comandos/" className="btn btn-outline btn-lg rounded-2xl border-white/10 hover:bg-white/5 hover:border-primary/40 px-8 h-14 sm:h-16 text-base sm:text-lg font-black gap-2 transition-all"> ⚡ Ver Comandos </a>
|
|
504
|
+
</div>
|
|
505
|
+
|
|
506
|
+
<div className="grid grid-cols-2 sm:flex sm:flex-wrap justify-center lg:justify-start gap-y-8 gap-x-12 pt-10 sm:pt-12">
|
|
507
|
+
<div className="relative group text-left sm:text-center">
|
|
508
|
+
<div className="text-3xl sm:text-5xl font-black text-white group-hover:text-primary transition-colors">${metrics.users}</div>
|
|
509
|
+
<div className="text-[9px] sm:text-[10px] uppercase font-black text-white/30 tracking-[0.2em] sm:tracking-[0.3em] mt-1">Usuários Reais</div>
|
|
510
|
+
</div>
|
|
511
|
+
<div className="w-px h-12 bg-white/5 hidden sm:block"></div>
|
|
512
|
+
<div className="relative group text-left sm:text-center">
|
|
513
|
+
<div className="text-3xl sm:text-5xl font-black text-white">${metrics.messages}</div>
|
|
514
|
+
<div className="text-[9px] sm:text-[10px] uppercase font-black text-white/30 tracking-[0.2em] sm:tracking-[0.3em] mt-1">Mensagens</div>
|
|
515
|
+
</div>
|
|
516
|
+
<div className="w-px h-12 bg-white/5 hidden lg:block"></div>
|
|
517
|
+
<div className="relative group col-span-2 sm:col-auto text-center lg:text-left pt-2 sm:pt-0 border-t border-white/5 sm:border-none">
|
|
518
|
+
<div className="text-3xl sm:text-5xl font-black text-white/80 group-hover:text-primary transition-colors">1,7 mil</div>
|
|
519
|
+
<div className="text-[9px] sm:text-[10px] uppercase font-black text-white/30 tracking-[0.2em] sm:tracking-[0.3em] mt-1">comandos usados</div>
|
|
520
|
+
</div>
|
|
521
|
+
</div>
|
|
522
|
+
</div>
|
|
523
|
+
|
|
524
|
+
<div data-reveal="fade-left" className="relative group hidden lg:block">
|
|
525
|
+
<div className="absolute -inset-4 bg-gradient-to-r from-primary/20 to-secondary/20 rounded-[2.5rem] blur-3xl opacity-50 group-hover:opacity-100 transition-opacity"></div>
|
|
526
|
+
<div className="relative bg-white/[0.03] backdrop-blur-2xl rounded-[2rem] border border-white/10 p-6 shadow-2xl animate-float">
|
|
527
|
+
<div className="flex items-center justify-between mb-6">
|
|
528
|
+
<div className="flex gap-1.5">
|
|
529
|
+
<div className="w-3 h-3 rounded-full bg-error/20"></div>
|
|
530
|
+
<div className="w-3 h-3 rounded-full bg-warning/20"></div>
|
|
531
|
+
<div className="w-3 h-3 rounded-full bg-success/20"></div>
|
|
532
|
+
</div>
|
|
533
|
+
<div className="text-[10px] font-mono text-white/20 tracking-tighter uppercase">LATENCY: ${metrics.latency}</div>
|
|
534
|
+
</div>
|
|
535
|
+
|
|
536
|
+
<div key=${simulationIndex} className="space-y-4 font-mono text-sm sm:text-base transition-all duration-500 animate-in fade-in slide-in-from-bottom-2">
|
|
537
|
+
<div className="flex gap-3">
|
|
538
|
+
<span className="text-primary font-bold">visitor:</span>
|
|
539
|
+
<span className="text-white/60">"${simulationMessages[simulationIndex].visitor}"</span>
|
|
540
|
+
</div>
|
|
541
|
+
<div className="flex gap-3 bg-primary/10 p-4 rounded-xl border border-primary/20">
|
|
542
|
+
<span className="text-success font-bold">omnizap:</span>
|
|
543
|
+
<span className="text-primary/90 italic">"${simulationMessages[simulationIndex].bot}"</span>
|
|
544
|
+
</div>
|
|
545
|
+
</div>
|
|
546
|
+
</div>
|
|
547
|
+
</div>
|
|
548
|
+
</div>
|
|
549
|
+
</div>
|
|
550
|
+
|
|
551
|
+
<!-- Scroll Indicator -->
|
|
552
|
+
<div className="absolute bottom-10 left-1/2 -translate-x-1/2 hidden lg:flex flex-col items-center gap-2 cursor-pointer group scroll-indicator-anim">
|
|
553
|
+
<span className="text-[9px] font-black uppercase tracking-[0.4em] text-white/20 group-hover:text-primary transition-colors">Explorar</span>
|
|
554
|
+
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 text-primary/40 group-hover:text-primary" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="3" d="M19 14l-7 7-7-7" /></svg>
|
|
555
|
+
</div>
|
|
556
|
+
</section>
|
|
557
|
+
|
|
558
|
+
<!-- Stats Marquee (Social Proof) -->
|
|
559
|
+
<div className="bg-primary/5 border-y border-white/5 overflow-hidden py-5">
|
|
560
|
+
<div className="animate-marquee-infinite gap-12 items-center text-[11px] font-black uppercase tracking-[0.4em] text-primary/50">
|
|
561
|
+
<span>Usado por +50.000 Grupos</span>
|
|
562
|
+
<span className="text-white/10">•</span>
|
|
563
|
+
<span>+100M Mensagens Processadas</span>
|
|
564
|
+
<span className="text-white/10">•</span>
|
|
565
|
+
<span>IA de Última Geração</span>
|
|
566
|
+
<span className="text-white/10">•</span>
|
|
567
|
+
<span>Segurança Total LGPD</span>
|
|
568
|
+
<span className="text-white/10">•</span>
|
|
569
|
+
<span>Figurinhas Instantâneas</span>
|
|
570
|
+
<span className="text-white/10">•</span>
|
|
571
|
+
<span>Moderação Ativa 24/7</span>
|
|
572
|
+
<span className="text-white/10">•</span>
|
|
573
|
+
{/* Duplicating for seamless loop */}
|
|
574
|
+
<span>Usado por +50.000 Grupos</span>
|
|
575
|
+
<span className="text-white/10">•</span>
|
|
576
|
+
<span>+100M Mensagens Processadas</span>
|
|
577
|
+
<span className="text-white/10">•</span>
|
|
578
|
+
<span>IA de Última Geração</span>
|
|
579
|
+
<span className="text-white/10">•</span>
|
|
580
|
+
<span>Segurança Total LGPD</span>
|
|
581
|
+
<span className="text-white/10">•</span>
|
|
582
|
+
<span>Figurinhas Instantâneas</span>
|
|
583
|
+
<span className="text-white/10">•</span>
|
|
584
|
+
<span>Moderação Ativa 24/7</span>
|
|
585
|
+
<span className="text-white/10">•</span>
|
|
586
|
+
</div>
|
|
587
|
+
</div>
|
|
588
|
+
|
|
589
|
+
<!-- Sticker Gallery (Live Preview) -->
|
|
590
|
+
<div className="py-12 bg-[#020617] relative overflow-hidden">
|
|
591
|
+
<div className="flex gap-4 animate-marquee-infinite opacity-50 hover:opacity-100 transition-opacity">
|
|
592
|
+
${[1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8].map(
|
|
593
|
+
(i) => html`
|
|
594
|
+
<div key=${i} className="w-20 h-20 sm:w-28 sm:h-28 rounded-2xl bg-white/5 border border-white/10 flex items-center justify-center group hover:border-primary/40 transition-all p-2">
|
|
595
|
+
<div className="w-full h-full rounded-xl bg-gradient-to-br from-white/5 to-white/[0.02] flex items-center justify-center text-2xl group-hover:scale-110 transition-transform grayscale hover:grayscale-0">${['🎨', '🎭', '🐱', '🔥', '🚀', '💎', '🎮', '🍕'][i - 1] || '✨'}</div>
|
|
596
|
+
</div>
|
|
597
|
+
`,
|
|
598
|
+
)}
|
|
599
|
+
</div>
|
|
600
|
+
</div>
|
|
601
|
+
|
|
602
|
+
<!-- Steps Section (Mobile First) -->
|
|
603
|
+
<section className="py-20 relative">
|
|
604
|
+
<div className="container mx-auto px-4">
|
|
605
|
+
<div data-reveal="fade-up" className="text-center mb-16 space-y-4">
|
|
606
|
+
<h2 className="text-3xl sm:text-5xl font-black tracking-tight">Comece em Segundos</h2>
|
|
607
|
+
<p className="text-white/40 max-w-xl mx-auto font-medium">O processo é simples, rápido e não requer conhecimento técnico.</p>
|
|
608
|
+
</div>
|
|
609
|
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
|
610
|
+
${STEPS.map(
|
|
611
|
+
(s) => html`
|
|
612
|
+
<div key=${s.step} data-reveal="fade-up" className="relative group p-8 rounded-[2.5rem] bg-white/[0.02] border border-white/5 hover:border-primary/20 transition-all duration-500">
|
|
613
|
+
<div className="absolute top-8 right-8 text-4xl font-black text-primary/10 group-hover:text-primary/20 transition-colors">${s.step}</div>
|
|
614
|
+
<div className="w-12 h-12 rounded-2xl bg-primary/10 flex items-center justify-center text-primary font-black mb-6 border border-primary/20">${s.step}</div>
|
|
615
|
+
<h3 className="text-xl font-bold mb-3">${s.title}</h3>
|
|
616
|
+
<p className="text-white/40 leading-relaxed text-sm font-medium">${s.desc}</p>
|
|
617
|
+
</div>
|
|
618
|
+
`,
|
|
619
|
+
)}
|
|
620
|
+
</div>
|
|
621
|
+
</div>
|
|
622
|
+
</section>
|
|
623
|
+
|
|
624
|
+
<!-- Features Section -->
|
|
625
|
+
<section id="recursos" className="py-24 bg-white/[0.02] relative">
|
|
626
|
+
<div className="container mx-auto px-4 relative z-10">
|
|
627
|
+
<div data-reveal="fade-up" className="text-center max-w-3xl mx-auto mb-20 space-y-6">
|
|
628
|
+
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-primary/10 border border-primary/20 text-primary text-[10px] font-black uppercase tracking-widest">Features V3.5</div>
|
|
629
|
+
<h2 className="text-4xl sm:text-6xl font-black tracking-tighter">
|
|
630
|
+
Tecnologia de <br />
|
|
631
|
+
<span className="text-transparent bg-clip-text bg-gradient-to-r from-primary to-emerald-400">Ponta</span>.
|
|
632
|
+
</h2>
|
|
633
|
+
<p className="text-white/40 text-lg sm:text-xl font-medium">Desenvolvido para máxima performance e facilidade de uso.</p>
|
|
634
|
+
</div>
|
|
635
|
+
|
|
636
|
+
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
637
|
+
${FEATURES.map(
|
|
638
|
+
(f) => html`
|
|
639
|
+
<div data-reveal="fade-up" className="group p-8 rounded-[2.5rem] bg-[#020617] border border-white/5 hover:border-primary/30 transition-all hover:shadow-2xl hover:shadow-primary/5">
|
|
640
|
+
<div className="w-14 h-14 rounded-2xl bg-white/5 flex items-center justify-center text-3xl mb-6 group-hover:scale-110 group-hover:bg-primary/10 transition-all border border-white/5">${f.icon}</div>
|
|
641
|
+
<h3 className="text-xl font-bold mb-3">${f.title}</h3>
|
|
642
|
+
<p className="text-white/40 leading-relaxed text-sm font-medium">${f.desc}</p>
|
|
643
|
+
</div>
|
|
644
|
+
`,
|
|
645
|
+
)}
|
|
646
|
+
</div>
|
|
647
|
+
</div>
|
|
648
|
+
</section>
|
|
649
|
+
|
|
650
|
+
<!-- Commands Section -->
|
|
651
|
+
<section id="comandos" className="py-16 sm:py-24">
|
|
652
|
+
<div className="container mx-auto px-4">
|
|
653
|
+
<div className="flex flex-col lg:flex-row gap-10 lg:gap-16 items-start">
|
|
654
|
+
<div className="w-full lg:w-1/3 lg:sticky lg:top-32 space-y-4 sm:space-y-6 text-center lg:text-left">
|
|
655
|
+
<h2 className="text-3xl sm:text-4xl font-black tracking-tight text-balance">
|
|
656
|
+
Comandos de <br className="hidden lg:block" />
|
|
657
|
+
Resposta Rápida
|
|
658
|
+
</h2>
|
|
659
|
+
<p className="text-white/40 leading-relaxed text-sm sm:text-base max-w-xl mx-auto lg:mx-0 font-medium">Interaja com o bot através de comandos intuitivos. Dezenas de ferramentas poderosas ao seu alcance.</p>
|
|
660
|
+
|
|
661
|
+
<div className="relative group max-w-sm mx-auto lg:mx-0">
|
|
662
|
+
<div className="absolute inset-y-0 left-4 flex items-center pointer-events-none">
|
|
663
|
+
<svg className="w-4 h-4 text-white/20 group-focus-within:text-primary transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" /></svg>
|
|
664
|
+
</div>
|
|
665
|
+
<input type="text" placeholder="Buscar comando..." className="w-full bg-white/[0.03] border border-white/10 rounded-xl py-3 pl-11 pr-4 text-sm font-medium focus:outline-none focus:border-primary/50 focus:bg-white/5 transition-all" value=${searchTerm} onInput=${(e) => setSearchTerm(e.target.value)} />
|
|
666
|
+
</div>
|
|
667
|
+
|
|
668
|
+
<div className="hidden lg:block p-6 rounded-2xl bg-primary/5 border border-primary/10">
|
|
669
|
+
<div className="text-primary font-black text-xl mb-1">1,7 mil+</div>
|
|
670
|
+
<div className="text-[10px] uppercase font-bold tracking-widest opacity-50">comandos usados</div>
|
|
671
|
+
</div>
|
|
672
|
+
<a href="/comandos/" className="btn btn-outline border-white/10 btn-block rounded-xl hidden lg:flex font-black text-[10px] uppercase tracking-widest h-12">Ver Todos os Comandos</a>
|
|
673
|
+
</div>
|
|
674
|
+
|
|
675
|
+
<div className="w-full lg:w-2/3 grid grid-cols-1 md:grid-cols-2 gap-4 sm:gap-6">
|
|
676
|
+
${filteredCommandBlocks.map(
|
|
677
|
+
(block) => html`
|
|
678
|
+
<div data-reveal="fade-up" className="bg-white/[0.02] border border-white/5 rounded-3xl overflow-hidden group hover:border-primary/20 transition-all">
|
|
679
|
+
<div className="p-5 sm:p-8">
|
|
680
|
+
<h3 className="text-xs sm:text-sm font-black uppercase tracking-[0.2em] text-primary/60 mb-5 sm:mb-6 flex items-center gap-2">
|
|
681
|
+
<span className="w-1.5 h-1.5 rounded-full bg-primary shadow-[0_0_8px_rgba(34,197,94,0.5)]"></span>
|
|
682
|
+
${block.title}
|
|
683
|
+
</h3>
|
|
684
|
+
<div className="grid gap-4 sm:gap-5">
|
|
685
|
+
${block.items.map(
|
|
686
|
+
([cmd, label]) => html`
|
|
687
|
+
<div className="flex items-start gap-3 group">
|
|
688
|
+
<div className="flex-1">
|
|
689
|
+
<div className="font-mono text-sm font-bold text-white/90 group-hover:text-primary transition-colors">${cmd}</div>
|
|
690
|
+
<div className="text-[11px] sm:text-xs text-white/30 font-medium leading-tight">${label}</div>
|
|
691
|
+
</div>
|
|
692
|
+
</div>
|
|
693
|
+
`,
|
|
694
|
+
)}
|
|
695
|
+
</div>
|
|
696
|
+
</div>
|
|
697
|
+
</div>
|
|
698
|
+
`,
|
|
699
|
+
)}
|
|
700
|
+
|
|
701
|
+
<!-- Mobile Only CTA -->
|
|
702
|
+
<div className="lg:hidden mt-2">
|
|
703
|
+
<a href="/comandos/" className="btn btn-block btn-outline border-white/10 rounded-2xl h-14 font-black text-[10px] uppercase tracking-widest"> Ver Todos os Comandos </a>
|
|
704
|
+
</div>
|
|
705
|
+
</div>
|
|
706
|
+
</div>
|
|
707
|
+
</div>
|
|
708
|
+
</section>
|
|
709
|
+
|
|
710
|
+
<!-- Resources Section -->
|
|
711
|
+
<section id="guias" className="py-20 bg-white/[0.01]">
|
|
712
|
+
<div className="container mx-auto px-4">
|
|
713
|
+
<div data-reveal="fade-up" className="mb-12">
|
|
714
|
+
<h2 className="text-3xl sm:text-4xl font-black tracking-tight mb-4">Guias e Recursos</h2>
|
|
715
|
+
<p className="text-white/40 max-w-2xl font-medium">Aprenda a extrair o máximo do seu bot com nossos guias práticos de operação e crescimento.</p>
|
|
716
|
+
</div>
|
|
717
|
+
|
|
718
|
+
<div className="grid sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
|
719
|
+
${GUIDES.map(
|
|
720
|
+
(guide) => html`
|
|
721
|
+
<a href=${guide.href} data-reveal="fade-up" className="p-6 rounded-3xl bg-white/[0.02] border border-white/5 hover:border-primary/40 transition-all group">
|
|
722
|
+
<h3 className="font-black mb-2 group-hover:text-primary transition-colors text-white/80">${guide.title}</h3>
|
|
723
|
+
<p className="text-xs text-white/30 leading-relaxed font-medium">${guide.desc}</p>
|
|
724
|
+
</a>
|
|
725
|
+
`,
|
|
726
|
+
)}
|
|
727
|
+
</div>
|
|
728
|
+
</div>
|
|
729
|
+
</section>
|
|
730
|
+
|
|
731
|
+
<!-- Pricing / Comparison Section -->
|
|
732
|
+
<section id="planos" className="py-24 bg-white/[0.01]">
|
|
733
|
+
<div className="container mx-auto px-4">
|
|
734
|
+
<div data-reveal="fade-up" className="text-center mb-16 space-y-4">
|
|
735
|
+
<h2 className="text-3xl sm:text-5xl font-black tracking-tight">Escolha seu Plano</h2>
|
|
736
|
+
<p className="text-white/40 font-medium">Recursos poderosos para todos os tamanhos de grupos.</p>
|
|
737
|
+
</div>
|
|
738
|
+
|
|
739
|
+
<div className="grid md:grid-cols-2 gap-8 max-w-4xl mx-auto">
|
|
740
|
+
<div data-reveal="fade-up" className="p-8 rounded-[2.5rem] bg-white/[0.02] border border-white/5 flex flex-col hover:border-white/10 transition-all">
|
|
741
|
+
<div className="mb-8">
|
|
742
|
+
<h3 className="text-xl font-bold mb-2">Plano Gratuito</h3>
|
|
743
|
+
<div className="text-4xl font-black mb-4">R$ 0<span className="text-sm text-white/20 font-medium italic">/sempre</span></div>
|
|
744
|
+
<p className="text-sm text-white/40">Ideal para grupos pequenos e iniciantes.</p>
|
|
745
|
+
</div>
|
|
746
|
+
<ul className="space-y-4 mb-10 flex-1">
|
|
747
|
+
${['Moderação básica', 'Figurinhas ilimitadas', 'Comandos de utilidades', 'Uso compartilhado de IA'].map(
|
|
748
|
+
(item) => html`
|
|
749
|
+
<li className="flex items-center gap-3 text-sm font-medium text-white/60">
|
|
750
|
+
<svg className="w-5 h-5 text-emerald-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="3" d="M5 13l4 4L19 7" /></svg>
|
|
751
|
+
${item}
|
|
752
|
+
</li>
|
|
753
|
+
`,
|
|
754
|
+
)}
|
|
755
|
+
</ul>
|
|
756
|
+
<a href=${botMenuUrl} className="btn btn-outline border-white/10 rounded-xl font-black">Adicionar Grátis</a>
|
|
757
|
+
</div>
|
|
758
|
+
|
|
759
|
+
<div data-reveal="fade-up" className="p-8 rounded-[2.5rem] bg-primary/5 border border-primary/20 flex flex-col relative overflow-hidden group hover:border-primary/40 transition-all">
|
|
760
|
+
<div className="absolute top-6 right-6 px-3 py-1 rounded-full bg-primary text-[#020617] text-[10px] font-black uppercase tracking-widest">Recomendado</div>
|
|
761
|
+
<div className="mb-8">
|
|
762
|
+
<h3 className="text-xl font-bold mb-2 text-primary">Plano Premium</h3>
|
|
763
|
+
<div className="text-4xl font-black mb-4 text-white">R$ 14,90<span className="text-sm text-white/20 font-medium italic">/mês</span></div>
|
|
764
|
+
<p className="text-sm text-white/40">Potência máxima para administradores profissionais.</p>
|
|
765
|
+
</div>
|
|
766
|
+
<ul className="space-y-4 mb-10 flex-1">
|
|
767
|
+
${['IA sem limites (GPT-4o)', 'Webhooks & API Docs', 'Backup de mensagens', 'Rankings customizados', 'Suporte prioritário'].map(
|
|
768
|
+
(item) => html`
|
|
769
|
+
<li className="flex items-center gap-3 text-sm font-medium text-white/90">
|
|
770
|
+
<svg className="w-5 h-5 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="3" d="M5 13l4 4L19 7" /></svg>
|
|
771
|
+
${item}
|
|
772
|
+
</li>
|
|
773
|
+
`,
|
|
774
|
+
)}
|
|
775
|
+
</ul>
|
|
776
|
+
<a href=${botMenuUrl} className="btn btn-primary rounded-xl font-black shadow-lg shadow-primary/20">Quero ser Premium</a>
|
|
777
|
+
</div>
|
|
778
|
+
</div>
|
|
779
|
+
</div>
|
|
780
|
+
</section>
|
|
781
|
+
|
|
782
|
+
<!-- FAQ Section -->
|
|
783
|
+
<section id="faq" className="py-24">
|
|
784
|
+
<div className="container mx-auto px-4 max-w-4xl">
|
|
785
|
+
<div data-reveal="fade-up" className="text-center mb-16 space-y-4">
|
|
786
|
+
<h2 className="text-3xl sm:text-5xl font-black tracking-tight">Dúvidas Frequentes</h2>
|
|
787
|
+
<p className="text-white/40 font-medium text-lg">Tudo o que você precisa saber para começar agora mesmo.</p>
|
|
788
|
+
</div>
|
|
789
|
+
|
|
790
|
+
<div className="space-y-4">
|
|
791
|
+
${FAQS.map(
|
|
792
|
+
(faq) => html`
|
|
793
|
+
<div data-reveal="fade-up" className="collapse collapse-plus bg-white/[0.02] border border-white/5 rounded-3xl group">
|
|
794
|
+
<input type="checkbox" />
|
|
795
|
+
<div className="collapse-title text-base font-bold text-white/70 p-6 group-hover:text-primary transition-colors">${faq.q}</div>
|
|
796
|
+
<div className="collapse-content px-6 pb-6 border-t border-white/5 pt-4">
|
|
797
|
+
<p className="text-sm text-white/40 leading-relaxed font-medium">${faq.a}</p>
|
|
798
|
+
</div>
|
|
799
|
+
</div>
|
|
800
|
+
`,
|
|
801
|
+
)}
|
|
802
|
+
</div>
|
|
803
|
+
</div>
|
|
804
|
+
</section>
|
|
805
|
+
|
|
806
|
+
<!-- Compliance Strip -->
|
|
807
|
+
<section className="py-12 border-y border-white/5 bg-white/[0.01]">
|
|
808
|
+
<div className="container mx-auto px-4 text-center space-y-6">
|
|
809
|
+
<div className="flex flex-wrap justify-center gap-x-8 gap-y-4 opacity-40 hover:opacity-100 transition-opacity">
|
|
810
|
+
<a href="/politica-de-privacidade/" className="text-[10px] font-bold uppercase tracking-widest hover:text-primary">Privacidade LGPD</a>
|
|
811
|
+
<a href="/termos-de-uso/" className="text-[10px] font-bold uppercase tracking-widest hover:text-primary">Termos de Uso</a>
|
|
812
|
+
<a href="/aup/" className="text-[10px] font-bold uppercase tracking-widest hover:text-primary">Uso Aceitável</a>
|
|
813
|
+
<a href="/dpa/" className="text-[10px] font-bold uppercase tracking-widest hover:text-primary">DPA B2B</a>
|
|
814
|
+
<a href="/suboperadores/" className="text-[10px] font-bold uppercase tracking-widest hover:text-primary">Suboperadores</a>
|
|
815
|
+
</div>
|
|
816
|
+
</div>
|
|
817
|
+
</section>
|
|
818
|
+
|
|
819
|
+
<!-- CTA Final -->
|
|
820
|
+
<section className="py-24 container mx-auto px-4">
|
|
821
|
+
<div data-reveal="fade-up" className="relative p-12 sm:p-20 rounded-[3rem] overflow-hidden text-center text-primary-content shadow-[0_0_80px_rgba(34,197,94,0.1)]">
|
|
822
|
+
<div className="absolute inset-0 bg-gradient-to-br from-primary via-emerald-500 to-secondary animate-gradient-x"></div>
|
|
823
|
+
<div className="absolute inset-0 opacity-20 bg-[url('https://www.transparenttextures.com/patterns/carbon-fibre.png')]"></div>
|
|
824
|
+
|
|
825
|
+
<div className="relative z-10 space-y-8">
|
|
826
|
+
<h2 className="text-3xl sm:text-5xl lg:text-6xl font-black leading-tight text-balance">Pronto para transformar seu grupo?</h2>
|
|
827
|
+
<p className="text-base sm:text-lg opacity-80 max-w-2xl mx-auto font-medium">Junte-se a milhares de administradores que já automatizaram suas comunidades com o OmniZap Bot.</p>
|
|
828
|
+
<div className="pt-4">
|
|
829
|
+
<a href=${botMenuUrl} className="btn btn-lg bg-white border-none text-[#020617] rounded-2xl hover:scale-105 active:scale-95 transition-all shadow-2xl px-8 sm:px-12 h-14 sm:h-16 text-base sm:text-lg font-black uppercase tracking-widest"> Adicionar Agora </a>
|
|
830
|
+
</div>
|
|
831
|
+
</div>
|
|
832
|
+
</div>
|
|
833
|
+
</section>
|
|
834
|
+
|
|
835
|
+
<!-- Developer Section (API) -->
|
|
836
|
+
<section className="py-24 relative overflow-hidden">
|
|
837
|
+
<div className="container mx-auto px-4">
|
|
838
|
+
<div className="grid lg:grid-cols-2 gap-16 items-center">
|
|
839
|
+
<div data-reveal="fade-right" className="space-y-6">
|
|
840
|
+
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-emerald-500/10 border border-emerald-500/20 text-emerald-500 text-[10px] font-black uppercase tracking-widest">Built for Devs</div>
|
|
841
|
+
<h2 className="text-4xl sm:text-5xl font-black tracking-tight">API & Webhooks</h2>
|
|
842
|
+
<p className="text-white/40 text-lg font-medium leading-relaxed">Integre o OmniZap com seus sistemas. Use nossa API REST para enviar mensagens, gerenciar grupos e receber eventos via Webhooks em tempo real.</p>
|
|
843
|
+
<div className="flex gap-4">
|
|
844
|
+
<a href="/api-docs/" className="btn btn-primary rounded-xl px-8">Documentação</a>
|
|
845
|
+
<a href="https://github.com/Omnizap-System/omnizap" target="_blank" className="btn btn-ghost border-white/5 rounded-xl px-8 hover:bg-white/5">GitHub</a>
|
|
846
|
+
</div>
|
|
847
|
+
</div>
|
|
848
|
+
<div data-reveal="fade-left" className="relative">
|
|
849
|
+
<div className="absolute -inset-4 bg-emerald-500/10 blur-3xl opacity-50 rounded-full"></div>
|
|
850
|
+
<div className="relative bg-[#0b0f1a] rounded-2xl border border-white/10 p-1 overflow-hidden shadow-2xl">
|
|
851
|
+
<div className="flex items-center gap-2 px-4 py-2 border-b border-white/5 bg-white/[0.02]">
|
|
852
|
+
<div className="w-2 h-2 rounded-full bg-red-500/50"></div>
|
|
853
|
+
<div className="w-2 h-2 rounded-full bg-yellow-500/50"></div>
|
|
854
|
+
<div className="w-2 h-2 rounded-full bg-green-500/50"></div>
|
|
855
|
+
<span className="text-[10px] font-mono text-white/20 ml-2 uppercase">send-message.js</span>
|
|
856
|
+
</div>
|
|
857
|
+
<pre className="p-6 font-mono text-xs sm:text-sm leading-relaxed overflow-x-auto no-scrollbar">
|
|
858
|
+
<code className="text-white/80">
|
|
859
|
+
<span className="text-emerald-400">fetch</span>('<span className="text-secondary">/api/v1/messages/send</span>', {<br/>
|
|
860
|
+
${' '}method: '<span className="text-secondary">POST</span>',<br/>
|
|
861
|
+
${' '}headers: { '<span className="text-secondary">Authorization</span>': '<span className="text-emerald-400">Bearer API_KEY</span>' },<br/>
|
|
862
|
+
${' '}body: <span className="text-emerald-400">JSON</span>.<span className="text-emerald-400">stringify</span>({<br/>
|
|
863
|
+
${' '}to: '<span className="text-secondary">551199999999@c.us</span>',<br/>
|
|
864
|
+
${' '}text: '<span className="text-secondary">Hello from OmniZap! 🚀</span>'<br/>
|
|
865
|
+
${' '})<br/>
|
|
866
|
+
});
|
|
867
|
+
</code>
|
|
868
|
+
</pre>
|
|
869
|
+
</div>
|
|
870
|
+
</div>
|
|
871
|
+
</div>
|
|
872
|
+
</div>
|
|
873
|
+
</section>
|
|
874
|
+
</main>
|
|
875
|
+
|
|
876
|
+
<!-- Footer -->
|
|
877
|
+
<footer className="bg-[#020617] border-t border-white/5 py-16">
|
|
878
|
+
<div className="container mx-auto px-4">
|
|
879
|
+
<div className="grid grid-cols-2 lg:grid-cols-4 gap-12 mb-12 text-center lg:text-left">
|
|
880
|
+
<div className="col-span-2 lg:col-span-1 space-y-4">
|
|
881
|
+
<div className="flex items-center justify-center lg:justify-start gap-2">
|
|
882
|
+
<img src="/assets/images/brand-logo-128.webp" className="w-8 h-8 rounded-lg" />
|
|
883
|
+
<span className="text-xl font-black tracking-tighter">OmniZap<span className="text-primary">.</span></span>
|
|
884
|
+
</div>
|
|
885
|
+
<p className="text-xs text-white/30 leading-relaxed font-medium">
|
|
886
|
+
Plataforma Open Source de automação WhatsApp. <br />
|
|
887
|
+
Feito para a comunidade brasileira.
|
|
888
|
+
</p>
|
|
889
|
+
</div>
|
|
890
|
+
|
|
891
|
+
<div>
|
|
892
|
+
<h4 className="font-bold text-xs uppercase tracking-widest text-white/20 mb-6">Explorar</h4>
|
|
893
|
+
<ul className="space-y-3 text-sm font-black text-white/50">
|
|
894
|
+
<li><a href="/comandos/" className="hover:text-primary transition-colors">Biblioteca de Comandos</a></li>
|
|
895
|
+
<li><a href="/api-docs/" className="hover:text-primary transition-colors">Documentação API</a></li>
|
|
896
|
+
<li><a href="/login/" className="hover:text-primary transition-colors">Painel de Usuário</a></li>
|
|
897
|
+
</ul>
|
|
898
|
+
</div>
|
|
899
|
+
|
|
900
|
+
<div>
|
|
901
|
+
<h4 className="font-bold text-xs uppercase tracking-widest text-white/20 mb-6">Legal</h4>
|
|
902
|
+
<ul className="space-y-3 text-sm font-medium text-white/40">
|
|
903
|
+
<li><a href="/termos-de-uso/" className="hover:text-primary transition-colors">Termos</a></li>
|
|
904
|
+
<li><a href="/politica-de-privacidade/" className="hover:text-primary transition-colors">Privacidade</a></li>
|
|
905
|
+
<li><a href="/licenca/" className="hover:text-primary transition-colors">Licença</a></li>
|
|
906
|
+
</ul>
|
|
907
|
+
</div>
|
|
908
|
+
|
|
909
|
+
<div>
|
|
910
|
+
<h4 className="font-bold text-xs uppercase tracking-widest text-white/20 mb-6">Social</h4>
|
|
911
|
+
<ul className="space-y-3 text-sm font-medium text-white/40">
|
|
912
|
+
<li><a href="https://github.com/Omnizap-System/omnizap" target="_blank" className="hover:text-primary transition-colors">GitHub</a></li>
|
|
913
|
+
<li><a href=${botMenuUrl} className="hover:text-primary transition-colors">WhatsApp</a></li>
|
|
914
|
+
</ul>
|
|
915
|
+
</div>
|
|
916
|
+
</div>
|
|
917
|
+
|
|
918
|
+
<div className="border-t border-white/5 pt-8 flex flex-col sm:flex-row justify-between items-center gap-4 text-[10px] font-bold uppercase tracking-[0.2em] text-white/20">
|
|
919
|
+
<span>© 2026 OMNIZAP SYSTEM</span>
|
|
920
|
+
<div className="flex items-center gap-4">
|
|
921
|
+
<span>STATUS: <span className="text-success">${metrics.status}</span></span>
|
|
922
|
+
<span className="text-white/10">•</span>
|
|
923
|
+
<span>VERSION: 2.5.8</span>
|
|
924
|
+
</div>
|
|
925
|
+
</div>
|
|
926
|
+
</div>
|
|
927
|
+
</footer>
|
|
928
|
+
|
|
929
|
+
<!-- Floating Action (WhatsApp Button Overlay) -->
|
|
930
|
+
<a href=${botMenuUrl} target="_blank" className="flex btn btn-primary btn-circle fixed bottom-6 right-6 sm:bottom-8 sm:right-8 z-50 w-14 h-14 sm:w-16 sm:h-16 shadow-[0_0_40px_rgba(34,197,94,0.3)] hover:scale-110 active:scale-95 transition-all border-none group">
|
|
931
|
+
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6 sm:h-7 sm:w-7 transition-transform group-hover:rotate-12" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
932
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
|
|
933
|
+
</svg>
|
|
934
|
+
</a>
|
|
935
|
+
</div>
|
|
936
|
+
`;
|
|
937
|
+
};
|
|
938
|
+
|
|
939
|
+
const rootElement = document.getElementById('home-react-root');
|
|
940
|
+
if (rootElement) {
|
|
941
|
+
createRoot(rootElement).render(html`<${App} />`);
|
|
942
|
+
}
|