@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.
- package/README.md +13 -13
- package/app/config/adminIdentity.js +1 -3
- package/app/connection/socketController.js +10 -20
- package/app/controllers/messageController.js +7 -28
- package/app/modules/aiModule/catCommand.js +29 -192
- package/app/modules/broadcastModule/noticeCommand.js +28 -97
- package/app/modules/gameModule/diceCommand.js +6 -32
- package/app/modules/playModule/playCommand.js +57 -258
- package/app/modules/quoteModule/quoteCommand.js +2 -4
- package/app/modules/rpgPokemonModule/rpgPokemonRepository.js +1 -13
- package/app/modules/statsModule/noMessageCommand.js +16 -84
- package/app/modules/statsModule/rankingCommand.js +5 -25
- package/app/modules/statsModule/rankingCommon.js +1 -9
- package/app/modules/stickerModule/convertToWebp.js +4 -27
- package/app/modules/stickerModule/stickerCommand.js +13 -24
- package/app/modules/stickerModule/stickerTextCommand.js +13 -25
- package/app/modules/stickerPackModule/autoPackCollectorService.js +16 -7
- package/app/modules/stickerPackModule/domainEventOutboxRepository.js +20 -36
- package/app/modules/stickerPackModule/domainEvents.js +2 -11
- package/app/modules/stickerPackModule/semanticReclassificationEngine.js +13 -50
- package/app/modules/stickerPackModule/semanticReclassificationEngine.test.js +2 -15
- package/app/modules/stickerPackModule/semanticThemeClusterService.js +14 -41
- package/app/modules/stickerPackModule/stickerAssetClassificationRepository.js +25 -95
- package/app/modules/stickerPackModule/stickerAssetRepository.js +12 -31
- package/app/modules/stickerPackModule/stickerAssetReprocessQueueRepository.js +13 -18
- package/app/modules/stickerPackModule/stickerAutoPackByTagsRuntime.js +284 -709
- package/app/modules/stickerPackModule/stickerClassificationBackgroundRuntime.js +27 -106
- package/app/modules/stickerPackModule/stickerClassificationService.js +46 -77
- package/app/modules/stickerPackModule/stickerDedicatedTaskWorkerRuntime.js +13 -53
- package/app/modules/stickerPackModule/stickerDomainEventBus.js +10 -16
- package/app/modules/stickerPackModule/stickerDomainEventConsumerRuntime.js +40 -39
- package/app/modules/stickerPackModule/stickerMarketplaceDriftService.js +1 -4
- package/app/modules/stickerPackModule/stickerObjectStorageService.js +26 -26
- package/app/modules/stickerPackModule/stickerPackCommandHandlers.js +32 -187
- package/app/modules/stickerPackModule/stickerPackInteractionEventRepository.js +6 -15
- package/app/modules/stickerPackModule/stickerPackItemRepository.js +6 -32
- package/app/modules/stickerPackModule/stickerPackMarketplaceService.js +12 -36
- package/app/modules/stickerPackModule/stickerPackMessageService.js +12 -40
- package/app/modules/stickerPackModule/stickerPackRepository.js +23 -66
- package/app/modules/stickerPackModule/stickerPackScoreSnapshotRepository.js +9 -21
- package/app/modules/stickerPackModule/stickerPackScoreSnapshotRuntime.js +10 -40
- package/app/modules/stickerPackModule/stickerPackService.js +50 -115
- package/app/modules/stickerPackModule/stickerPackServiceRuntime.js +2 -21
- package/app/modules/stickerPackModule/stickerPackUtils.js +13 -3
- package/app/modules/stickerPackModule/stickerStorageService.js +16 -65
- package/app/modules/stickerPackModule/stickerWorkerPipelineRuntime.js +4 -22
- package/app/modules/stickerPackModule/stickerWorkerTaskQueueRepository.js +14 -29
- package/app/modules/systemMetricsModule/pingCommand.js +9 -39
- package/app/modules/tiktokModule/tiktokCommand.js +17 -109
- package/app/modules/userModule/userCommand.js +2 -88
- package/app/observability/metrics.js +5 -16
- package/app/services/captchaService.js +1 -6
- package/app/services/dbWriteQueue.js +3 -18
- package/app/services/featureFlagService.js +2 -8
- package/app/services/newsBroadcastService.js +0 -1
- package/app/services/queueUtils.js +2 -4
- package/app/services/whatsappLoginLinkService.js +7 -9
- package/app/store/premiumUserStore.js +1 -2
- package/app/utils/antiLink/antiLinkModule.js +3 -233
- package/app/utils/logger/loggerModule.js +9 -34
- package/app/utils/systemMetrics/systemMetricsModule.js +1 -4
- package/database/index.js +1 -0
- package/database/init.js +1 -8
- package/database/migrations/20260228_0027_web_visit_event.sql +15 -0
- package/docker-compose.yml +27 -27
- package/docs/seo/omnizap-seo-playbook-br-2026-02-28.md +26 -0
- package/docs/seo/satellite-page-template.md +2 -0
- package/docs/seo/satellite-pages-phase1.json +40 -177
- package/eslint.config.js +2 -15
- package/index.js +8 -36
- package/ml/clip_classifier/README.md +4 -6
- package/observability/alert-rules.yml +12 -12
- package/observability/grafana/provisioning/dashboards/dashboards.yml +1 -1
- package/package.json +6 -3
- package/public/api-docs/index.html +220 -193
- package/public/bot-whatsapp-para-grupo/index.html +291 -261
- package/public/bot-whatsapp-sem-programar/index.html +291 -261
- package/public/comandos/index.html +421 -406
- package/public/como-automatizar-avisos-no-whatsapp/index.html +291 -261
- package/public/como-criar-comandos-whatsapp/index.html +291 -261
- package/public/como-evitar-spam-no-whatsapp/index.html +291 -261
- package/public/como-moderar-grupo-whatsapp/index.html +291 -261
- package/public/como-organizar-comunidade-whatsapp/index.html +291 -261
- package/public/css/github-project-panel.css +13 -8
- package/public/css/stickers-admin.css +25 -9
- package/public/css/styles.css +23 -16
- package/public/index.html +1106 -993
- package/public/js/apps/apiDocsApp.js +17 -167
- package/public/js/apps/createPackApp.js +69 -332
- package/public/js/apps/homeApp.js +274 -101
- package/public/js/apps/loginApp.js +3 -12
- package/public/js/apps/stickersAdminApp.js +190 -181
- package/public/js/apps/stickersApp.js +482 -1411
- package/public/js/apps/userApp.js +217 -1
- package/public/js/catalog.js +11 -74
- package/public/js/github-panel/components/ErrorState.js +1 -8
- package/public/js/github-panel/components/GithubProjectPanel.js +2 -9
- package/public/js/github-panel/components/SkeletonPanel.js +1 -11
- package/public/js/github-panel/components/StatCard.js +1 -7
- package/public/js/github-panel/vendor/react.js +1 -9
- package/public/js/runtime/react-runtime.js +1 -9
- package/public/licenca/index.html +200 -86
- package/public/login/index.html +315 -325
- package/public/melhor-bot-whatsapp-para-grupos/index.html +291 -261
- package/public/stickers/admin/index.html +14 -19
- package/public/stickers/create/index.html +39 -44
- package/public/stickers/index.html +96 -107
- package/public/termos-de-uso/index.html +369 -122
- package/public/user/index.html +527 -350
- package/scripts/cache-bust.mjs +5 -24
- package/scripts/generate-seo-satellite-pages.mjs +10 -13
- package/scripts/run-prettier-all.mjs +25 -0
- package/scripts/sticker-catalog-loadtest.mjs +13 -11
- package/scripts/sticker-worker-task.mjs +1 -4
- package/scripts/sync-readme-snapshot.mjs +3 -2
- package/server/auth/googleWebAuth/googleWebAuthService.js +614 -0
- package/server/controllers/stickerCatalogController.js +297 -632
- package/server/http/httpServer.js +2 -10
- package/server/routes/stickerCatalog/catalogHandlers/catalogAdminHttp.js +1 -8
- package/server/routes/stickerCatalog/catalogHandlers/catalogAuthHttp.js +1 -9
- package/server/routes/stickerCatalog/catalogHandlers/catalogPublicHttp.js +10 -11
- package/server/routes/stickerCatalog/catalogHandlers/catalogUploadHttp.js +1 -10
- 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
|
-
|
|
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
|
);
|