@kaikybrofc/omnizap-system 2.2.10 → 2.3.1

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 (123) hide show
  1. package/README.md +13 -13
  2. package/app/config/adminIdentity.js +1 -3
  3. package/app/connection/socketController.js +10 -20
  4. package/app/controllers/messageController.js +7 -28
  5. package/app/modules/aiModule/catCommand.js +29 -192
  6. package/app/modules/broadcastModule/noticeCommand.js +28 -97
  7. package/app/modules/gameModule/diceCommand.js +6 -32
  8. package/app/modules/playModule/playCommand.js +57 -258
  9. package/app/modules/quoteModule/quoteCommand.js +2 -4
  10. package/app/modules/rpgPokemonModule/rpgPokemonRepository.js +1 -13
  11. package/app/modules/statsModule/noMessageCommand.js +16 -84
  12. package/app/modules/statsModule/rankingCommand.js +5 -25
  13. package/app/modules/statsModule/rankingCommon.js +1 -9
  14. package/app/modules/stickerModule/convertToWebp.js +4 -27
  15. package/app/modules/stickerModule/stickerCommand.js +13 -24
  16. package/app/modules/stickerModule/stickerTextCommand.js +13 -25
  17. package/app/modules/stickerPackModule/autoPackCollectorService.js +16 -7
  18. package/app/modules/stickerPackModule/domainEventOutboxRepository.js +20 -36
  19. package/app/modules/stickerPackModule/domainEvents.js +2 -11
  20. package/app/modules/stickerPackModule/semanticReclassificationEngine.js +13 -50
  21. package/app/modules/stickerPackModule/semanticReclassificationEngine.test.js +2 -15
  22. package/app/modules/stickerPackModule/semanticThemeClusterService.js +14 -41
  23. package/app/modules/stickerPackModule/stickerAssetClassificationRepository.js +25 -95
  24. package/app/modules/stickerPackModule/stickerAssetRepository.js +12 -31
  25. package/app/modules/stickerPackModule/stickerAssetReprocessQueueRepository.js +13 -18
  26. package/app/modules/stickerPackModule/stickerAutoPackByTagsRuntime.js +284 -709
  27. package/app/modules/stickerPackModule/stickerClassificationBackgroundRuntime.js +27 -106
  28. package/app/modules/stickerPackModule/stickerClassificationService.js +46 -77
  29. package/app/modules/stickerPackModule/stickerDedicatedTaskWorkerRuntime.js +13 -53
  30. package/app/modules/stickerPackModule/stickerDomainEventBus.js +10 -16
  31. package/app/modules/stickerPackModule/stickerDomainEventConsumerRuntime.js +40 -39
  32. package/app/modules/stickerPackModule/stickerMarketplaceDriftService.js +1 -4
  33. package/app/modules/stickerPackModule/stickerObjectStorageService.js +26 -26
  34. package/app/modules/stickerPackModule/stickerPackCommandHandlers.js +32 -187
  35. package/app/modules/stickerPackModule/stickerPackInteractionEventRepository.js +6 -15
  36. package/app/modules/stickerPackModule/stickerPackItemRepository.js +6 -32
  37. package/app/modules/stickerPackModule/stickerPackMarketplaceService.js +12 -36
  38. package/app/modules/stickerPackModule/stickerPackMessageService.js +12 -40
  39. package/app/modules/stickerPackModule/stickerPackRepository.js +23 -66
  40. package/app/modules/stickerPackModule/stickerPackScoreSnapshotRepository.js +9 -21
  41. package/app/modules/stickerPackModule/stickerPackScoreSnapshotRuntime.js +10 -40
  42. package/app/modules/stickerPackModule/stickerPackService.js +50 -115
  43. package/app/modules/stickerPackModule/stickerPackServiceRuntime.js +2 -21
  44. package/app/modules/stickerPackModule/stickerPackUtils.js +13 -3
  45. package/app/modules/stickerPackModule/stickerStorageService.js +16 -65
  46. package/app/modules/stickerPackModule/stickerWorkerPipelineRuntime.js +4 -22
  47. package/app/modules/stickerPackModule/stickerWorkerTaskQueueRepository.js +14 -29
  48. package/app/modules/systemMetricsModule/pingCommand.js +9 -39
  49. package/app/modules/tiktokModule/tiktokCommand.js +17 -109
  50. package/app/modules/userModule/userCommand.js +2 -88
  51. package/app/observability/metrics.js +5 -16
  52. package/app/services/captchaService.js +1 -6
  53. package/app/services/dbWriteQueue.js +3 -18
  54. package/app/services/featureFlagService.js +2 -8
  55. package/app/services/newsBroadcastService.js +0 -1
  56. package/app/services/queueUtils.js +2 -4
  57. package/app/services/whatsappLoginLinkService.js +7 -9
  58. package/app/store/premiumUserStore.js +1 -2
  59. package/app/utils/antiLink/antiLinkModule.js +3 -233
  60. package/app/utils/logger/loggerModule.js +9 -34
  61. package/app/utils/systemMetrics/systemMetricsModule.js +1 -4
  62. package/database/index.js +1 -0
  63. package/database/init.js +1 -8
  64. package/database/migrations/20260228_0027_web_visit_event.sql +15 -0
  65. package/docker-compose.yml +27 -27
  66. package/docs/seo/omnizap-seo-playbook-br-2026-02-28.md +26 -0
  67. package/docs/seo/satellite-page-template.md +2 -0
  68. package/docs/seo/satellite-pages-phase1.json +40 -177
  69. package/eslint.config.js +2 -15
  70. package/index.js +8 -36
  71. package/ml/clip_classifier/README.md +4 -6
  72. package/observability/alert-rules.yml +12 -12
  73. package/observability/grafana/provisioning/dashboards/dashboards.yml +1 -1
  74. package/package.json +6 -3
  75. package/public/api-docs/index.html +220 -193
  76. package/public/bot-whatsapp-para-grupo/index.html +291 -261
  77. package/public/bot-whatsapp-sem-programar/index.html +291 -261
  78. package/public/comandos/index.html +421 -406
  79. package/public/como-automatizar-avisos-no-whatsapp/index.html +291 -261
  80. package/public/como-criar-comandos-whatsapp/index.html +291 -261
  81. package/public/como-evitar-spam-no-whatsapp/index.html +291 -261
  82. package/public/como-moderar-grupo-whatsapp/index.html +291 -261
  83. package/public/como-organizar-comunidade-whatsapp/index.html +291 -261
  84. package/public/css/github-project-panel.css +13 -8
  85. package/public/css/stickers-admin.css +25 -9
  86. package/public/css/styles.css +23 -16
  87. package/public/index.html +1106 -993
  88. package/public/js/apps/apiDocsApp.js +17 -167
  89. package/public/js/apps/createPackApp.js +69 -332
  90. package/public/js/apps/homeApp.js +274 -101
  91. package/public/js/apps/loginApp.js +3 -12
  92. package/public/js/apps/stickersAdminApp.js +190 -181
  93. package/public/js/apps/stickersApp.js +482 -1411
  94. package/public/js/apps/userApp.js +217 -1
  95. package/public/js/catalog.js +11 -74
  96. package/public/js/github-panel/components/ErrorState.js +1 -8
  97. package/public/js/github-panel/components/GithubProjectPanel.js +2 -9
  98. package/public/js/github-panel/components/SkeletonPanel.js +1 -11
  99. package/public/js/github-panel/components/StatCard.js +1 -7
  100. package/public/js/github-panel/vendor/react.js +1 -9
  101. package/public/js/runtime/react-runtime.js +1 -9
  102. package/public/licenca/index.html +200 -86
  103. package/public/login/index.html +315 -325
  104. package/public/melhor-bot-whatsapp-para-grupos/index.html +291 -261
  105. package/public/stickers/admin/index.html +14 -19
  106. package/public/stickers/create/index.html +39 -44
  107. package/public/stickers/index.html +96 -107
  108. package/public/termos-de-uso/index.html +369 -122
  109. package/public/user/index.html +527 -350
  110. package/scripts/cache-bust.mjs +5 -24
  111. package/scripts/generate-seo-satellite-pages.mjs +10 -13
  112. package/scripts/run-prettier-all.mjs +25 -0
  113. package/scripts/sticker-catalog-loadtest.mjs +13 -11
  114. package/scripts/sticker-worker-task.mjs +1 -4
  115. package/scripts/sync-readme-snapshot.mjs +3 -2
  116. package/server/auth/googleWebAuth/googleWebAuthService.js +614 -0
  117. package/server/controllers/stickerCatalogController.js +297 -632
  118. package/server/http/httpServer.js +2 -10
  119. package/server/routes/stickerCatalog/catalogHandlers/catalogAdminHttp.js +1 -8
  120. package/server/routes/stickerCatalog/catalogHandlers/catalogAuthHttp.js +1 -9
  121. package/server/routes/stickerCatalog/catalogHandlers/catalogPublicHttp.js +10 -11
  122. package/server/routes/stickerCatalog/catalogHandlers/catalogUploadHttp.js +1 -10
  123. package/server/routes/stickerCatalog/catalogRouter.js +11 -13
