@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.
Files changed (166) hide show
  1. package/.env.example +534 -0
  2. package/LICENSE +21 -0
  3. package/README.md +431 -0
  4. package/RELEASE-v2.1.2.md +83 -0
  5. package/app/config/adminIdentity.js +87 -0
  6. package/app/config/baileysConfig.js +693 -0
  7. package/app/config/groupUtils.js +388 -0
  8. package/app/connection/socketController.js +992 -0
  9. package/app/controllers/messageController.js +354 -0
  10. package/app/modules/adminModule/groupCommandHandlers.js +1294 -0
  11. package/app/modules/adminModule/groupEventHandlers.js +355 -0
  12. package/app/modules/aiModule/catCommand.js +1006 -0
  13. package/app/modules/broadcastModule/noticeCommand.js +416 -0
  14. package/app/modules/gameModule/diceCommand.js +67 -0
  15. package/app/modules/menuModule/common.js +311 -0
  16. package/app/modules/menuModule/menus.js +59 -0
  17. package/app/modules/playModule/playCommand.js +1615 -0
  18. package/app/modules/quoteModule/quoteCommand.js +851 -0
  19. package/app/modules/rpgPokemonModule/rpgBattleCanvasRenderer.js +786 -0
  20. package/app/modules/rpgPokemonModule/rpgBattleService.js +2082 -0
  21. package/app/modules/rpgPokemonModule/rpgBattleService.test.js +760 -0
  22. package/app/modules/rpgPokemonModule/rpgEvolutionUtils.js +22 -0
  23. package/app/modules/rpgPokemonModule/rpgPokemonCommand.js +172 -0
  24. package/app/modules/rpgPokemonModule/rpgPokemonDomain.js +192 -0
  25. package/app/modules/rpgPokemonModule/rpgPokemonDomain.test.js +93 -0
  26. package/app/modules/rpgPokemonModule/rpgPokemonEvolution.test.js +46 -0
  27. package/app/modules/rpgPokemonModule/rpgPokemonMessages.js +746 -0
  28. package/app/modules/rpgPokemonModule/rpgPokemonRepository.js +1859 -0
  29. package/app/modules/rpgPokemonModule/rpgPokemonService.js +6738 -0
  30. package/app/modules/rpgPokemonModule/rpgProfileCanvasRenderer.js +354 -0
  31. package/app/modules/statsModule/globalRankingCommand.js +65 -0
  32. package/app/modules/statsModule/noMessageCommand.js +288 -0
  33. package/app/modules/statsModule/rankingCommand.js +60 -0
  34. package/app/modules/statsModule/rankingCommon.js +889 -0
  35. package/app/modules/stickerModule/addStickerMetadata.js +239 -0
  36. package/app/modules/stickerModule/convertToWebp.js +390 -0
  37. package/app/modules/stickerModule/stickerCommand.js +454 -0
  38. package/app/modules/stickerModule/stickerConvertCommand.js +156 -0
  39. package/app/modules/stickerModule/stickerTextCommand.js +657 -0
  40. package/app/modules/stickerPackModule/autoPackCollectorRuntime.js +20 -0
  41. package/app/modules/stickerPackModule/autoPackCollectorService.js +284 -0
  42. package/app/modules/stickerPackModule/semanticReclassificationEngine.js +466 -0
  43. package/app/modules/stickerPackModule/semanticReclassificationEngine.test.js +88 -0
  44. package/app/modules/stickerPackModule/semanticThemeClusterService.js +571 -0
  45. package/app/modules/stickerPackModule/stickerAssetClassificationRepository.js +449 -0
  46. package/app/modules/stickerPackModule/stickerAssetRepository.js +400 -0
  47. package/app/modules/stickerPackModule/stickerAssetReprocessQueueRepository.js +180 -0
  48. package/app/modules/stickerPackModule/stickerAutoPackByTagsRuntime.js +4078 -0
  49. package/app/modules/stickerPackModule/stickerClassificationBackgroundRuntime.js +598 -0
  50. package/app/modules/stickerPackModule/stickerClassificationService.js +588 -0
  51. package/app/modules/stickerPackModule/stickerMarketplaceDriftService.js +102 -0
  52. package/app/modules/stickerPackModule/stickerPackCatalogHttp.js +7506 -0
  53. package/app/modules/stickerPackModule/stickerPackCommandHandlers.js +1095 -0
  54. package/app/modules/stickerPackModule/stickerPackEngagementRepository.js +108 -0
  55. package/app/modules/stickerPackModule/stickerPackErrors.js +30 -0
  56. package/app/modules/stickerPackModule/stickerPackInteractionEventRepository.js +110 -0
  57. package/app/modules/stickerPackModule/stickerPackItemRepository.js +440 -0
  58. package/app/modules/stickerPackModule/stickerPackMarketplaceService.js +337 -0
  59. package/app/modules/stickerPackModule/stickerPackMessageService.js +296 -0
  60. package/app/modules/stickerPackModule/stickerPackRepository.js +442 -0
  61. package/app/modules/stickerPackModule/stickerPackService.js +788 -0
  62. package/app/modules/stickerPackModule/stickerPackServiceRuntime.js +51 -0
  63. package/app/modules/stickerPackModule/stickerPackUtils.js +97 -0
  64. package/app/modules/stickerPackModule/stickerStorageService.js +507 -0
  65. package/app/modules/stickerPackModule/stickerWorkerPipelineRuntime.js +233 -0
  66. package/app/modules/stickerPackModule/stickerWorkerTaskQueueRepository.js +205 -0
  67. package/app/modules/systemMetricsModule/pingCommand.js +421 -0
  68. package/app/modules/tiktokModule/tiktokCommand.js +798 -0
  69. package/app/modules/userModule/userCommand.js +1217 -0
  70. package/app/modules/waifuPicsModule/waifuPicsCommand.js +177 -0
  71. package/app/observability/metrics.js +734 -0
  72. package/app/services/captchaService.js +492 -0
  73. package/app/services/dbWriteQueue.js +572 -0
  74. package/app/services/groupMetadataService.js +279 -0
  75. package/app/services/lidMapService.js +663 -0
  76. package/app/services/messagePersistenceService.js +56 -0
  77. package/app/services/newsBroadcastService.js +351 -0
  78. package/app/services/pokeApiService.js +398 -0
  79. package/app/services/queueUtils.js +57 -0
  80. package/app/services/socketState.js +7 -0
  81. package/app/store/aiPromptStore.js +38 -0
  82. package/app/store/groupConfigStore.js +58 -0
  83. package/app/store/premiumUserStore.js +36 -0
  84. package/app/utils/antiLink/antiLinkModule.js +804 -0
  85. package/app/utils/http/getImageBufferModule.js +18 -0
  86. package/app/utils/json/jsonSanitizer.js +113 -0
  87. package/app/utils/json/jsonSanitizer.test.js +40 -0
  88. package/app/utils/logger/loggerModule.js +262 -0
  89. package/app/utils/systemMetrics/systemMetricsModule.js +91 -0
  90. package/database/index.js +2052 -0
  91. package/database/init.js +516 -0
  92. package/database/migrations/20260203_0001_sticker_packs.sql +54 -0
  93. package/database/migrations/20260210_0003_rpg_pokemon.sql +58 -0
  94. package/database/migrations/20260210_0004_rpg_shiny_biome.sql +9 -0
  95. package/database/migrations/20260210_0005_rpg_missions.sql +14 -0
  96. package/database/migrations/20260210_0006_rpg_world_pokedex_traits.sql +27 -0
  97. package/database/migrations/20260210_0007_rpg_raid_pvp.sql +56 -0
  98. package/database/migrations/20260210_0008_rpg_social_system.sql +195 -0
  99. package/database/migrations/20260211_0009_rpg_social_xp.sql +36 -0
  100. package/database/migrations/20260222_0010_remove_message_xp.sql +2 -0
  101. package/database/migrations/20260226_0011_sticker_asset_classification.sql +17 -0
  102. package/database/migrations/20260226_0012_sticker_pack_engagement.sql +16 -0
  103. package/database/migrations/20260226_0013_sticker_marketplace_intelligence.sql +19 -0
  104. package/database/migrations/20260226_0014_sticker_pack_publish_flow.sql +30 -0
  105. package/database/migrations/20260226_0014_sticker_worker_queues.sql +42 -0
  106. package/database/migrations/20260226_0015_sticker_auto_pack_curation_integrity.sql +18 -0
  107. package/database/migrations/20260226_0016_sticker_web_google_auth_persistence.sql +34 -0
  108. package/database/migrations/20260226_0017_sticker_web_admin_ban.sql +22 -0
  109. package/database/migrations/20260226_0018_sticker_web_admin_moderator.sql +18 -0
  110. package/database/migrations/20260227_0019_sticker_classification_v2_signals.sql +12 -0
  111. package/database/migrations/20260227_0020_semantic_theme_clusters.sql +35 -0
  112. package/docker-compose.yml +103 -0
  113. package/ecosystem.prod.config.cjs +35 -0
  114. package/eslint.config.js +61 -0
  115. package/index.js +437 -0
  116. package/ml/clip_classifier/Dockerfile +16 -0
  117. package/ml/clip_classifier/README.md +120 -0
  118. package/ml/clip_classifier/adaptive_scoring.py +40 -0
  119. package/ml/clip_classifier/classifier.py +654 -0
  120. package/ml/clip_classifier/embedding_store.py +481 -0
  121. package/ml/clip_classifier/env_loader.py +15 -0
  122. package/ml/clip_classifier/llm_label_expander.py +144 -0
  123. package/ml/clip_classifier/main.py +213 -0
  124. package/ml/clip_classifier/requirements.txt +10 -0
  125. package/ml/clip_classifier/similarity_engine.py +74 -0
  126. package/observability/alert-rules.yml +60 -0
  127. package/observability/grafana/dashboards/omnizap-mysql.json +136 -0
  128. package/observability/grafana/dashboards/omnizap-overview.json +170 -0
  129. package/observability/grafana/provisioning/dashboards/dashboards.yml +11 -0
  130. package/observability/grafana/provisioning/datasources/datasources.yml +15 -0
  131. package/observability/loki-config.yml +38 -0
  132. package/observability/mysql-exporter.cnf +5 -0
  133. package/observability/mysql-setup.sql +46 -0
  134. package/observability/prometheus.yml +32 -0
  135. package/observability/promtail-config.yml +84 -0
  136. package/package.json +109 -0
  137. package/public/api-docs/index.html +144 -0
  138. package/public/css/github-project-panel.css +297 -0
  139. package/public/css/stickers-admin.css +1272 -0
  140. package/public/css/styles.css +671 -0
  141. package/public/index.html +1311 -0
  142. package/public/js/apps/apiDocsApp.js +310 -0
  143. package/public/js/apps/createPackApp.js +2069 -0
  144. package/public/js/apps/homeApp.js +396 -0
  145. package/public/js/apps/stickersAdminApp.js +1744 -0
  146. package/public/js/apps/stickersApp.js +4830 -0
  147. package/public/js/catalog.js +1019 -0
  148. package/public/js/github-panel/components/CommitList.js +34 -0
  149. package/public/js/github-panel/components/ErrorState.js +16 -0
  150. package/public/js/github-panel/components/GithubProjectPanel.js +106 -0
  151. package/public/js/github-panel/components/ReleaseList.js +38 -0
  152. package/public/js/github-panel/components/SkeletonPanel.js +22 -0
  153. package/public/js/github-panel/components/StatCard.js +15 -0
  154. package/public/js/github-panel/index.js +15 -0
  155. package/public/js/github-panel/useGithubRepoData.js +154 -0
  156. package/public/js/github-panel/vendor/react.js +11 -0
  157. package/public/js/runtime/react-runtime.js +19 -0
  158. package/public/licenca/index.html +106 -0
  159. package/public/stickers/admin/index.html +23 -0
  160. package/public/stickers/create/index.html +47 -0
  161. package/public/stickers/index.html +48 -0
  162. package/public/termos-de-uso/index.html +125 -0
  163. package/scripts/cache-bust.mjs +107 -0
  164. package/scripts/deploy.sh +458 -0
  165. package/scripts/github-deploy-notify.mjs +174 -0
  166. 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
+ ![Node.js](https://img.shields.io/badge/Node.js-18%2B-3C873A?logo=node.js&logoColor=white)
4
+ ![JavaScript](https://img.shields.io/badge/JavaScript-ES2022-F7DF1E?logo=javascript&logoColor=000)
5
+ ![MySQL](https://img.shields.io/badge/MySQL-8%2B-4479A1?logo=mysql&logoColor=white)
6
+ ![Baileys](https://img.shields.io/badge/Baileys-WhatsApp%20SDK-25D366?logo=whatsapp&logoColor=white)
7
+ ![PM2](https://img.shields.io/badge/PM2-Process%20Manager-2B037A?logo=pm2&logoColor=white)
8
+ ![OpenAI](https://img.shields.io/badge/OpenAI-SDK-111111?logo=openai&logoColor=white)
9
+ ![License](https://img.shields.io/badge/License-MIT-0B6E4F?logo=opensourceinitiative&logoColor=white)
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
+ };