@kaikybrofc/omnizap-system 2.3.1 → 2.3.3

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 (49) hide show
  1. package/README.md +82 -483
  2. package/app/controllers/messageController.js +473 -255
  3. package/app/modules/analyticsModule/messageAnalysisEventRepository.js +83 -0
  4. package/app/modules/stickerModule/stickerCommand.js +7 -2
  5. package/app/modules/stickerModule/stickerTextCommand.js +7 -2
  6. package/app/modules/stickerPackModule/stickerDomainEventConsumerRuntime.js +1 -3
  7. package/app/modules/stickerPackModule/stickerPackCommandHandlers.js +224 -53
  8. package/app/observability/metrics.js +6 -3
  9. package/app/services/googleWebLinkService.js +77 -0
  10. package/app/services/lidMapService.js +83 -4
  11. package/database/index.js +2 -0
  12. package/database/migrations/20260301_0028_message_analysis_event.sql +32 -0
  13. package/database/migrations/20260301_0029_admin_action_audit.sql +16 -0
  14. package/package.json +1 -1
  15. package/public/index.html +12 -8
  16. package/public/js/apps/createPackApp.js +4 -4
  17. package/public/js/apps/homeApp.js +78 -34
  18. package/public/js/apps/loginApp.js +245 -35
  19. package/public/js/apps/stickersAdminApp.js +4 -10
  20. package/public/js/apps/stickersApp.js +1 -1
  21. package/public/js/apps/userApp.js +956 -55
  22. package/public/js/apps/userProfileApp.js +244 -0
  23. package/public/login/index.html +437 -101
  24. package/public/termos-de-uso/index.html +1 -1
  25. package/public/user/index.html +2 -181
  26. package/public/user/systemadm/index.html +774 -0
  27. package/server/controllers/stickerCatalog/nonCatalogHandlers.js +183 -0
  28. package/server/controllers/stickerCatalogController.js +1289 -368
  29. package/server/controllers/systemAdminController.js +141 -0
  30. package/server/controllers/userController.js +87 -0
  31. package/server/http/httpServer.js +72 -32
  32. package/server/middleware/cachePolicy.js +24 -0
  33. package/server/middleware/cachePolicyHelpers.js +1 -0
  34. package/server/middleware/rateLimit.js +89 -0
  35. package/server/middleware/requestLogger.js +16 -0
  36. package/server/middleware/requireAdminAuth.js +42 -0
  37. package/server/middleware/securityHeaders.js +6 -0
  38. package/server/routes/admin/systemAdminRouter.js +56 -0
  39. package/server/routes/health/healthRouter.js +41 -0
  40. package/server/routes/indexRouter.js +197 -0
  41. package/server/routes/metrics/metricsRouter.js +13 -0
  42. package/server/routes/stickerCatalog/catalogHandlers/catalogAdminHttp.js +44 -0
  43. package/server/routes/stickerCatalog/stickerApiRouter.js +84 -0
  44. package/server/routes/stickerCatalog/stickerDataRouter.js +140 -0
  45. package/server/routes/stickerCatalog/stickerSiteRouter.js +43 -0
  46. package/server/routes/user/userRouter.js +56 -0
  47. package/server/utils/safePath.js +26 -0
  48. package/server/routes/metricsRoute.js +0 -7
  49. package/server/routes/stickerCatalogRoute.js +0 -20