@@ -7,12 +7,7 @@ function Icon({ cls }) {
7
7
  }
8
8
 
9
9
  function Card({ title, code, iconClass }) {
10
- return h(
11
- 'section',
12
- { className: 'card' },
13
- h('h2', null, h(Icon, { cls: iconClass || 'fa-solid fa-file-code' }), title),
14
- h('pre', null, h('code', null, code)),
15
- );
10
+ return h('section', { className: 'card' }, h('h2', null, h(Icon, { cls: iconClass || 'fa-solid fa-file-code' }), title), h('pre', null, h('code', null, code)));
16
11
  }
17
12
 
18
13
  function SectionTitle({ iconClass, children }) {
@@ -49,10 +44,7 @@ function StatusPanel() {
49
44
  ok: true,
50
45
  latencyMs: Date.now() - start,
51
46
  cpu: Number.isFinite(Number(host.cpu_percent)) ? `${Number(host.cpu_percent).toFixed(2)}%` : 'n/d',
52
- ram:
53
- host.memory_used && host.memory_total
54
- ? `${host.memory_used} / ${host.memory_total} (${Number(host.memory_percent || 0).toFixed(2)}%)`
55
- : 'n/d',
47
+ ram: host.memory_used && host.memory_total ? `${host.memory_used} / ${host.memory_total} (${Number(host.memory_percent || 0).toFixed(2)}%)` : 'n/d',
56
48
  uptime: process.uptime || 'n/d',
57
49
  error: '',
58
50
  });
