@kaikybrofc/omnizap-system 2.2.10 → 2.3.0
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 +20 -18
- 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 +13 -34
- 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/init.js +1 -8
- 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 +1117 -994
- package/public/js/apps/apiDocsApp.js +17 -167
- package/public/js/apps/createPackApp.js +69 -332
- package/public/js/apps/homeApp.js +94 -74
- package/public/js/apps/loginApp.js +3 -12
- package/public/js/apps/stickersAdminApp.js +190 -181
- package/public/js/apps/stickersApp.js +496 -1397
- 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 +104 -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 +142 -115
- package/public/user/index.html +347 -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/controllers/stickerCatalogController.js +67 -5
- 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
package/scripts/cache-bust.mjs
CHANGED
|
@@ -5,20 +5,10 @@ import path from 'node:path';
|
|
|
5
5
|
import { URLSearchParams } from 'node:url';
|
|
6
6
|
|
|
7
7
|
const TARGET_SOURCE_EXTENSIONS = new Set(['.html', '.js', '.mjs', '.css']);
|
|
8
|
-
const ASSET_SUFFIX_PATTERN =
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
'gi',
|
|
13
|
-
);
|
|
14
|
-
const QUOTED_LOCAL_ASSET_PATTERN = new RegExp(
|
|
15
|
-
String.raw`(["'])((?:\/|\.{1,2}\/)[^"'\s]+?${ASSET_SUFFIX_PATTERN})\1`,
|
|
16
|
-
'gi',
|
|
17
|
-
);
|
|
18
|
-
const CSS_URL_ASSET_PATTERN = new RegExp(
|
|
19
|
-
String.raw`(url\(\s*["']?)([^"')\s]+?${ASSET_SUFFIX_PATTERN})(["']?\s*\))`,
|
|
20
|
-
'gi',
|
|
21
|
-
);
|
|
8
|
+
const ASSET_SUFFIX_PATTERN = String.raw`\.(?:js|mjs|cjs|css|png|jpe?g|gif|svg|webp|ico|json|map|woff2?|ttf|eot)(?:\?[^"'#\s)]*)?(?:#[^"' \s)]*)?`;
|
|
9
|
+
const HTML_ATTRIBUTE_ASSET_PATTERN = new RegExp(String.raw`((?:src|href|poster)=["'])([^"']+?${ASSET_SUFFIX_PATTERN})(["'])`, 'gi');
|
|
10
|
+
const QUOTED_LOCAL_ASSET_PATTERN = new RegExp(String.raw`(["'])((?:\/|\.{1,2}\/)[^"'\s]+?${ASSET_SUFFIX_PATTERN})\1`, 'gi');
|
|
11
|
+
const CSS_URL_ASSET_PATTERN = new RegExp(String.raw`(url\(\s*["']?)([^"')\s]+?${ASSET_SUFFIX_PATTERN})(["']?\s*\))`, 'gi');
|
|
22
12
|
|
|
23
13
|
const usage = () => {
|
|
24
14
|
console.error('Uso: node scripts/cache-bust.mjs --dir <diretorio> --version <build_id>');
|
|
@@ -77,16 +67,7 @@ const isLocalAssetPath = (assetPath) => {
|
|
|
77
67
|
if (!value) return false;
|
|
78
68
|
|
|
79
69
|
const lower = value.toLowerCase();
|
|
80
|
-
if (
|
|
81
|
-
lower.startsWith('http://') ||
|
|
82
|
-
lower.startsWith('https://') ||
|
|
83
|
-
lower.startsWith('//') ||
|
|
84
|
-
lower.startsWith('data:') ||
|
|
85
|
-
lower.startsWith('mailto:') ||
|
|
86
|
-
lower.startsWith('tel:') ||
|
|
87
|
-
lower.startsWith('javascript:') ||
|
|
88
|
-
lower.startsWith('#')
|
|
89
|
-
) {
|
|
70
|
+
if (lower.startsWith('http://') || lower.startsWith('https://') || lower.startsWith('//') || lower.startsWith('data:') || lower.startsWith('mailto:') || lower.startsWith('tel:') || lower.startsWith('javascript:') || lower.startsWith('#')) {
|
|
90
71
|
return false;
|
|
91
72
|
}
|
|
92
73
|
|
|
@@ -54,7 +54,12 @@ const ensurePageConfig = (page) => {
|
|
|
54
54
|
h1: String(page.h1).trim(),
|
|
55
55
|
intro: String(page.intro).trim(),
|
|
56
56
|
intent_label: String(page.intent_label || 'Guia pratico').trim(),
|
|
57
|
-
keywords: Array.isArray(page.keywords)
|
|
57
|
+
keywords: Array.isArray(page.keywords)
|
|
58
|
+
? page.keywords
|
|
59
|
+
.filter(Boolean)
|
|
60
|
+
.map((item) => String(item).trim())
|
|
61
|
+
.filter(Boolean)
|
|
62
|
+
: [],
|
|
58
63
|
sections: Array.isArray(page.sections) ? page.sections : [],
|
|
59
64
|
faq: Array.isArray(page.faq) ? page.faq : [],
|
|
60
65
|
related_links: Array.isArray(page.related_links) ? page.related_links : [],
|
|
@@ -63,19 +68,13 @@ const ensurePageConfig = (page) => {
|
|
|
63
68
|
|
|
64
69
|
const renderSection = (section) => {
|
|
65
70
|
const title = String(section?.title || '').trim();
|
|
66
|
-
const paragraphs = Array.isArray(section?.paragraphs)
|
|
67
|
-
|
|
68
|
-
: [];
|
|
69
|
-
const bullets = Array.isArray(section?.bullets)
|
|
70
|
-
? section.bullets.map((item) => String(item || '').trim()).filter(Boolean)
|
|
71
|
-
: [];
|
|
71
|
+
const paragraphs = Array.isArray(section?.paragraphs) ? section.paragraphs.map((item) => String(item || '').trim()).filter(Boolean) : [];
|
|
72
|
+
const bullets = Array.isArray(section?.bullets) ? section.bullets.map((item) => String(item || '').trim()).filter(Boolean) : [];
|
|
72
73
|
|
|
73
74
|
if (!title && paragraphs.length === 0 && bullets.length === 0) return '';
|
|
74
75
|
|
|
75
76
|
const paragraphsHtml = paragraphs.map((paragraph) => ` <p>${escapeHtml(paragraph)}</p>`).join('\n');
|
|
76
|
-
const bulletsHtml = bullets.length
|
|
77
|
-
? `\n <ul>\n${bullets.map((bullet) => ` <li>${escapeHtml(bullet)}</li>`).join('\n')}\n </ul>`
|
|
78
|
-
: '';
|
|
77
|
+
const bulletsHtml = bullets.length ? `\n <ul>\n${bullets.map((bullet) => ` <li>${escapeHtml(bullet)}</li>`).join('\n')}\n </ul>` : '';
|
|
79
78
|
|
|
80
79
|
return `<section class="card">\n ${title ? `<h2>${escapeHtml(title)}</h2>` : ''}\n${paragraphsHtml}${bulletsHtml}\n </section>`;
|
|
81
80
|
};
|
|
@@ -122,9 +121,7 @@ const withRequiredLinks = (relatedLinks) => {
|
|
|
122
121
|
const renderLinks = (links) => {
|
|
123
122
|
if (!links.length) return '';
|
|
124
123
|
|
|
125
|
-
return `<section class="card">\n <h2>Links úteis</h2>\n <div class="links-grid">\n${links
|
|
126
|
-
.map((link) => ` <a href="${escapeHtml(link.href)}">${escapeHtml(link.label)}</a>`)
|
|
127
|
-
.join('\n')}\n </div>\n </section>`;
|
|
124
|
+
return `<section class="card">\n <h2>Links úteis</h2>\n <div class="links-grid">\n${links.map((link) => ` <a href="${escapeHtml(link.href)}">${escapeHtml(link.label)}</a>`).join('\n')}\n </div>\n </section>`;
|
|
128
125
|
};
|
|
129
126
|
|
|
130
127
|
const renderPageHtml = (page, generatedAt) => {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
|
|
6
|
+
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const projectRoot = path.resolve(scriptDir, '..');
|
|
8
|
+
const prettierBin = path.join(projectRoot, 'node_modules', '.bin', process.platform === 'win32' ? 'prettier.cmd' : 'prettier');
|
|
9
|
+
|
|
10
|
+
const mode = process.argv.includes('--check') ? '--check' : '--write';
|
|
11
|
+
const args = ['.', mode, '--config', '.prettierrc', '--ignore-path', '.gitignore', '--ignore-unknown'];
|
|
12
|
+
|
|
13
|
+
const child = spawn(prettierBin, args, {
|
|
14
|
+
stdio: 'inherit',
|
|
15
|
+
cwd: projectRoot,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
child.on('exit', (code) => {
|
|
19
|
+
process.exit(code ?? 1);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
child.on('error', (error) => {
|
|
23
|
+
console.error(`[prettier] Falha ao executar: ${error?.message || 'erro desconhecido'}`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
});
|
|
@@ -6,11 +6,7 @@ import fs from 'node:fs/promises';
|
|
|
6
6
|
import { URL } from 'node:url';
|
|
7
7
|
|
|
8
8
|
const DEFAULT_BASE_URL = process.env.STICKER_LOADTEST_BASE_URL || 'http://127.0.0.1:9102';
|
|
9
|
-
const DEFAULT_PATHS = [
|
|
10
|
-
'/api/sticker-packs?limit=24&offset=0&sort=popular',
|
|
11
|
-
'/api/sticker-packs/stats',
|
|
12
|
-
'/api/sticker-packs/creators?limit=25',
|
|
13
|
-
];
|
|
9
|
+
const DEFAULT_PATHS = ['/api/sticker-packs?limit=24&offset=0&sort=popular', '/api/sticker-packs/stats', '/api/sticker-packs/creators?limit=25'];
|
|
14
10
|
const DEFAULT_DURATION_SECONDS = 30;
|
|
15
11
|
const DEFAULT_CONCURRENCY = 20;
|
|
16
12
|
const DEFAULT_TIMEOUT_MS = 12_000;
|
|
@@ -33,7 +29,9 @@ const parseCliArgs = (argv) => {
|
|
|
33
29
|
};
|
|
34
30
|
|
|
35
31
|
const args = parseCliArgs(process.argv.slice(2));
|
|
36
|
-
const baseUrl = String(args.get('--base-url') || DEFAULT_BASE_URL)
|
|
32
|
+
const baseUrl = String(args.get('--base-url') || DEFAULT_BASE_URL)
|
|
33
|
+
.trim()
|
|
34
|
+
.replace(/\/+$/, '');
|
|
37
35
|
const durationSeconds = Math.max(5, Number(args.get('--duration-seconds') || DEFAULT_DURATION_SECONDS));
|
|
38
36
|
const concurrency = Math.max(1, Number(args.get('--concurrency') || DEFAULT_CONCURRENCY));
|
|
39
37
|
const timeoutMs = Math.max(1000, Number(args.get('--timeout-ms') || DEFAULT_TIMEOUT_MS));
|
|
@@ -146,11 +144,15 @@ const main = async () => {
|
|
|
146
144
|
console.log(`[loadtest] duration_seconds=${durationSeconds} concurrency=${concurrency} paths=${requestPaths.join(',')}`);
|
|
147
145
|
await sleep(250);
|
|
148
146
|
|
|
149
|
-
await Promise.all(
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
147
|
+
await Promise.all(
|
|
148
|
+
Array.from({ length: concurrency }).map((_, index) =>
|
|
149
|
+
runWorker({
|
|
150
|
+
deadlineMs,
|
|
151
|
+
workerIndex: index,
|
|
152
|
+
stats,
|
|
153
|
+
}),
|
|
154
|
+
),
|
|
155
|
+
);
|
|
154
156
|
|
|
155
157
|
const elapsedSeconds = Math.max(0.001, (Date.now() - startedAt) / 1000);
|
|
156
158
|
const sortedLatencies = [...stats.latencies].sort((a, b) => a - b);
|
|
@@ -4,10 +4,7 @@ import 'dotenv/config';
|
|
|
4
4
|
import logger from '../app/utils/logger/loggerModule.js';
|
|
5
5
|
import initializeDatabase from '../database/init.js';
|
|
6
6
|
import { closePool } from '../database/index.js';
|
|
7
|
-
import {
|
|
8
|
-
isSupportedStickerWorkerTaskType,
|
|
9
|
-
startDedicatedStickerWorker,
|
|
10
|
-
} from '../app/modules/stickerPackModule/stickerDedicatedTaskWorkerRuntime.js';
|
|
7
|
+
import { isSupportedStickerWorkerTaskType, startDedicatedStickerWorker } from '../app/modules/stickerPackModule/stickerDedicatedTaskWorkerRuntime.js';
|
|
11
8
|
|
|
12
9
|
const parseCliArgs = (argv = []) => {
|
|
13
10
|
const args = new Map();
|
|
@@ -15,7 +15,9 @@ const START_MARKER = '<!-- README_SNAPSHOT:START -->';
|
|
|
15
15
|
const END_MARKER = '<!-- README_SNAPSHOT:END -->';
|
|
16
16
|
|
|
17
17
|
const readmePath = path.resolve(projectRoot, process.env.README_SNAPSHOT_TARGET_PATH || 'README.md');
|
|
18
|
-
const siteOrigin = String(process.env.SITE_ORIGIN || 'https://omnizap.shop')
|
|
18
|
+
const siteOrigin = String(process.env.SITE_ORIGIN || 'https://omnizap.shop')
|
|
19
|
+
.trim()
|
|
20
|
+
.replace(/\/+$/, '');
|
|
19
21
|
const sourceUrl = String(process.env.README_SNAPSHOT_SOURCE_URL || `${siteOrigin}/api/sticker-packs/readme-markdown`).trim();
|
|
20
22
|
const timeoutMs = Math.max(1000, Number(process.env.README_SNAPSHOT_TIMEOUT_MS) || 15000);
|
|
21
23
|
|
|
@@ -68,4 +70,3 @@ syncReadmeSnapshot().catch((error) => {
|
|
|
68
70
|
console.error(`[readme-sync] Falha: ${error?.message || error}`);
|
|
69
71
|
process.exit(1);
|
|
70
72
|
});
|
|
71
|
-
|
|
@@ -3033,11 +3033,7 @@ const renderCatalogHtml = async ({ initialPackKey }) => {
|
|
|
3033
3033
|
|
|
3034
3034
|
const renderPackSeoHtml = ({ packSummary }) => {
|
|
3035
3035
|
const packName = truncateText(packSummary?.name || packSummary?.pack_key || 'Pack', 95);
|
|
3036
|
-
const packDescription = truncateText(
|
|
3037
|
-
packSummary?.description
|
|
3038
|
-
|| `Pack de stickers "${packName}" disponível no catálogo OmniZap para uso em bots e automações WhatsApp via API.`,
|
|
3039
|
-
180,
|
|
3040
|
-
);
|
|
3036
|
+
const packDescription = truncateText(packSummary?.description || `Pack de stickers "${packName}" disponível no catálogo OmniZap para uso em bots e automações WhatsApp via API.`, 180);
|
|
3041
3037
|
const canonicalUrl = toSiteAbsoluteUrl(buildPackWebUrl(packSummary?.pack_key || ''));
|
|
3042
3038
|
const catalogUrl = toSiteAbsoluteUrl(`${STICKER_WEB_PATH}/`);
|
|
3043
3039
|
const homeUrl = toSiteAbsoluteUrl('/');
|
|
@@ -3648,6 +3644,71 @@ const handleMarketplaceStatsRequest = async (req, res, url) => {
|
|
|
3648
3644
|
}
|
|
3649
3645
|
};
|
|
3650
3646
|
|
|
3647
|
+
const handleHomeBootstrapRequest = async (req, res, url) => {
|
|
3648
|
+
const visibility = normalizeCatalogVisibility(url?.searchParams?.get('visibility'));
|
|
3649
|
+
const fetchTimeoutMs = {
|
|
3650
|
+
support: 450,
|
|
3651
|
+
session: 450,
|
|
3652
|
+
stats: 700,
|
|
3653
|
+
system_summary: 700,
|
|
3654
|
+
};
|
|
3655
|
+
const errors = [];
|
|
3656
|
+
|
|
3657
|
+
const [supportResult, sessionResult, statsResult, systemSummaryResult] = await Promise.allSettled([withTimeout(buildSupportInfo(), fetchTimeoutMs.support), STICKER_WEB_GOOGLE_CLIENT_ID ? withTimeout(resolveGoogleWebSessionFromRequest(req), fetchTimeoutMs.session) : Promise.resolve(null), withTimeout(getMarketplaceStatsCached(visibility), fetchTimeoutMs.stats), withTimeout(getSystemSummaryCached(), fetchTimeoutMs.system_summary)]);
|
|
3658
|
+
|
|
3659
|
+
const support = supportResult.status === 'fulfilled' ? supportResult.value || null : null;
|
|
3660
|
+
if (supportResult.status !== 'fulfilled') {
|
|
3661
|
+
errors.push({
|
|
3662
|
+
source: 'support',
|
|
3663
|
+
message: supportResult.reason?.message || 'support_unavailable',
|
|
3664
|
+
});
|
|
3665
|
+
}
|
|
3666
|
+
|
|
3667
|
+
const session = sessionResult.status === 'fulfilled' ? sessionResult.value || null : null;
|
|
3668
|
+
if (sessionResult.status !== 'fulfilled') {
|
|
3669
|
+
errors.push({
|
|
3670
|
+
source: 'session',
|
|
3671
|
+
message: sessionResult.reason?.message || 'session_unavailable',
|
|
3672
|
+
});
|
|
3673
|
+
}
|
|
3674
|
+
|
|
3675
|
+
const statsPayload = statsResult.status === 'fulfilled' ? statsResult.value || null : null;
|
|
3676
|
+
if (statsResult.status !== 'fulfilled') {
|
|
3677
|
+
errors.push({
|
|
3678
|
+
source: 'stats',
|
|
3679
|
+
message: statsResult.reason?.message || 'stats_unavailable',
|
|
3680
|
+
});
|
|
3681
|
+
}
|
|
3682
|
+
|
|
3683
|
+
const systemSummaryPayload = systemSummaryResult.status === 'fulfilled' ? systemSummaryResult.value || null : null;
|
|
3684
|
+
if (systemSummaryResult.status !== 'fulfilled') {
|
|
3685
|
+
errors.push({
|
|
3686
|
+
source: 'system_summary',
|
|
3687
|
+
message: systemSummaryResult.reason?.message || 'system_summary_unavailable',
|
|
3688
|
+
});
|
|
3689
|
+
}
|
|
3690
|
+
|
|
3691
|
+
sendJson(req, res, 200, {
|
|
3692
|
+
data: {
|
|
3693
|
+
support,
|
|
3694
|
+
session: mapGoogleSessionResponseData(session),
|
|
3695
|
+
stats: statsPayload?.data || null,
|
|
3696
|
+
stats_filters: statsPayload?.filters || null,
|
|
3697
|
+
system_summary: systemSummaryPayload?.data || null,
|
|
3698
|
+
},
|
|
3699
|
+
meta: {
|
|
3700
|
+
visibility,
|
|
3701
|
+
cache_seconds: {
|
|
3702
|
+
stats: HOME_MARKETPLACE_STATS_CACHE_SECONDS,
|
|
3703
|
+
system_summary: SYSTEM_SUMMARY_CACHE_SECONDS,
|
|
3704
|
+
},
|
|
3705
|
+
timeouts_ms: fetchTimeoutMs,
|
|
3706
|
+
partial: errors.length > 0,
|
|
3707
|
+
errors,
|
|
3708
|
+
},
|
|
3709
|
+
});
|
|
3710
|
+
};
|
|
3711
|
+
|
|
3651
3712
|
const handleCreatePackConfigRequest = async (req, res) => {
|
|
3652
3713
|
triggerStaleDraftCleanup();
|
|
3653
3714
|
sendJson(req, res, 200, {
|
|
@@ -7624,6 +7685,7 @@ const catalogApiRouter = createCatalogApiRouter({
|
|
|
7624
7685
|
handleCreatorRankingRequest,
|
|
7625
7686
|
handleRecommendationsRequest,
|
|
7626
7687
|
handleMarketplaceStatsRequest,
|
|
7688
|
+
handleHomeBootstrapRequest,
|
|
7627
7689
|
handleCreatePackConfigRequest,
|
|
7628
7690
|
handleOrphanStickerListRequest,
|
|
7629
7691
|
handleDataFileListRequest,
|
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
import http from 'node:http';
|
|
2
2
|
import logger from '../../app/utils/logger/loggerModule.js';
|
|
3
|
-
import {
|
|
4
|
-
getMetricsServerConfig,
|
|
5
|
-
isMetricsEnabled,
|
|
6
|
-
recordHttpRequest,
|
|
7
|
-
resolveRouteGroup,
|
|
8
|
-
} from '../../app/observability/metrics.js';
|
|
3
|
+
import { getMetricsServerConfig, isMetricsEnabled, recordHttpRequest, resolveRouteGroup } from '../../app/observability/metrics.js';
|
|
9
4
|
import { parseRequestUrl, normalizeRequestId } from './requestContext.js';
|
|
10
5
|
import { maybeHandleMetricsRoute } from '../routes/metricsRoute.js';
|
|
11
|
-
import {
|
|
12
|
-
getStickerCatalogRouteConfig,
|
|
13
|
-
maybeHandleStickerCatalogRoute,
|
|
14
|
-
} from '../routes/stickerCatalogRoute.js';
|
|
6
|
+
import { getStickerCatalogRouteConfig, maybeHandleStickerCatalogRoute } from '../routes/stickerCatalogRoute.js';
|
|
15
7
|
|
|
16
8
|
let server = null;
|
|
17
9
|
let serverStarted = false;
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
export const handleCatalogAdminRoutes = async ({
|
|
2
|
-
req,
|
|
3
|
-
res,
|
|
4
|
-
url,
|
|
5
|
-
segments,
|
|
6
|
-
handlers,
|
|
7
|
-
sendJson,
|
|
8
|
-
}) => {
|
|
1
|
+
export const handleCatalogAdminRoutes = async ({ req, res, url, segments, handlers, sendJson }) => {
|
|
9
2
|
if (segments[0] !== 'admin') return false;
|
|
10
3
|
|
|
11
4
|
if (segments.length === 2 && segments[1] === 'overview') {
|
|
@@ -2,15 +2,7 @@ const METHOD_NOT_ALLOWED_BODY = { error: 'Metodo nao permitido.' };
|
|
|
2
2
|
|
|
3
3
|
const isReadMethod = (method) => method === 'GET' || method === 'HEAD';
|
|
4
4
|
|
|
5
|
-
export const handleCatalogAuthRoutes = async ({
|
|
6
|
-
req,
|
|
7
|
-
res,
|
|
8
|
-
pathname,
|
|
9
|
-
url,
|
|
10
|
-
apiBasePath,
|
|
11
|
-
handlers,
|
|
12
|
-
sendJson,
|
|
13
|
-
}) => {
|
|
5
|
+
export const handleCatalogAuthRoutes = async ({ req, res, pathname, url, apiBasePath, handlers, sendJson }) => {
|
|
14
6
|
if (pathname === `${apiBasePath}/auth/google/session`) {
|
|
15
7
|
await handlers.handleGoogleAuthSessionRequest(req, res);
|
|
16
8
|
return true;
|
|
@@ -2,17 +2,7 @@ const METHOD_NOT_ALLOWED_BODY = { error: 'Metodo nao permitido.' };
|
|
|
2
2
|
|
|
3
3
|
const isReadMethod = (method) => method === 'GET' || method === 'HEAD';
|
|
4
4
|
|
|
5
|
-
export const handleCatalogPublicRoutes = async ({
|
|
6
|
-
req,
|
|
7
|
-
res,
|
|
8
|
-
pathname,
|
|
9
|
-
url,
|
|
10
|
-
segments,
|
|
11
|
-
apiBasePath,
|
|
12
|
-
orphanApiPath,
|
|
13
|
-
handlers,
|
|
14
|
-
sendJson,
|
|
15
|
-
}) => {
|
|
5
|
+
export const handleCatalogPublicRoutes = async ({ req, res, pathname, url, segments, apiBasePath, orphanApiPath, handlers, sendJson }) => {
|
|
16
6
|
if (pathname === apiBasePath) {
|
|
17
7
|
if (!isReadMethod(req.method || '')) {
|
|
18
8
|
sendJson(req, res, 405, METHOD_NOT_ALLOWED_BODY);
|
|
@@ -58,6 +48,15 @@ export const handleCatalogPublicRoutes = async ({
|
|
|
58
48
|
return true;
|
|
59
49
|
}
|
|
60
50
|
|
|
51
|
+
if (pathname === `${apiBasePath}/home-bootstrap`) {
|
|
52
|
+
if (!isReadMethod(req.method || '')) {
|
|
53
|
+
sendJson(req, res, 405, METHOD_NOT_ALLOWED_BODY);
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
await handlers.handleHomeBootstrapRequest(req, res, url);
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
|
|
61
60
|
if (pathname === `${apiBasePath}/create-config`) {
|
|
62
61
|
if (!isReadMethod(req.method || '')) {
|
|
63
62
|
sendJson(req, res, 405, METHOD_NOT_ALLOWED_BODY);
|
|
@@ -2,16 +2,7 @@ const METHOD_NOT_ALLOWED_BODY = { error: 'Metodo nao permitido.' };
|
|
|
2
2
|
|
|
3
3
|
const isPublishStateMethod = (method) => method === 'GET' || method === 'HEAD' || method === 'POST';
|
|
4
4
|
|
|
5
|
-
export const handleCatalogUploadRoutes = async ({
|
|
6
|
-
req,
|
|
7
|
-
res,
|
|
8
|
-
pathname,
|
|
9
|
-
url,
|
|
10
|
-
segments,
|
|
11
|
-
apiBasePath,
|
|
12
|
-
handlers,
|
|
13
|
-
sendJson,
|
|
14
|
-
}) => {
|
|
5
|
+
export const handleCatalogUploadRoutes = async ({ req, res, pathname, url, segments, apiBasePath, handlers, sendJson }) => {
|
|
15
6
|
if (pathname === `${apiBasePath}/create`) {
|
|
16
7
|
if (req.method !== 'POST') {
|
|
17
8
|
sendJson(req, res, 405, METHOD_NOT_ALLOWED_BODY);
|
|
@@ -4,20 +4,18 @@ import { handleCatalogUploadRoutes } from './catalogHandlers/catalogUploadHttp.j
|
|
|
4
4
|
import { handleCatalogPublicRoutes } from './catalogHandlers/catalogPublicHttp.js';
|
|
5
5
|
|
|
6
6
|
const decodePathSegments = (suffix) =>
|
|
7
|
-
suffix
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
suffix
|
|
8
|
+
.split('/')
|
|
9
|
+
.filter(Boolean)
|
|
10
|
+
.map((segment) => {
|
|
11
|
+
try {
|
|
12
|
+
return decodeURIComponent(segment);
|
|
13
|
+
} catch {
|
|
14
|
+
return segment;
|
|
15
|
+
}
|
|
16
|
+
});
|
|
14
17
|
|
|
15
|
-
export const createCatalogApiRouter = ({
|
|
16
|
-
apiBasePath,
|
|
17
|
-
orphanApiPath,
|
|
18
|
-
handlers,
|
|
19
|
-
sendJson,
|
|
20
|
-
}) => {
|
|
18
|
+
export const createCatalogApiRouter = ({ apiBasePath, orphanApiPath, handlers, sendJson }) => {
|
|
21
19
|
if (!apiBasePath || typeof handlers !== 'object' || typeof sendJson !== 'function') {
|
|
22
20
|
throw new Error('catalog_api_router_config_invalid');
|
|
23
21
|
}
|