@@ -0,0 +1,183 @@
1
+ export const createStickerCatalogNonCatalogHandlers = ({ sendJson, sendText, logger, getSystemSummaryCached, systemSummaryCache, systemSummaryCacheSeconds, getReadmeSummaryCached, readmeSummaryCache, readmeSummaryCacheSeconds, getGlobalRankingSummaryCached, globalRankRefreshSeconds, globalRankCache, sanitizeRankingPayloadByBot, getActiveSocket, resolveBotUserCandidates, getMarketplaceGlobalStatsCached, marketplaceGlobalStatsCacheSeconds, marketplaceGlobalStatsCache, githubRepoInfo, githubToken, githubProjectCacheSeconds, fetchGitHubProjectSummary, buildSupportInfo, buildBotContactInfo }) => {
2
+ const handleSystemSummaryRequest = async (req, res) => {
3
+ try {
4
+ const payload = await getSystemSummaryCached();
5
+ sendJson(req, res, 200, {
6
+ ...payload,
7
+ meta: {
8
+ ...(payload.meta || {}),
9
+ cache_seconds: systemSummaryCacheSeconds,
10
+ },
11
+ });
12
+ } catch (error) {
13
+ logger.warn('Falha ao montar resumo do sistema.', {
14
+ action: 'system_summary_error',
15
+ error: error?.message,
16
+ });
17
+ if (systemSummaryCache.value) {
18
+ sendJson(req, res, 200, {
19
+ ...systemSummaryCache.value,
20
+ meta: {
21
+ ...(systemSummaryCache.value.meta || {}),
22
+ cache_seconds: systemSummaryCacheSeconds,
23
+ stale: true,
24
+ error: error?.message || 'fallback_cache',
25
+ },
26
+ });
27
+ return;
28
+ }
29
+ sendJson(req, res, 503, { error: 'Resumo do sistema indisponível no momento.' });
30
+ }
31
+ };
32
+
33
+ const handleReadmeSummaryRequest = async (req, res) => {
34
+ try {
35
+ const payload = await getReadmeSummaryCached();
36
+ sendJson(req, res, 200, payload);
37
+ } catch (error) {
38
+ logger.warn('Falha ao montar resumo markdown para README.', {
39
+ action: 'readme_summary_error',
40
+ error: error?.message,
41
+ });
42
+ if (readmeSummaryCache.value) {
43
+ sendJson(req, res, 200, {
44
+ ...readmeSummaryCache.value,
45
+ meta: {
46
+ stale: true,
47
+ error: error?.message || 'fallback_cache',
48
+ },
49
+ });
50
+ return;
51
+ }
52
+ sendJson(req, res, 503, { error: 'Resumo markdown indisponível no momento.' });
53
+ }
54
+ };
55
+
56
+ const handleReadmeMarkdownRequest = async (req, res) => {
57
+ try {
58
+ const payload = await getReadmeSummaryCached();
59
+ const markdown = String(payload?.data?.markdown || '').trim();
60
+ res.setHeader('X-Robots-Tag', 'noindex, nofollow');
61
+ res.setHeader('Cache-Control', `public, max-age=${Math.min(readmeSummaryCacheSeconds, 300)}`);
62
+ res.setHeader('X-Cache-Seconds', String(readmeSummaryCacheSeconds));
63
+ sendText(req, res, 200, markdown ? `${markdown}\n` : '', 'text/markdown; charset=utf-8');
64
+ } catch (error) {
65
+ logger.warn('Falha ao renderizar markdown para README.', {
66
+ action: 'readme_markdown_error',
67
+ error: error?.message,
68
+ });
69
+ if (readmeSummaryCache.value) {
70
+ const markdown = String(readmeSummaryCache.value?.data?.markdown || '').trim();
71
+ res.setHeader('X-Robots-Tag', 'noindex, nofollow');
72
+ res.setHeader('Cache-Control', `public, max-age=${Math.min(readmeSummaryCacheSeconds, 300)}`);
73
+ res.setHeader('X-Cache-Seconds', String(readmeSummaryCacheSeconds));
74
+ sendText(req, res, 200, markdown ? `${markdown}\n` : '', 'text/markdown; charset=utf-8');
75
+ return;
76
+ }
77
+ sendText(req, res, 503, 'Resumo markdown indisponivel no momento.\n', 'text/plain; charset=utf-8');
78
+ }
79
+ };
80
+
81
+ const handleGlobalRankingSummaryRequest = async (req, res) => {
82
+ const activeSocket = getActiveSocket();
83
+ const botUsers = resolveBotUserCandidates(activeSocket);
84
+ try {
85
+ const rawData = await getGlobalRankingSummaryCached();
86
+ const data = sanitizeRankingPayloadByBot(rawData, botUsers);
87
+ sendJson(req, res, 200, { data, meta: { cache_seconds: globalRankRefreshSeconds } });
88
+ } catch (error) {
89
+ logger.warn('Falha ao montar resumo do ranking global.', {
90
+ action: 'global_ranking_summary_error',
91
+ error: error?.message,
92
+ });
93
+ if (globalRankCache.value) {
94
+ sendJson(req, res, 200, {
95
+ data: sanitizeRankingPayloadByBot(globalRankCache.value, botUsers),
96
+ meta: { cache_seconds: globalRankRefreshSeconds, stale: true, error: error?.message || 'fallback_cache' },
97
+ });
98
+ return;
99
+ }
100
+ sendJson(req, res, 503, { error: 'Ranking global indisponível no momento.' });
101
+ }
102
+ };
103
+
104
+ const handleMarketplaceGlobalStatsRequest = async (req, res) => {
105
+ try {
106
+ const data = await getMarketplaceGlobalStatsCached();
107
+ sendJson(req, res, 200, {
108
+ ...data,
109
+ cache_seconds: marketplaceGlobalStatsCacheSeconds,
110
+ });
111
+ } catch (error) {
112
+ logger.warn('Falha ao montar stats globais do marketplace.', {
113
+ action: 'marketplace_global_stats_error',
114
+ error: error?.message,
115
+ });
116
+ if (marketplaceGlobalStatsCache.value) {
117
+ sendJson(req, res, 200, {
118
+ ...marketplaceGlobalStatsCache.value,
119
+ cache_seconds: marketplaceGlobalStatsCacheSeconds,
120
+ stale: true,
121
+ });
122
+ return;
123
+ }
124
+ sendJson(req, res, 503, { error: 'Stats globais do marketplace indisponíveis no momento.' });
125
+ }
126
+ };
127
+
128
+ const handleGitHubProjectSummaryRequest = async (req, res) => {
129
+ if (!githubRepoInfo) {
130
+ sendJson(req, res, 500, { error: 'Configuracao de repositorio GitHub invalida.' });
131
+ return;
132
+ }
133
+
134
+ try {
135
+ const data = await fetchGitHubProjectSummary();
136
+ sendJson(req, res, 200, {
137
+ data,
138
+ meta: {
139
+ repository: githubRepoInfo.fullName,
140
+ token_configured: Boolean(githubToken),
141
+ cache_seconds: githubProjectCacheSeconds,
142
+ },
143
+ });
144
+ } catch (error) {
145
+ logger.warn('Falha ao consultar resumo do repositorio no GitHub.', {
146
+ action: 'github_project_summary_error',
147
+ repository: githubRepoInfo.fullName,
148
+ error: error?.message,
149
+ status_code: error?.statusCode || null,
150
+ });
151
+ sendJson(req, res, 502, { error: 'Falha ao consultar dados do projeto no GitHub.' });
152
+ }
153
+ };
154
+
155
+ const handleSupportInfoRequest = async (req, res) => {
156
+ const data = await buildSupportInfo();
157
+ if (!data) {
158
+ sendJson(req, res, 404, { error: 'Contato de suporte indisponível.' });
159
+ return;
160
+ }
161
+ sendJson(req, res, 200, { data });
162
+ };
163
+
164
+ const handleBotContactInfoRequest = async (req, res) => {
165
+ const data = buildBotContactInfo();
166
+ if (!data) {
167
+ sendJson(req, res, 404, { error: 'Contato do bot indisponivel no momento.' });
168
+ return;
169
+ }
170
+ sendJson(req, res, 200, { data });
171
+ };
172
+
173
+ return {
174
+ handleSystemSummaryRequest,
175
+ handleReadmeSummaryRequest,
176
+ handleReadmeMarkdownRequest,
177
+ handleGlobalRankingSummaryRequest,
178
+ handleMarketplaceGlobalStatsRequest,
179
+ handleGitHubProjectSummaryRequest,
180
+ handleSupportInfoRequest,
181
+ handleBotContactInfoRequest,
182
+ };
183
+ };