@@ -81,64 +73,19 @@ function StatusPanel() {
81
73
  const statusLabel = state.loading ? 'Consultando...' : state.ok ? 'Online' : 'Instável';
82
74
  const statusClass = state.loading ? 'badge badge-warn' : state.ok ? 'badge badge-ok' : 'badge badge-bad';
83
75
 
84
- return h(
85
- 'section',
86
- { className: 'card' },
87
- h('h3', { className: 'sub-title' }, h(Icon, { cls: 'fa-solid fa-heart-pulse' }), 'Status em tempo real'),
88
- h('div', { className: 'status-row' }, h('span', { className: statusClass }, statusLabel), state.latencyMs ? h('span', { className: 'status-meta' }, `Latência: ${state.latencyMs}ms`) : null),
89
- h(
90
- 'div',
91
- { className: 'status-grid' },
92
- h('div', { className: 'status-item' }, h('strong', null, 'CPU host'), h('span', null, state.cpu || 'n/d')),
93
- h('div', { className: 'status-item' }, h('strong', null, 'RAM host'), h('span', null, state.ram || 'n/d')),
94
- h('div', { className: 'status-item' }, h('strong', null, 'Uptime processo'), h('span', null, state.uptime || 'n/d')),
95
- ),
96
- state.error ? h('p', { className: 'status-error' }, `Falha: ${state.error}`) : null,
97
- );
76
+ return h('section', { className: 'card' }, h('h3', { className: 'sub-title' }, h(Icon, { cls: 'fa-solid fa-heart-pulse' }), 'Status em tempo real'), h('div', { className: 'status-row' }, h('span', { className: statusClass }, statusLabel), state.latencyMs ? h('span', { className: 'status-meta' }, `Latência: ${state.latencyMs}ms`) : null), h('div', { className: 'status-grid' }, h('div', { className: 'status-item' }, h('strong', null, 'CPU host'), h('span', null, state.cpu || 'n/d')), h('div', { className: 'status-item' }, h('strong', null, 'RAM host'), h('span', null, state.ram || 'n/d')), h('div', { className: 'status-item' }, h('strong', null, 'Uptime processo'), h('span', null, state.uptime || 'n/d'))), state.error ? h('p', { className: 'status-error' }, `Falha: ${state.error}`) : null);
98
77
  }
