@kaikybrofc/omnizap-system 2.1.8
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/.env.example +534 -0
- package/LICENSE +21 -0
- package/README.md +431 -0
- package/RELEASE-v2.1.2.md +83 -0
- package/app/config/adminIdentity.js +87 -0
- package/app/config/baileysConfig.js +693 -0
- package/app/config/groupUtils.js +388 -0
- package/app/connection/socketController.js +992 -0
- package/app/controllers/messageController.js +354 -0
- package/app/modules/adminModule/groupCommandHandlers.js +1294 -0
- package/app/modules/adminModule/groupEventHandlers.js +355 -0
- package/app/modules/aiModule/catCommand.js +1006 -0
- package/app/modules/broadcastModule/noticeCommand.js +416 -0
- package/app/modules/gameModule/diceCommand.js +67 -0
- package/app/modules/menuModule/common.js +311 -0
- package/app/modules/menuModule/menus.js +59 -0
- package/app/modules/playModule/playCommand.js +1615 -0
- package/app/modules/quoteModule/quoteCommand.js +851 -0
- package/app/modules/rpgPokemonModule/rpgBattleCanvasRenderer.js +786 -0
- package/app/modules/rpgPokemonModule/rpgBattleService.js +2082 -0
- package/app/modules/rpgPokemonModule/rpgBattleService.test.js +760 -0
- package/app/modules/rpgPokemonModule/rpgEvolutionUtils.js +22 -0
- package/app/modules/rpgPokemonModule/rpgPokemonCommand.js +172 -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 +1859 -0
- package/app/modules/rpgPokemonModule/rpgPokemonService.js +6738 -0
- package/app/modules/rpgPokemonModule/rpgProfileCanvasRenderer.js +354 -0
- package/app/modules/statsModule/globalRankingCommand.js +65 -0
- package/app/modules/statsModule/noMessageCommand.js +288 -0
- package/app/modules/statsModule/rankingCommand.js +60 -0
- package/app/modules/statsModule/rankingCommon.js +889 -0
- package/app/modules/stickerModule/addStickerMetadata.js +239 -0
- package/app/modules/stickerModule/convertToWebp.js +390 -0
- package/app/modules/stickerModule/stickerCommand.js +454 -0
- package/app/modules/stickerModule/stickerConvertCommand.js +156 -0
- package/app/modules/stickerModule/stickerTextCommand.js +657 -0
- package/app/modules/stickerPackModule/autoPackCollectorRuntime.js +20 -0
- package/app/modules/stickerPackModule/autoPackCollectorService.js +284 -0
- package/app/modules/stickerPackModule/semanticReclassificationEngine.js +466 -0
- package/app/modules/stickerPackModule/semanticReclassificationEngine.test.js +88 -0
- package/app/modules/stickerPackModule/semanticThemeClusterService.js +571 -0
- package/app/modules/stickerPackModule/stickerAssetClassificationRepository.js +449 -0
- package/app/modules/stickerPackModule/stickerAssetRepository.js +400 -0
- package/app/modules/stickerPackModule/stickerAssetReprocessQueueRepository.js +180 -0
- package/app/modules/stickerPackModule/stickerAutoPackByTagsRuntime.js +4078 -0
- package/app/modules/stickerPackModule/stickerClassificationBackgroundRuntime.js +598 -0
- package/app/modules/stickerPackModule/stickerClassificationService.js +588 -0
- package/app/modules/stickerPackModule/stickerMarketplaceDriftService.js +102 -0
- package/app/modules/stickerPackModule/stickerPackCatalogHttp.js +7506 -0
- package/app/modules/stickerPackModule/stickerPackCommandHandlers.js +1095 -0
- package/app/modules/stickerPackModule/stickerPackEngagementRepository.js +108 -0
- package/app/modules/stickerPackModule/stickerPackErrors.js +30 -0
- package/app/modules/stickerPackModule/stickerPackInteractionEventRepository.js +110 -0
- package/app/modules/stickerPackModule/stickerPackItemRepository.js +440 -0
- package/app/modules/stickerPackModule/stickerPackMarketplaceService.js +337 -0
- package/app/modules/stickerPackModule/stickerPackMessageService.js +296 -0
- package/app/modules/stickerPackModule/stickerPackRepository.js +442 -0
- package/app/modules/stickerPackModule/stickerPackService.js +788 -0
- package/app/modules/stickerPackModule/stickerPackServiceRuntime.js +51 -0
- package/app/modules/stickerPackModule/stickerPackUtils.js +97 -0
- package/app/modules/stickerPackModule/stickerStorageService.js +507 -0
- package/app/modules/stickerPackModule/stickerWorkerPipelineRuntime.js +233 -0
- package/app/modules/stickerPackModule/stickerWorkerTaskQueueRepository.js +205 -0
- package/app/modules/systemMetricsModule/pingCommand.js +421 -0
- package/app/modules/tiktokModule/tiktokCommand.js +798 -0
- package/app/modules/userModule/userCommand.js +1217 -0
- package/app/modules/waifuPicsModule/waifuPicsCommand.js +177 -0
- package/app/observability/metrics.js +734 -0
- package/app/services/captchaService.js +492 -0
- package/app/services/dbWriteQueue.js +572 -0
- package/app/services/groupMetadataService.js +279 -0
- package/app/services/lidMapService.js +663 -0
- package/app/services/messagePersistenceService.js +56 -0
- package/app/services/newsBroadcastService.js +351 -0
- package/app/services/pokeApiService.js +398 -0
- package/app/services/queueUtils.js +57 -0
- package/app/services/socketState.js +7 -0
- package/app/store/aiPromptStore.js +38 -0
- package/app/store/groupConfigStore.js +58 -0
- package/app/store/premiumUserStore.js +36 -0
- package/app/utils/antiLink/antiLinkModule.js +804 -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/logger/loggerModule.js +262 -0
- package/app/utils/systemMetrics/systemMetricsModule.js +91 -0
- package/database/index.js +2052 -0
- package/database/init.js +516 -0
- package/database/migrations/20260203_0001_sticker_packs.sql +54 -0
- package/database/migrations/20260210_0003_rpg_pokemon.sql +58 -0
- package/database/migrations/20260210_0004_rpg_shiny_biome.sql +9 -0
- package/database/migrations/20260210_0005_rpg_missions.sql +14 -0
- package/database/migrations/20260210_0006_rpg_world_pokedex_traits.sql +27 -0
- package/database/migrations/20260210_0007_rpg_raid_pvp.sql +56 -0
- package/database/migrations/20260210_0008_rpg_social_system.sql +195 -0
- package/database/migrations/20260211_0009_rpg_social_xp.sql +36 -0
- package/database/migrations/20260222_0010_remove_message_xp.sql +2 -0
- package/database/migrations/20260226_0011_sticker_asset_classification.sql +17 -0
- package/database/migrations/20260226_0012_sticker_pack_engagement.sql +16 -0
- package/database/migrations/20260226_0013_sticker_marketplace_intelligence.sql +19 -0
- package/database/migrations/20260226_0014_sticker_pack_publish_flow.sql +30 -0
- package/database/migrations/20260226_0014_sticker_worker_queues.sql +42 -0
- package/database/migrations/20260226_0015_sticker_auto_pack_curation_integrity.sql +18 -0
- package/database/migrations/20260226_0016_sticker_web_google_auth_persistence.sql +34 -0
- package/database/migrations/20260226_0017_sticker_web_admin_ban.sql +22 -0
- package/database/migrations/20260226_0018_sticker_web_admin_moderator.sql +18 -0
- package/database/migrations/20260227_0019_sticker_classification_v2_signals.sql +12 -0
- package/database/migrations/20260227_0020_semantic_theme_clusters.sql +35 -0
- package/docker-compose.yml +103 -0
- package/ecosystem.prod.config.cjs +35 -0
- package/eslint.config.js +61 -0
- package/index.js +437 -0
- package/ml/clip_classifier/Dockerfile +16 -0
- package/ml/clip_classifier/README.md +120 -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/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-exporter.cnf +5 -0
- package/observability/mysql-setup.sql +46 -0
- package/observability/prometheus.yml +32 -0
- package/observability/promtail-config.yml +84 -0
- package/package.json +109 -0
- package/public/api-docs/index.html +144 -0
- package/public/css/github-project-panel.css +297 -0
- package/public/css/stickers-admin.css +1272 -0
- package/public/css/styles.css +671 -0
- package/public/index.html +1311 -0
- package/public/js/apps/apiDocsApp.js +310 -0
- package/public/js/apps/createPackApp.js +2069 -0
- package/public/js/apps/homeApp.js +396 -0
- package/public/js/apps/stickersAdminApp.js +1744 -0
- package/public/js/apps/stickersApp.js +4830 -0
- package/public/js/catalog.js +1019 -0
- package/public/js/github-panel/components/CommitList.js +34 -0
- package/public/js/github-panel/components/ErrorState.js +16 -0
- package/public/js/github-panel/components/GithubProjectPanel.js +106 -0
- package/public/js/github-panel/components/ReleaseList.js +38 -0
- package/public/js/github-panel/components/SkeletonPanel.js +22 -0
- package/public/js/github-panel/components/StatCard.js +15 -0
- package/public/js/github-panel/index.js +15 -0
- package/public/js/github-panel/useGithubRepoData.js +154 -0
- package/public/js/github-panel/vendor/react.js +11 -0
- package/public/js/runtime/react-runtime.js +19 -0
- package/public/licenca/index.html +106 -0
- package/public/stickers/admin/index.html +23 -0
- package/public/stickers/create/index.html +47 -0
- package/public/stickers/index.html +48 -0
- package/public/termos-de-uso/index.html +125 -0
- package/scripts/cache-bust.mjs +107 -0
- package/scripts/deploy.sh +458 -0
- package/scripts/github-deploy-notify.mjs +174 -0
- package/scripts/release.sh +129 -0
package/README.md
ADDED
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
<img width="1318" height="352" alt="OmniZap banner" src="https://github.com/user-attachments/assets/d44835e7-021a-4c67-a0e7-5b858d51eb91" />
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
O **OmniZap System** é uma plataforma de automação para WhatsApp usando **Node.js + Baileys**, com foco em:
|
|
12
|
+
|
|
13
|
+
- comando por chat (grupos e privado)
|
|
14
|
+
- persistência em MySQL
|
|
15
|
+
- automações administrativas
|
|
16
|
+
- mídia/figurinhas com packs persistentes
|
|
17
|
+
- observabilidade (Prometheus/Grafana/Loki)
|
|
18
|
+
|
|
19
|
+
**Versão atual:** `2.1.3`
|
|
20
|
+
|
|
21
|
+
## Links oficiais do projeto
|
|
22
|
+
|
|
23
|
+
- Site principal: https://omnizap.shop/
|
|
24
|
+
- Catálogo web de stickers: https://omnizap.shop/stickers/
|
|
25
|
+
- API Docs: https://omnizap.shop/api-docs/
|
|
26
|
+
- Termos de uso: https://omnizap.shop/termos-de-uso/
|
|
27
|
+
- Licença: https://omnizap.shop/licenca/
|
|
28
|
+
|
|
29
|
+
## Recursos principais
|
|
30
|
+
|
|
31
|
+
- Gerenciamento de grupos (admin, boas-vindas, despedida, anti-link, captcha).
|
|
32
|
+
- Prefixo de comando por grupo.
|
|
33
|
+
- Comandos de mídia (`play`, `playvid`, stickers e conversões).
|
|
34
|
+
- Sticker packs persistentes com CRUD e envio com fallback.
|
|
35
|
+
- Recursos de IA (`cat`, `catimg`, `catprompt`) com OpenAI.
|
|
36
|
+
- Estatísticas (`ranking`, `rankingglobal`, `semmsg`, `user perfil`).
|
|
37
|
+
- Suporte a LID/JID com reconciliação automática (`lid_map`).
|
|
38
|
+
- Métricas e logs estruturados para operação em produção.
|
|
39
|
+
|
|
40
|
+
## Pré-requisitos
|
|
41
|
+
|
|
42
|
+
- Node.js 18+ recomendado.
|
|
43
|
+
- MySQL 8+.
|
|
44
|
+
- FFmpeg instalado e acessível no `PATH`.
|
|
45
|
+
- PM2 (opcional): `npm i -g pm2`.
|
|
46
|
+
- Docker Compose (opcional, para stack de observabilidade).
|
|
47
|
+
|
|
48
|
+
## Instalação rápida
|
|
49
|
+
|
|
50
|
+
1. Clone o repositório:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
git clone https://github.com/Kaikygr/omnizap-system.git
|
|
54
|
+
cd omnizap-system
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
2. Instale dependências:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npm install
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
3. Crie o `.env` a partir do exemplo:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
cp .env.example .env
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
4. Ajuste as variáveis mínimas obrigatórias no `.env` (o restante já vem com defaults no `.env.example`):
|
|
70
|
+
|
|
71
|
+
```env
|
|
72
|
+
DB_HOST=localhost
|
|
73
|
+
DB_USER=seu_usuario
|
|
74
|
+
DB_PASSWORD=sua_senha
|
|
75
|
+
DB_NAME=omnizap
|
|
76
|
+
USER_ADMIN=seu_jid@s.whatsapp.net
|
|
77
|
+
IMAGE_MENU=https://example.com/menu.png
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Para recursos de IA (`cat`, `catimg`, `catprompt`), configure também:
|
|
81
|
+
|
|
82
|
+
```env
|
|
83
|
+
OPENAI_API_KEY=sua_chave
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
5. Inicialize banco e tabelas:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
npm run db:init
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
6. Inicie o bot:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
npm run start
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
7. Escaneie o QR Code no terminal.
|
|
99
|
+
|
|
100
|
+
## Observações importantes de ambiente
|
|
101
|
+
|
|
102
|
+
- `DB_NAME` recebe sufixo automaticamente:
|
|
103
|
+
- `NODE_ENV=development` => `_dev`
|
|
104
|
+
- `NODE_ENV=production` => `_prod`
|
|
105
|
+
- Se já terminar com `_dev` ou `_prod`, o nome é preservado.
|
|
106
|
+
- `COMMAND_PREFIX` pode ser global e também por grupo (via comandos admin).
|
|
107
|
+
- `LID_BACKFILL_ON_START=true` habilita backfill de `lid_map` no boot.
|
|
108
|
+
- `LID_BACKFILL_BATCH` padrão do serviço: `50000`.
|
|
109
|
+
|
|
110
|
+
## Referência de variáveis (`.env.example`)
|
|
111
|
+
|
|
112
|
+
O `.env.example` foi atualizado para cobrir todas as variáveis atualmente referenciadas no código e no `docker-compose.yml`.
|
|
113
|
+
|
|
114
|
+
Principais blocos do arquivo:
|
|
115
|
+
|
|
116
|
+
- Core do bot (prefixo, admin, imagem de menu, logs e Baileys).
|
|
117
|
+
- Banco MySQL (conexão, fila de escrita, monitor de query lenta).
|
|
118
|
+
- Métricas/observabilidade do app (`METRICS_*`, `DB_QUERY_ALERT_THRESHOLDS`, social metrics).
|
|
119
|
+
- OpenAI (chat, imagem, TTS, timeout e retry).
|
|
120
|
+
- Mídia (`play`, TikTok, FFmpeg/FFprobe).
|
|
121
|
+
- Sticker packs (storage, limites, auto-coleta, catálogo web).
|
|
122
|
+
- XP e RPG Pokémon (economia, PvP, raids, social XP, canvas).
|
|
123
|
+
- Stack de observabilidade no Docker (Prometheus, Grafana, Loki, Promtail e exporters).
|
|
124
|
+
|
|
125
|
+
Variáveis legadas foram mantidas por compatibilidade (`QUOTE_API_URL`, `WAIFU_API_*`, `STORE_PATH`), mas não participam do fluxo principal atual.
|
|
126
|
+
|
|
127
|
+
## Scripts npm
|
|
128
|
+
|
|
129
|
+
- `npm run start`: inicia o app (`node index.js`).
|
|
130
|
+
- `npm run dev`: alias de start.
|
|
131
|
+
- `npm run db:init`: cria/valida schema e executa migrations.
|
|
132
|
+
- `npm run pm2:prod`: sobe com PM2 usando `ecosystem.prod.config.cjs`.
|
|
133
|
+
- `npm run deploy`: deploy automático de `public/` com cache-bust, backup, validação e reload do Nginx.
|
|
134
|
+
- `npm run deploy:dry-run`: simula o deploy sem publicar/recarregar serviços.
|
|
135
|
+
- `npm run release`: bump de versão `patch` + deploy + publish do package (com auto commit/push git).
|
|
136
|
+
- `npm run release:minor`: bump `minor` + deploy + publish do package.
|
|
137
|
+
- `npm run release:major`: bump `major` + deploy + publish do package.
|
|
138
|
+
- `npm run test`: executa testes Node (`node --test`).
|
|
139
|
+
- `npm run lint`: lint com ESLint.
|
|
140
|
+
- `npm run lint:fix`: lint com correções automáticas.
|
|
141
|
+
|
|
142
|
+
## Deploy automático (Nginx + cache-bust)
|
|
143
|
+
|
|
144
|
+
Comando padrão:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
npm run deploy
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Variáveis úteis:
|
|
151
|
+
|
|
152
|
+
- `DEPLOY_TARGET_DIR` (default: `/var/www/omnizap`)
|
|
153
|
+
- `DEPLOY_NGINX_SERVICE` (default: `nginx`)
|
|
154
|
+
- `DEPLOY_PM2_APP_NAME` (default: `omnizap-system-production`)
|
|
155
|
+
- `DEPLOY_RESTART_PM2` (default: `1`)
|
|
156
|
+
- `DEPLOY_CREATE_BACKUP` (default: `1`)
|
|
157
|
+
- `DEPLOY_VERIFY_URL` (default: `https://omnizap.shop/`)
|
|
158
|
+
- `DEPLOY_GITHUB_NOTIFY` (default: `1`) - cria/atualiza deployment no GitHub
|
|
159
|
+
- `DEPLOY_GITHUB_ENVIRONMENT` (default: `production`)
|
|
160
|
+
- `DEPLOY_GITHUB_REPO` (opcional, ex.: `kaikybrofc/omnizap-system`)
|
|
161
|
+
- `DEPLOY_GITHUB_TOKEN` (opcional; se vazio usa `GITHUB_TOKEN`/`GH_TOKEN`)
|
|
162
|
+
- `DEPLOY_PACKAGE_STEP` (default: `0`) - executa etapa de package durante o deploy
|
|
163
|
+
- `DEPLOY_PACKAGE_INSTALL` (default: `1`) - instala dependências (`npm ci --omit=dev`)
|
|
164
|
+
- `DEPLOY_PACKAGE_TEST` (default: `0`) - executa `npm test`
|
|
165
|
+
- `DEPLOY_PACKAGE_PACK` (default: `0`) - gera artefato `npm pack`
|
|
166
|
+
- `DEPLOY_PACKAGE_ARTIFACTS_DIR` (default: `.artifacts`) - pasta dos artefatos do pack
|
|
167
|
+
- `DEPLOY_PACKAGE_PUBLISH` (default: `0`) - publica em registry npm
|
|
168
|
+
- `DEPLOY_PACKAGE_REGISTRY` (default: `https://npm.pkg.github.com`)
|
|
169
|
+
- `DEPLOY_PACKAGE_TOKEN` (opcional; fallback automático por tipo de registry)
|
|
170
|
+
- `DEPLOY_PACKAGE_OTP` (opcional) - OTP para publish quando 2FA interativo for exigido
|
|
171
|
+
- `DEPLOY_PACKAGE_SCOPE_OWNER` (opcional) - owner esperado do scope para publish (ex.: `kaikybrofc` ou sua org)
|
|
172
|
+
- `DEPLOY_PACKAGE_TAG` (default: `latest`)
|
|
173
|
+
- `DEPLOY_PACKAGE_PUBLISH_SKIP_IF_EXISTS` (default: `1`) - evita erro se versão já existir
|
|
174
|
+
- `DEPLOY_PACKAGE_PUBLISH_SECONDARY` (default: `0`) - habilita publish secundário (dual publish)
|
|
175
|
+
- `DEPLOY_PACKAGE_SECONDARY_REGISTRY` (default: `https://registry.npmjs.org`)
|
|
176
|
+
- `DEPLOY_PACKAGE_SECONDARY_TOKEN` (opcional; fallback: `NPM_TOKEN`/`NODE_AUTH_TOKEN`/demais tokens)
|
|
177
|
+
- `DEPLOY_PACKAGE_SECONDARY_OTP` (opcional) - OTP do npmjs para publish com 2FA
|
|
178
|
+
- `DEPLOY_PACKAGE_SECONDARY_TAG` (default: `latest`)
|
|
179
|
+
- `DEPLOY_PACKAGE_SECONDARY_ACCESS` (default: `public`) - usado para pacote escopado no npmjs
|
|
180
|
+
- `DEPLOY_PACKAGE_SECONDARY_PUBLISH_SKIP_IF_EXISTS` (default: mesmo valor de `DEPLOY_PACKAGE_PUBLISH_SKIP_IF_EXISTS`)
|
|
181
|
+
- `DEPLOY_PACKAGE_SECONDARY_TOKEN_KEYS` (opcional) - ordem customizada de fallback de tokens
|
|
182
|
+
|
|
183
|
+
Para `npm.pkg.github.com`, prefira token do GitHub (`DEPLOY_GITHUB_TOKEN` ou `GITHUB_TOKEN`); `NPM_TOKEN` comum pode não autenticar no registry do GitHub.
|
|
184
|
+
Para `npm.pkg.github.com`, o nome do pacote deve ser escopado com owner existente (`@owner/pacote`), por exemplo `@kaikybrofc/omnizap-system`.
|
|
185
|
+
Para `registry.npmjs.org`, use token do npmjs (não token do GitHub). Se sua conta exigir 2FA para publish, use token granular com bypass 2FA habilitado ou informe OTP via `DEPLOY_PACKAGE_SECONDARY_OTP`.
|
|
186
|
+
|
|
187
|
+
Exemplo sem restart do PM2:
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
DEPLOY_RESTART_PM2=0 npm run deploy
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Exemplo com marcação explícita no GitHub:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
DEPLOY_GITHUB_NOTIFY=1 DEPLOY_GITHUB_ENVIRONMENT=production npm run deploy
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Exemplo com etapa package completa:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
DEPLOY_PACKAGE_STEP=1 DEPLOY_PACKAGE_TEST=1 DEPLOY_PACKAGE_PACK=1 npm run deploy
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Exemplo publicando no GitHub Packages:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
DEPLOY_PACKAGE_STEP=1 DEPLOY_PACKAGE_PUBLISH=1 DEPLOY_PACKAGE_TOKEN=seu_token npm run deploy
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Exemplo de dual publish (GitHub Packages + npmjs):
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
DEPLOY_PACKAGE_STEP=1 \
|
|
215
|
+
DEPLOY_PACKAGE_PUBLISH=1 \
|
|
216
|
+
DEPLOY_PACKAGE_PUBLISH_SECONDARY=1 \
|
|
217
|
+
DEPLOY_PACKAGE_SECONDARY_TOKEN=seu_token_npmjs \
|
|
218
|
+
npm run deploy
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Comando único de release (patch + deploy + publish):
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
npm run release
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
`npm run release` agora executa publish primário + secundário por padrão (você pode desativar com `DEPLOY_PACKAGE_PUBLISH_SECONDARY=0`).
|
|
228
|
+
|
|
229
|
+
Variáveis do fluxo de release (git):
|
|
230
|
+
|
|
231
|
+
- `RELEASE_GIT_AUTO_COMMIT` (default: `1`) - commit automático se houver alterações pendentes
|
|
232
|
+
- `RELEASE_GIT_AUTO_PUSH` (default: `1`) - push automático dos commits gerados
|
|
233
|
+
- `RELEASE_GIT_REMOTE` (default: `origin`)
|
|
234
|
+
- `RELEASE_GIT_BRANCH` (opcional; vazio usa branch atual)
|
|
235
|
+
- `RELEASE_GIT_PRE_COMMIT_MESSAGE` (default: `chore(release): auto-commit before release`)
|
|
236
|
+
- `RELEASE_GIT_COMMIT_VERSION` (default: `1`) - commita alteração da versão após sucesso
|
|
237
|
+
- `RELEASE_GIT_VERSION_COMMIT_PREFIX` (default: `chore(release): v`)
|
|
238
|
+
|
|
239
|
+
## Execução com PM2
|
|
240
|
+
|
|
241
|
+
Após conectar o QR uma primeira vez em modo normal:
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
npm run pm2:prod
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Comandos úteis:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
pm2 status
|
|
251
|
+
pm2 logs
|
|
252
|
+
pm2 restart omnizap-system-production
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
> O QR Code não é exibido no fluxo do PM2. Conecte primeiro no modo normal.
|
|
256
|
+
|
|
257
|
+
## Comandos principais
|
|
258
|
+
|
|
259
|
+
Use `menu` para ver os comandos por categoria. Exemplos:
|
|
260
|
+
|
|
261
|
+
- `<prefix>menu`
|
|
262
|
+
- `<prefix>menu figurinhas`
|
|
263
|
+
- `<prefix>menu midia`
|
|
264
|
+
- `<prefix>menu ia`
|
|
265
|
+
- `<prefix>menu stats`
|
|
266
|
+
- `<prefix>menuadm`
|
|
267
|
+
|
|
268
|
+
Comandos mais usados:
|
|
269
|
+
|
|
270
|
+
- `<prefix>sticker` / `<prefix>s`
|
|
271
|
+
- `<prefix>stickertext` / `<prefix>st` / `<prefix>stw` / `<prefix>stb`
|
|
272
|
+
- `<prefix>toimg` / `<prefix>tovideo`
|
|
273
|
+
- `<prefix>play <busca|url>`
|
|
274
|
+
- `<prefix>playvid <busca|url>`
|
|
275
|
+
- `<prefix>tiktok <url>`
|
|
276
|
+
- `<prefix>quote`
|
|
277
|
+
- `<prefix>cat`, `<prefix>catimg`, `<prefix>catprompt`
|
|
278
|
+
- `<prefix>ranking`, `<prefix>rankingglobal`, `<prefix>semmsg`
|
|
279
|
+
- `<prefix>user perfil`
|
|
280
|
+
|
|
281
|
+
## Sticker packs persistentes
|
|
282
|
+
|
|
283
|
+
Exemplos de fluxo:
|
|
284
|
+
|
|
285
|
+
```text
|
|
286
|
+
<prefix>pack create "Meu Pack"
|
|
287
|
+
<prefix>pack add <pack>
|
|
288
|
+
<prefix>pack list
|
|
289
|
+
<prefix>pack info <pack>
|
|
290
|
+
<prefix>pack send <pack>
|
|
291
|
+
<prefix>pack publish <pack> <private|public|unlisted>
|
|
292
|
+
<prefix>pack delete <pack>
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Notas:
|
|
296
|
+
|
|
297
|
+
- Edição de pack é restrita ao dono (`owner_jid`).
|
|
298
|
+
- O envio tenta sticker pack nativo e faz fallback automático quando necessário.
|
|
299
|
+
- O sistema captura “última figurinha” para simplificar `add` e `setcover`.
|
|
300
|
+
|
|
301
|
+
### Catálogo web de packs
|
|
302
|
+
|
|
303
|
+
O servidor HTTP de observabilidade também expõe um catálogo web simples para os packs publicados:
|
|
304
|
+
|
|
305
|
+
- Página web: `http://localhost:9102/stickers`
|
|
306
|
+
- API: `http://localhost:9102/api/sticker-packs`
|
|
307
|
+
- Endpoint de métricas permanece em: `http://localhost:9102/metrics`
|
|
308
|
+
|
|
309
|
+
Em produção (instância oficial):
|
|
310
|
+
|
|
311
|
+
- Página web: `https://omnizap.shop/stickers/`
|
|
312
|
+
- API: `https://omnizap.shop/api/sticker-packs`
|
|
313
|
+
- API Docs: `https://omnizap.shop/api-docs/`
|
|
314
|
+
|
|
315
|
+
Principais rotas da API:
|
|
316
|
+
|
|
317
|
+
- `GET /api/sticker-packs?q=&visibility=public|unlisted|all&limit=&offset=`
|
|
318
|
+
- `GET /api/sticker-packs/orphan-stickers?q=&limit=&offset=` (figurinhas salvas sem pack)
|
|
319
|
+
- `GET /api/sticker-packs/:packKey`
|
|
320
|
+
- `GET /api/sticker-packs/:packKey/stickers/:stickerId.webp`
|
|
321
|
+
- `GET /api/sticker-packs/data-files?q=&limit=&offset=` (lista imagens da pasta `data`)
|
|
322
|
+
- `GET /data/<caminho-da-imagem>` (acesso direto ao arquivo de imagem)
|
|
323
|
+
|
|
324
|
+
## Suporte a LID/JID
|
|
325
|
+
|
|
326
|
+
O WhatsApp pode alternar IDs entre `@lid` e `@s.whatsapp.net`.
|
|
327
|
+
O OmniZap resolve isso com um `sender_id` canônico para manter métricas/rankings consistentes.
|
|
328
|
+
|
|
329
|
+
- Tabela dedicada: `lid_map`.
|
|
330
|
+
- Cache em memória com TTL.
|
|
331
|
+
- Reconciliação automática quando o JID real aparece.
|
|
332
|
+
- Backfill opcional no startup.
|
|
333
|
+
|
|
334
|
+
## Classificação de imagens (CLIP / MobileCLIP)
|
|
335
|
+
|
|
336
|
+
Para categorizar packs e stickers solos (ex.: anime/game/real/cartoon/nsfw), foi adicionado um microserviço Python:
|
|
337
|
+
|
|
338
|
+
- Caminho: `ml/clip_classifier`
|
|
339
|
+
- Stack: `FastAPI + MobileCLIP (OpenCLIP) + PyTorch`
|
|
340
|
+
- Endpoint: `POST /classify` (upload de imagem)
|
|
341
|
+
|
|
342
|
+
Documentação e execução:
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
cd ml/clip_classifier
|
|
346
|
+
cat README.md
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Observabilidade (Prometheus + Grafana + Loki)
|
|
350
|
+
|
|
351
|
+
O projeto inclui `docker-compose.yml` com:
|
|
352
|
+
|
|
353
|
+
- Prometheus
|
|
354
|
+
- Grafana
|
|
355
|
+
- Loki
|
|
356
|
+
- Promtail
|
|
357
|
+
- MySQL Exporter
|
|
358
|
+
- Node Exporter
|
|
359
|
+
|
|
360
|
+
Subir stack:
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
docker compose up -d
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Setup recomendado de métricas MySQL:
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
sudo mysql < observability/mysql-setup.sql
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Acessos padrão:
|
|
373
|
+
|
|
374
|
+
- Grafana: `http://localhost:3003`
|
|
375
|
+
- Prometheus: `http://localhost:9090`
|
|
376
|
+
- Loki: `http://localhost:3100`
|
|
377
|
+
- Métricas do app: `http://localhost:9102/metrics`
|
|
378
|
+
|
|
379
|
+
Arquivos úteis:
|
|
380
|
+
|
|
381
|
+
- `observability/prometheus.yml`
|
|
382
|
+
- `observability/alert-rules.yml`
|
|
383
|
+
- `observability/grafana/dashboards/omnizap-overview.json`
|
|
384
|
+
- `observability/grafana/dashboards/omnizap-mysql.json`
|
|
385
|
+
|
|
386
|
+
## Troubleshooting
|
|
387
|
+
|
|
388
|
+
**QR não aparece no PM2**
|
|
389
|
+
|
|
390
|
+
- Inicie com `npm run start`, conecte o QR e depois volte para PM2.
|
|
391
|
+
- Se necessário, limpe sessão salva e reconecte.
|
|
392
|
+
|
|
393
|
+
**Erro de conexão MySQL**
|
|
394
|
+
|
|
395
|
+
- Verifique `DB_HOST`, `DB_USER`, `DB_PASSWORD`, `DB_NAME`.
|
|
396
|
+
- Confirme se o usuário possui permissão de leitura/escrita.
|
|
397
|
+
|
|
398
|
+
**FFmpeg não encontrado**
|
|
399
|
+
|
|
400
|
+
- Instale FFmpeg no sistema ou configure `FFMPEG_PATH`/`FFPROBE_PATH`.
|
|
401
|
+
|
|
402
|
+
**Comando `play` falhando**
|
|
403
|
+
|
|
404
|
+
- Verifique se o serviço configurado em `YTDLS_BASE_URL`/`YT_DLS_BASE_URL` está ativo.
|
|
405
|
+
|
|
406
|
+
**Comando `tiktok` falhando**
|
|
407
|
+
|
|
408
|
+
- Verifique se sua API local está ativa em `TIKTOK_EXTRACT_BASE_URL` + `TIKTOK_EXTRACT_PATH` (ex.: `http://127.0.0.1:8000/extract`).
|
|
409
|
+
|
|
410
|
+
## Tecnologias
|
|
411
|
+
|
|
412
|
+
- Node.js
|
|
413
|
+
- MySQL (`mysql2`)
|
|
414
|
+
- Baileys (`@whiskeysockets/baileys`)
|
|
415
|
+
- OpenAI SDK
|
|
416
|
+
- Axios
|
|
417
|
+
- Canvas
|
|
418
|
+
- PM2
|
|
419
|
+
- Prometheus / Grafana / Loki
|
|
420
|
+
|
|
421
|
+
## Contribuições
|
|
422
|
+
|
|
423
|
+
1. Faça um fork.
|
|
424
|
+
2. Crie uma branch: `git checkout -b feature/minha-feature`.
|
|
425
|
+
3. Commit: `git commit -m "feat: minha feature"`.
|
|
426
|
+
4. Push: `git push origin feature/minha-feature`.
|
|
427
|
+
5. Abra um Pull Request.
|
|
428
|
+
|
|
429
|
+
## Licença
|
|
430
|
+
|
|
431
|
+
Licença MIT. Veja [`LICENSE`](LICENSE).
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# v2.1.3
|
|
2
|
+
|
|
3
|
+
Atualiza a versão para `2.1.3` e consolida o ciclo de entregas desde a `v2.1.2`.
|
|
4
|
+
|
|
5
|
+
Período do ciclo: `2026-02-26` a `2026-02-27`
|
|
6
|
+
Comparação base: `v2.1.2..HEAD`
|
|
7
|
+
Escopo: **39 commits** e **71 arquivos alterados**
|
|
8
|
+
|
|
9
|
+
## Destaques
|
|
10
|
+
|
|
11
|
+
- Plataforma web de stickers expandida de ponta a ponta: criação de packs no browser, upload de mídia (imagem/vídeo), fluxo de publicação e dashboard de criador.
|
|
12
|
+
- Marketplace e descoberta evoluídos: categorias, sorting, ranking de criadores, métricas globais, cards/UX mobile e melhorias de navegação.
|
|
13
|
+
- SEO e indexação: `sitemap`, ajustes de páginas SEO por pack e controles de exposição NSFW no catálogo.
|
|
14
|
+
- Classificação inteligente e curadoria automática reforçadas: pipeline CLIP/MobileCLIP/OpenCLIP, fila de reprocessamento, clustering semântico e otimizações do auto-pack por tags.
|
|
15
|
+
- Admin panel consolidado com moderação: gestão de bans e role de moderador, com persistência de sessão Google Web.
|
|
16
|
+
- Backend mais robusto: limpeza segura de órfãos, proteção de mutações, idempotência em uploads/publicação e novos caches para stats/sumários.
|
|
17
|
+
- Runtime e resiliência: reconexão de socket aprimorada, tratamento de rejeições transitórias e ajustes de agendamento em background.
|
|
18
|
+
- Banco e deploy: novas migrations para classificação/engajamento/workers/admin, e ajuste no nome do banco com sufixo por ambiente.
|
|
19
|
+
|
|
20
|
+
## Banco de dados e migrations
|
|
21
|
+
|
|
22
|
+
Este ciclo adiciona migrations estruturais importantes:
|
|
23
|
+
|
|
24
|
+
- `20260226_0011_sticker_asset_classification.sql`
|
|
25
|
+
- `20260226_0012_sticker_pack_engagement.sql`
|
|
26
|
+
- `20260226_0013_sticker_marketplace_intelligence.sql`
|
|
27
|
+
- `20260226_0014_sticker_pack_publish_flow.sql`
|
|
28
|
+
- `20260226_0014_sticker_worker_queues.sql`
|
|
29
|
+
- `20260226_0015_sticker_auto_pack_curation_integrity.sql`
|
|
30
|
+
- `20260226_0016_sticker_web_google_auth_persistence.sql`
|
|
31
|
+
- `20260226_0017_sticker_web_admin_ban.sql`
|
|
32
|
+
- `20260226_0018_sticker_web_admin_moderator.sql`
|
|
33
|
+
- `20260227_0019_sticker_classification_v2_signals.sql`
|
|
34
|
+
- `20260227_0020_semantic_theme_clusters.sql`
|
|
35
|
+
|
|
36
|
+
## Commits incluídos (v2.1.2..HEAD)
|
|
37
|
+
|
|
38
|
+
- `b46a33f` Improve background scheduling, add cached stats and UI/status enhancements
|
|
39
|
+
- `c43decb` Enable semantic clustering and improve auto-pack scheduler
|
|
40
|
+
- `91f2950` Enhance socket reconnection and prioritize complete sticker packs
|
|
41
|
+
- `64f8e73` Improve classification and auto-pack optimization
|
|
42
|
+
- `d11d78b` Appends environment-based suffix to DB name
|
|
43
|
+
- `b8ede5f` Add advanced auto-pack optimization and CLIP classification pipeline
|
|
44
|
+
- `32e169f` Add SEO, sitemap and NSFW gating to sticker catalog
|
|
45
|
+
- `7271a9b` Adds web links for sticker packs and sets auto-packs to unlisted
|
|
46
|
+
- `7cd1151` Ignore transient rejections and force process exit
|
|
47
|
+
- `5072a0e` Add admin moderator role and revamp admin panel UI
|
|
48
|
+
- `84c08dd` Add admin panel and ban management
|
|
49
|
+
- `27b387b` Persist Google web sessions and add client-side Google auth cache
|
|
50
|
+
- `6c07feb` Improve mobile category-chip touch and scroll behavior
|
|
51
|
+
- `c3ca0ea` Improve auto-pack-by-tags curation and pack metadata
|
|
52
|
+
- `3f6c258` Fix mobile discover tabs behavior
|
|
53
|
+
- `831c279` Adds marketplace global stats API and panel
|
|
54
|
+
- `08fdafe` Add catalog sorting, creators ranking and pack UI improvements
|
|
55
|
+
- `082ba82` Add safe pack management, orphan asset cleanup, and UX/network robustness
|
|
56
|
+
- `d928227` Improve marketplace discovery UX
|
|
57
|
+
- `97fe5f4` Bumps stickers app asset version
|
|
58
|
+
- `d2d1843` Adds sticker upload API and improves creator dashboard UX
|
|
59
|
+
- `be5506b` Adds creator pack management endpoints and dashboard UI
|
|
60
|
+
- `589f671` Add creator profile with Google sign-in
|
|
61
|
+
- `122c1e8` Switches CLIP classifier to MobileCLIP/OpenCLIP
|
|
62
|
+
- `7385d30` Allow spaces in pack names and add tag typeahead
|
|
63
|
+
- `2c5589c` Stops trimming input on field change
|
|
64
|
+
- `067b6f9` Add web pack publish flow with Google auth and idempotent uploads
|
|
65
|
+
- `6953768` Allow image/video uploads with WebP conversion
|
|
66
|
+
- `b33c1b8` Add web pack creation and sticker upload UI/API
|
|
67
|
+
- `2b23441` Add reprocess queue, cohesion scoring and ranking
|
|
68
|
+
- `6342d2b` Add marketplace stats endpoint and homepage preview
|
|
69
|
+
- `55cf8b7` Batch-scans and deduplicates catalog listings
|
|
70
|
+
- `7819fe6` Adds automatic sticker pack curation by tags
|
|
71
|
+
- `8ed61bc` Improve API docs and dynamic sidebar/UI for stickers
|
|
72
|
+
- `d0fd86d` Adds support contact API and enhances sticker catalog UI
|
|
73
|
+
- `c5cb106` Improves pack cards and mobile header UX
|
|
74
|
+
- `3da0375` Adds categories filtering and pack engagement tracking
|
|
75
|
+
- `d9bb604` Adds CLIP-based sticker classification
|
|
76
|
+
- `fffc205` Enhances catalog and API docs UI
|
|
77
|
+
|
|
78
|
+
## Notas de atualização
|
|
79
|
+
|
|
80
|
+
- `package.json` atualizado para `2.1.3`.
|
|
81
|
+
- `README.md` atualizado para refletir a versão atual.
|
|
82
|
+
- Recomendado reiniciar o processo de produção após deploy (`pm2 restart ... --update-env`).
|
|
83
|
+
- Atenção para comportamento de nome de banco por ambiente (`DB_NAME` com sufixo `_dev`/`_prod` quando aplicável).
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { encodeJid, getJidUser, isSameJidUser, normalizeJid } from './baileysConfig.js';
|
|
2
|
+
import { extractUserIdInfo, resolveUserId, resolveUserIdCached } from '../services/lidMapService.js';
|
|
3
|
+
|
|
4
|
+
const ADMIN_ENV_KEY = 'USER_ADMIN';
|
|
5
|
+
|
|
6
|
+
const normalizePhoneDigits = (value) => String(value || '').replace(/\D+/g, '');
|
|
7
|
+
|
|
8
|
+
export const getAdminRawValue = () => String(process.env[ADMIN_ENV_KEY] || '').trim();
|
|
9
|
+
|
|
10
|
+
export const getAdminJid = () => {
|
|
11
|
+
const raw = getAdminRawValue();
|
|
12
|
+
if (!raw) return null;
|
|
13
|
+
|
|
14
|
+
let candidate = '';
|
|
15
|
+
if (raw.includes('@')) {
|
|
16
|
+
candidate = normalizeJid(raw) || raw;
|
|
17
|
+
} else {
|
|
18
|
+
const digits = normalizePhoneDigits(raw);
|
|
19
|
+
if (!digits) return null;
|
|
20
|
+
candidate = normalizeJid(encodeJid(digits, 's.whatsapp.net')) || '';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (!candidate) return null;
|
|
24
|
+
|
|
25
|
+
const resolvedCached = resolveUserIdCached(extractUserIdInfo(candidate));
|
|
26
|
+
const normalizedResolved = normalizeJid(resolvedCached || candidate);
|
|
27
|
+
return normalizedResolved || candidate;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const getAdminPhone = () => {
|
|
31
|
+
const adminJid = getAdminJid();
|
|
32
|
+
if (!adminJid) return null;
|
|
33
|
+
|
|
34
|
+
const user = getJidUser(adminJid);
|
|
35
|
+
if (user) return user;
|
|
36
|
+
|
|
37
|
+
const digits = normalizePhoneDigits(adminJid);
|
|
38
|
+
return digits || null;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const resolveAdminJid = async () => {
|
|
42
|
+
const cached = getAdminJid();
|
|
43
|
+
if (!cached) return null;
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
const resolved = await resolveUserId(extractUserIdInfo(cached));
|
|
47
|
+
return normalizeJid(resolved || cached) || cached;
|
|
48
|
+
} catch {
|
|
49
|
+
return cached;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const isAdminSender = (senderJid) => {
|
|
54
|
+
const adminJid = getAdminJid();
|
|
55
|
+
if (!adminJid || !senderJid) return false;
|
|
56
|
+
|
|
57
|
+
const normalizedSender = normalizeJid(senderJid);
|
|
58
|
+
if (!normalizedSender) return false;
|
|
59
|
+
|
|
60
|
+
return isSameJidUser(normalizedSender, adminJid) || normalizedSender === adminJid;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const isAdminSenderAsync = async (senderIdentity) => {
|
|
64
|
+
const senderInfo = extractUserIdInfo(senderIdentity);
|
|
65
|
+
if (!senderInfo.raw && !senderInfo.jid && !senderInfo.lid && !senderInfo.participantAlt) return false;
|
|
66
|
+
|
|
67
|
+
const normalizedSender = normalizeJid(senderInfo.jid || senderInfo.raw || '');
|
|
68
|
+
const cachedSender = resolveUserIdCached(senderInfo);
|
|
69
|
+
const normalizedCachedSender = normalizeJid(cachedSender || '');
|
|
70
|
+
const resolvedSender = await resolveUserId(senderInfo).catch(() => null);
|
|
71
|
+
const normalizedResolvedSender = normalizeJid(resolvedSender || '');
|
|
72
|
+
const senderCandidates = new Set(
|
|
73
|
+
[normalizedSender, normalizedCachedSender, normalizedResolvedSender].filter(Boolean),
|
|
74
|
+
);
|
|
75
|
+
if (!senderCandidates.size) return false;
|
|
76
|
+
|
|
77
|
+
const adminJid = (await resolveAdminJid()) || getAdminJid();
|
|
78
|
+
if (!adminJid) return false;
|
|
79
|
+
const normalizedAdmin = normalizeJid(adminJid) || adminJid;
|
|
80
|
+
|
|
81
|
+
for (const senderCandidate of senderCandidates) {
|
|
82
|
+
if (isSameJidUser(senderCandidate, normalizedAdmin) || senderCandidate === normalizedAdmin) {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
};
|