99
78
 
100
79
  function ApiDocsApp() {
101
80
  return h(
102
81
  'main',
103
82
  { className: 'wrap' },
104
- h(
105
- 'div',
106
- { className: 'top' },
107
- h('a', { href: '/' }, h(Icon, { cls: 'fa-solid fa-house' }), 'Home'),
108
- h('a', { href: '/stickers/' }, h(Icon, { cls: 'fa-solid fa-icons' }), 'Stickers'),
109
- h('a', { href: '/termos-de-uso/' }, h(Icon, { cls: 'fa-solid fa-file-contract' }), 'Termos'),
110
- h('a', { href: '/licenca/' }, h(Icon, { cls: 'fa-solid fa-scale-balanced' }), 'Licença'),
111
- h('a', { href: 'https://github.com/Kaikygr/omnizap-system', target: '_blank', rel: 'noreferrer noopener' }, h(Icon, { cls: 'fa-brands fa-github' }), 'GitHub'),
112
- ),
83
+ h('div', { className: 'top' }, h('a', { href: '/' }, h(Icon, { cls: 'fa-solid fa-house' }), 'Home'), h('a', { href: '/stickers/' }, h(Icon, { cls: 'fa-solid fa-icons' }), 'Stickers'), h('a', { href: '/termos-de-uso/' }, h(Icon, { cls: 'fa-solid fa-file-contract' }), 'Termos'), h('a', { href: '/licenca/' }, h(Icon, { cls: 'fa-solid fa-scale-balanced' }), 'Licença'), h('a', { href: 'https://github.com/Kaikygr/omnizap-system', target: '_blank', rel: 'noreferrer noopener' }, h(Icon, { cls: 'fa-brands fa-github' }), 'GitHub')),
113
84
  h('h1', null, h(Icon, { cls: 'fa-solid fa-code' }), 'OmniZap API | Área de Desenvolvedor'),
114
85
  h('p', null, 'Documentação técnica da API OmniZap para bots e automação WhatsApp, com o catálogo de stickers como módulo integrável.'),
115
86
  h(SectionTitle, { iconClass: 'fa-solid fa-route' }, 'Casos de uso'),
116
- h(
117
- 'section',
118
- { className: 'card' },
119
- h('ul', { className: 'list' },
120
- h('li', null, 'Operar bot WhatsApp com endpoints públicos para conteúdo e interação.'),
121
- h('li', null, 'Integrar server-to-server para sincronizar packs, stickers e métricas.'),
122
- h('li', null, 'Conectar automações internas (CRM, suporte, marketing e comunidades).')
123
- ),
124
- ),
125
- h(
126
- 'section',
127
- { className: 'card' },
128
- h('h2', null, h(Icon, { cls: 'fa-solid fa-diagram-project' }), 'Mapa da plataforma'),
129
- h(
130
- 'p',
131
- null,
132
- 'O domínio principal é a plataforma de bot + API. O catálogo de stickers funciona como feature integrada para distribuição e engajamento.',
133
- ),
134
- h(
135
- 'ul',
136
- { className: 'list' },
137
- h('li', null, 'Página principal: / (plataforma OmniZap)'),
138
- h('li', null, 'Catálogo: /stickers/ (módulo de stickers)'),
139
- h('li', null, 'Packs públicos: /stickers/{packKey} (landing de conteúdo)'),
140
- ),
141
- ),
87
+ h('section', { className: 'card' }, h('ul', { className: 'list' }, h('li', null, 'Operar bot WhatsApp com endpoints públicos para conteúdo e interação.'), h('li', null, 'Integrar server-to-server para sincronizar packs, stickers e métricas.'), h('li', null, 'Conectar automações internas (CRM, suporte, marketing e comunidades).'))),
88
+ h('section', { className: 'card' }, h('h2', null, h(Icon, { cls: 'fa-solid fa-diagram-project' }), 'Mapa da plataforma'), h('p', null, 'O domínio principal é a plataforma de bot + API. O catálogo de stickers funciona como feature integrada para distribuição e engajamento.'), h('ul', { className: 'list' }, h('li', null, 'Página principal: / (plataforma OmniZap)'), h('li', null, 'Catálogo: /stickers/ (módulo de stickers)'), h('li', null, 'Packs públicos: /stickers/{packKey} (landing de conteúdo)'))),
142
89
  h(StatusPanel),
143
90
  h(SectionTitle, { iconClass: 'fa-solid fa-plug-circle-check' }, 'Endpoints'),
144
91
  h(Card, { title: 'Base URL', code: 'https://omnizap.shop/api/sticker-packs', iconClass: 'fa-solid fa-link' }),
@@ -155,10 +102,7 @@ function ApiDocsApp() {
155
102
  h(Card, { title: 'Detalhes de pack', code: 'GET /api/sticker-packs/:packKey', iconClass: 'fa-solid fa-circle-info' }),
156
103
  h(Card, {
157
104
  title: 'Interações do pack (dados reais)',
158
- code:
159
- 'POST /api/sticker-packs/:packKey/open\n' +
160
- 'POST /api/sticker-packs/:packKey/like\n' +
161
- 'POST /api/sticker-packs/:packKey/dislike',
105
+ code: 'POST /api/sticker-packs/:packKey/open\n' + 'POST /api/sticker-packs/:packKey/like\n' + 'POST /api/sticker-packs/:packKey/dislike',
162
106
  iconClass: 'fa-solid fa-thumbs-up',
163
107
  }),
164
108
  h(Card, { title: 'Contato de suporte', code: 'GET /api/sticker-packs/support', iconClass: 'fa-brands fa-whatsapp' }),
@@ -173,138 +117,49 @@ function ApiDocsApp() {
173
117
  h(SectionTitle, { iconClass: 'fa-solid fa-brackets-curly' }, 'Como a API responde'),
174
118
  h(Card, {
175
119
  title: 'Padrão de resposta (sucesso)',
176
- code:
177
- '{\n' +
178
- ' "data": [ ... ],\n' +
179
- ' "pagination": { "limit": 24, "offset": 0, "has_more": true, "next_offset": 24 },\n' +
180
- ' "filters": { "q": "", "visibility": "public", "categories": [] }\n' +
181
- '}',
120
+ code: '{\n' + ' "data": [ ... ],\n' + ' "pagination": { "limit": 24, "offset": 0, "has_more": true, "next_offset": 24 },\n' + ' "filters": { "q": "", "visibility": "public", "categories": [] }\n' + '}',
182
121
  iconClass: 'fa-solid fa-circle-check',
183
122
  }),
184
123
  h(Card, {
185
124
  title: 'Padrão de resposta (erro)',
186
- code:
187
- '{\n' +
188
- ' "ok": false,\n' +
189
- ' "error": "mensagem descritiva do erro"\n' +
190
- '}',
125
+ code: '{\n' + ' "ok": false,\n' + ' "error": "mensagem descritiva do erro"\n' + '}',
191
126
  iconClass: 'fa-solid fa-triangle-exclamation',
192
127
  }),
193
128
  h(Card, {
194
129
  title: 'Exemplo real de retorno (pack + engagement)',
195
- code:
196
- '{\n' +
197
- ' "data": {\n' +
198
- ' "pack_key": "auto-manga-panel-2-iu4n2",\n' +
199
- ' "name": "[AUTO] Manga Panel #2",\n' +
200
- ' "sticker_count": 30,\n' +
201
- ' "tags": ["manga-panel", "anime"],\n' +
202
- ' "engagement": {\n' +
203
- ' "open_count": 120,\n' +
204
- ' "like_count": 34,\n' +
205
- ' "dislike_count": 2,\n' +
206
- ' "score": 32\n' +
207
- ' }\n' +
208
- ' }\n' +
209
- '}',
130
+ code: '{\n' + ' "data": {\n' + ' "pack_key": "auto-manga-panel-2-iu4n2",\n' + ' "name": "[AUTO] Manga Panel #2",\n' + ' "sticker_count": 30,\n' + ' "tags": ["manga-panel", "anime"],\n' + ' "engagement": {\n' + ' "open_count": 120,\n' + ' "like_count": 34,\n' + ' "dislike_count": 2,\n' + ' "score": 32\n' + ' }\n' + ' }\n' + '}',
210
131
  iconClass: 'fa-solid fa-database',
211
132
  }),
212
133
  h(SectionTitle, { iconClass: 'fa-solid fa-filter' }, 'Filtros e paginação'),
213
134
  h(Card, {
214
135
  title: 'Parâmetros principais',
215
- code:
216
- 'q: texto de busca (nome, publisher, descrição, pack_key)\n' +
217
- 'visibility: public | unlisted | all\n' +
218
- 'categories: lista separada por vírgula (ex: anime,meme)\n' +
219
- 'limit: tamanho da página\n' +
220
- 'offset: deslocamento para próxima página',
136
+ code: 'q: texto de busca (nome, publisher, descrição, pack_key)\n' + 'visibility: public | unlisted | all\n' + 'categories: lista separada por vírgula (ex: anime,meme)\n' + 'limit: tamanho da página\n' + 'offset: deslocamento para próxima página',
221
137
  iconClass: 'fa-solid fa-sliders',
222
138
  }),
223
139
  h(Card, {
224
140
  title: 'Exemplo de paginação incremental',
225
- code:
226
- 'GET /api/sticker-packs?visibility=public&limit=24&offset=0\n' +
227
- 'GET /api/sticker-packs?visibility=public&limit=24&offset=24\n' +
228
- 'GET /api/sticker-packs?visibility=public&limit=24&offset=48',
141
+ code: 'GET /api/sticker-packs?visibility=public&limit=24&offset=0\n' + 'GET /api/sticker-packs?visibility=public&limit=24&offset=24\n' + 'GET /api/sticker-packs?visibility=public&limit=24&offset=48',
229
142
  iconClass: 'fa-solid fa-forward-step',
230
143
  }),
231
144
  h(SectionTitle, { iconClass: 'fa-solid fa-diagram-project' }, 'Como integrar no seu sistema'),
232
145
  h(Card, {
233
146
  title: 'Passo a passo de integração',
234
- code:
235
- '1) Defina a base URL: https://omnizap.shop/api/sticker-packs\n' +
236
- '2) Faça um health-check inicial em /system-summary\n' +
237
- '3) Liste packs com /?visibility=public&limit=24\n' +
238
- '4) Abra detalhes com /:packKey\n' +
239
- '5) Baixe stickers com /:packKey/stickers/:stickerId.webp\n' +
240
- '6) Trate paginação usando limit/offset e has_more',
147
+ code: '1) Defina a base URL: https://omnizap.shop/api/sticker-packs\n' + '2) Faça um health-check inicial em /system-summary\n' + '3) Liste packs com /?visibility=public&limit=24\n' + '4) Abra detalhes com /:packKey\n' + '5) Baixe stickers com /:packKey/stickers/:stickerId.webp\n' + '6) Trate paginação usando limit/offset e has_more',
241
148
  iconClass: 'fa-solid fa-list-check',
242
149
  }),
243
150
  h(Card, {
244
151
  title: 'Exemplo cURL',
245
- code:
246
- 'curl -sS "https://omnizap.shop/api/sticker-packs?visibility=public&limit=5"\n' +
247
- 'curl -sS "https://omnizap.shop/api/sticker-packs?categories=anime,meme&limit=12"\n' +
248
- 'curl -sS "https://omnizap.shop/api/sticker-packs/orphan-stickers?limit=20&offset=0"\n' +
249
- 'curl -sS -X POST "https://omnizap.shop/api/sticker-packs/<packKey>/open"\n' +
250
- 'curl -sS -X POST "https://omnizap.shop/api/sticker-packs/<packKey>/like"\n' +
251
- 'curl -sS "https://omnizap.shop/api/sticker-packs/support"\n' +
252
- 'curl -sS "https://omnizap.shop/api/sticker-packs/system-summary"\n' +
253
- 'curl -sS "https://omnizap.shop/api/sticker-packs/project-summary"',
152
+ code: 'curl -sS "https://omnizap.shop/api/sticker-packs?visibility=public&limit=5"\n' + 'curl -sS "https://omnizap.shop/api/sticker-packs?categories=anime,meme&limit=12"\n' + 'curl -sS "https://omnizap.shop/api/sticker-packs/orphan-stickers?limit=20&offset=0"\n' + 'curl -sS -X POST "https://omnizap.shop/api/sticker-packs/<packKey>/open"\n' + 'curl -sS -X POST "https://omnizap.shop/api/sticker-packs/<packKey>/like"\n' + 'curl -sS "https://omnizap.shop/api/sticker-packs/support"\n' + 'curl -sS "https://omnizap.shop/api/sticker-packs/system-summary"\n' + 'curl -sS "https://omnizap.shop/api/sticker-packs/project-summary"',
254
153
  iconClass: 'fa-solid fa-terminal',
255
154
  }),
256
155
  h(Card, {
257
156
  title: 'Exemplo JavaScript (fetch)',
258
- code:
259
- "const API_BASE = 'https://omnizap.shop/api/sticker-packs';\n\n" +
260
- 'async function getPublicPacks() {\n' +
261
- " const url = `${API_BASE}?visibility=public&limit=24&offset=0`;\n" +
262
- ' const response = await fetch(url);\n' +
263
- " if (!response.ok) throw new Error(`HTTP ${response.status}`);\n" +
264
- ' const payload = await response.json();\n' +
265
- ' return payload?.data || [];\n' +
266
- '}\n\n' +
267
- 'async function getPackDetails(packKey) {\n' +
268
- ' const response = await fetch(`${API_BASE}/${encodeURIComponent(packKey)}`);\n' +
269
- " if (!response.ok) throw new Error(`HTTP ${response.status}`);\n" +
270
- ' const payload = await response.json();\n' +
271
- ' return payload?.data || null;\n' +
272
- '}\n\n' +
273
- '(async () => {\n' +
274
- ' try {\n' +
275
- ' const packs = await getPublicPacks();\n' +
276
- " console.log('Packs encontrados:', packs.length);\n" +
277
- ' if (packs[0]?.pack_key) {\n' +
278
- ' const details = await getPackDetails(packs[0].pack_key);\n' +
279
- " console.log('Primeiro pack:', details?.name, details?.pack_key);\n" +
280
- " await fetch(`${API_BASE}/${encodeURIComponent(packs[0].pack_key)}/open`, { method: 'POST' });\n" +
281
- ' }\n' +
282
- ' } catch (error) {\n' +
283
- " console.error('Falha ao consumir API:', error.message);\n" +
284
- ' }\n' +
285
- '})();',
157
+ code: "const API_BASE = 'https://omnizap.shop/api/sticker-packs';\n\n" + 'async function getPublicPacks() {\n' + ' const url = `${API_BASE}?visibility=public&limit=24&offset=0`;\n' + ' const response = await fetch(url);\n' + ' if (!response.ok) throw new Error(`HTTP ${response.status}`);\n' + ' const payload = await response.json();\n' + ' return payload?.data || [];\n' + '}\n\n' + 'async function getPackDetails(packKey) {\n' + ' const response = await fetch(`${API_BASE}/${encodeURIComponent(packKey)}`);\n' + ' if (!response.ok) throw new Error(`HTTP ${response.status}`);\n' + ' const payload = await response.json();\n' + ' return payload?.data || null;\n' + '}\n\n' + '(async () => {\n' + ' try {\n' + ' const packs = await getPublicPacks();\n' + " console.log('Packs encontrados:', packs.length);\n" + ' if (packs[0]?.pack_key) {\n' + ' const details = await getPackDetails(packs[0].pack_key);\n' + " console.log('Primeiro pack:', details?.name, details?.pack_key);\n" + " await fetch(`${API_BASE}/${encodeURIComponent(packs[0].pack_key)}/open`, { method: 'POST' });\n" + ' }\n' + ' } catch (error) {\n' + " console.error('Falha ao consumir API:', error.message);\n" + ' }\n' + '})();',
286
158
  iconClass: 'fa-brands fa-js',
287
159
  }),
288
160
  h(Card, {
289
161
  title: 'Exemplo Node.js (backend / integração server-to-server)',
290
- code:
291
- "const API_BASE = 'https://omnizap.shop/api/sticker-packs';\n" +
292
- '\n' +
293
- 'export async function syncCatalogPage(offset = 0) {\n' +
294
- ' const url = `${API_BASE}?visibility=public&limit=50&offset=${offset}`;\n' +
295
- ' const response = await fetch(url, { headers: { Accept: "application/json" } });\n' +
296
- ' if (!response.ok) throw new Error(`Catalog HTTP ${response.status}`);\n' +
297
- ' const payload = await response.json();\n' +
298
- ' const packs = payload?.data || [];\n' +
299
- ' const nextOffset = payload?.pagination?.next_offset;\n' +
300
- ' return { packs, nextOffset, hasMore: Boolean(payload?.pagination?.has_more) };\n' +
301
- '}\n' +
302
- '\n' +
303
- 'export async function markPackLike(packKey) {\n' +
304
- ' const response = await fetch(`${API_BASE}/${encodeURIComponent(packKey)}/like`, { method: "POST" });\n' +
305
- ' if (!response.ok) throw new Error(`Like HTTP ${response.status}`);\n' +
306
- ' return response.json();\n' +
307
- '}',
162
+ code: "const API_BASE = 'https://omnizap.shop/api/sticker-packs';\n" + '\n' + 'export async function syncCatalogPage(offset = 0) {\n' + ' const url = `${API_BASE}?visibility=public&limit=50&offset=${offset}`;\n' + ' const response = await fetch(url, { headers: { Accept: "application/json" } });\n' + ' if (!response.ok) throw new Error(`Catalog HTTP ${response.status}`);\n' + ' const payload = await response.json();\n' + ' const packs = payload?.data || [];\n' + ' const nextOffset = payload?.pagination?.next_offset;\n' + ' return { packs, nextOffset, hasMore: Boolean(payload?.pagination?.has_more) };\n' + '}\n' + '\n' + 'export async function markPackLike(packKey) {\n' + ' const response = await fetch(`${API_BASE}/${encodeURIComponent(packKey)}/like`, { method: "POST" });\n' + ' if (!response.ok) throw new Error(`Like HTTP ${response.status}`);\n' + ' return response.json();\n' + '}',
308
163
  iconClass: 'fa-solid fa-server',
309
164
  }),
310
165
  h(SectionTitle, { iconClass: 'fa-solid fa-circle-question' }, 'FAQ rápido'),
@@ -325,12 +180,7 @@ function ApiDocsApp() {
325
180
  }),
326
181
  h(Card, {
327
182
  title: 'Checklist de produção',
328
- code:
329
- '- Implementar retry com backoff (429/5xx)\n' +
330
- '- Cachear listagens por 30-120s no seu sistema\n' +
331
- '- Validar next_offset para paginação contínua\n' +
332
- '- Tratar 404 de pack removido/inválido\n' +
333
- '- Registrar métricas de latência e taxa de erro do consumo',
183
+ code: '- Implementar retry com backoff (429/5xx)\n' + '- Cachear listagens por 30-120s no seu sistema\n' + '- Validar next_offset para paginação contínua\n' + '- Tratar 404 de pack removido/inválido\n' + '- Registrar métricas de latência e taxa de erro do consumo',
334
184
  iconClass: 'fa-solid fa-shield-heart',
335
185
  }),
336
186
  );