@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
@@ -1,371 +1,548 @@
1
1
  <!doctype html>
2
2
  <html lang="pt-BR">
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1" />
6
- <title>OmniZap System | Minha Conta</title>
7
- <meta name="description" content="Painel de conta do OmniZap System com dados do usuário vinculado ao WhatsApp." />
8
- <meta name="robots" content="noindex, nofollow" />
9
- <meta name="theme-color" content="#0f172a" />
10
- <link rel="canonical" href="https://omnizap.shop/user/" />
11
- <link rel="icon" type="image/jpeg" href="https://iili.io/FC3FABe.jpg" />
12
- <link rel="preconnect" href="https://fonts.googleapis.com" />
13
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
14
- <link
15
- href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&family=Sora:wght@500;600;700&display=swap"
16
- rel="stylesheet"
17
- />
18
- <style>
19
- :root {
20
- --bg: #0f172a;
21
- --bg-2: #111827;
22
- --card: #1e293bcf;
23
- --line: rgba(255, 255, 255, 0.05);
24
- --text: #f8fafc;
25
- --muted: #94a3b8;
26
- --primary: #22c55e;
27
- --radius: 18px;
28
- }
29
-
30
- * {
31
- box-sizing: border-box;
32
- }
33
-
34
- html,
35
- body {
36
- margin: 0;
37
- padding: 0;
38
- min-height: 100%;
39
- }
40
-
41
- body {
42
- color: var(--text);
43
- font-family: "Manrope", system-ui, sans-serif;
44
- background:
45
- radial-gradient(55rem 22rem at -10% -10%, #2563eb30, transparent 60%),
46
- radial-gradient(55rem 22rem at 110% -8%, #7c3aed22, transparent 56%),
47
- linear-gradient(160deg, var(--bg), var(--bg-2));
48
- min-height: 100vh;
49
- display: flex;
50
- align-items: center;
51
- justify-content: center;
52
- padding: 24px 14px;
53
- }
54
-
55
- .page {
56
- width: min(840px, 100%);
57
- border: 1px solid rgba(255, 255, 255, 0.05);
58
- border-radius: 24px;
59
- background: linear-gradient(150deg, #111827e8, #1e293bee);
60
- box-shadow: 0 18px 44px #0209166e, inset 0 1px 0 #95c1ff1a;
61
- overflow: hidden;
62
- }
63
-
64
- .head {
65
- border-bottom: 1px solid rgba(255, 255, 255, 0.05);
66
- padding: 20px 22px;
67
- display: flex;
68
- align-items: center;
69
- justify-content: space-between;
70
- gap: 14px;
71
- flex-wrap: wrap;
72
- }
73
-
74
- .brand {
75
- display: inline-flex;
76
- align-items: center;
77
- gap: 10px;
78
- font-family: "Sora", sans-serif;
79
- font-weight: 700;
80
- letter-spacing: 0.2px;
81
- text-decoration: none;
82
- color: var(--text);
83
- }
84
-
85
- .brand img {
86
- width: 30px;
87
- height: 30px;
88
- border-radius: 50%;
89
- border: 1px solid rgba(255, 255, 255, 0.05);
90
- object-fit: cover;
91
- }
92
-
93
- .head-actions {
94
- display: flex;
95
- flex-wrap: wrap;
96
- gap: 8px;
97
- }
98
-
99
- .btn {
100
- border: 1px solid var(--line);
101
- border-radius: 12px;
102
- background: #101a2f;
103
- color: var(--text);
104
- text-decoration: none;
105
- padding: 9px 12px;
106
- font-size: 14px;
107
- font-weight: 600;
108
- transition: transform .2s ease, border-color .2s ease, box-shadow .2s ease;
109
- cursor: pointer;
110
- }
111
-
112
- .btn:hover {
113
- transform: translateY(-1px);
114
- border-color: #2563eb;
115
- box-shadow: 0 10px 20px #02091650;
116
- }
117
-
118
- .btn.primary {
119
- border-color: transparent;
120
- background: #22c55e;
121
- color: #0f172a;
122
- box-shadow: 0 10px 22px #22c55e30;
123
- }
124
-
125
- .btn.primary:hover {
126
- background: #16a34a;
127
- }
128
-
129
- .content {
130
- padding: 24px 22px;
131
- display: grid;
132
- gap: 14px;
133
- }
134
-
135
- h1 {
136
- margin: 0;
137
- font-family: "Sora", sans-serif;
138
- font-size: clamp(26px, 3.6vw, 36px);
139
- line-height: 1.08;
140
- letter-spacing: -0.02em;
141
- background: linear-gradient(90deg, #eef5ff 0%, #60a5fa 46%, #a78bfa 100%);
142
- -webkit-background-clip: text;
143
- background-clip: text;
144
- color: transparent;
145
- }
146
-
147
- .lead {
148
- margin: 0;
149
- color: #bfd1ea;
150
- line-height: 1.6;
151
- font-size: 16px;
152
- }
153
-
154
- .card {
155
- border: 1px solid #334f7bc7;
156
- border-radius: var(--radius);
157
- background: var(--card);
158
- padding: 16px;
159
- display: grid;
160
- gap: 12px;
161
- backdrop-filter: blur(8px);
162
- }
163
-
164
- .status {
165
- margin: 0;
166
- color: #dce8fa;
167
- font-size: 15px;
168
- line-height: 1.5;
169
- }
170
-
171
- .error {
172
- margin: 0;
173
- border: 1px solid #a74949;
174
- border-radius: 12px;
175
- background: #3b181899;
176
- color: #ffd7d7;
177
- padding: 9px 10px;
178
- font-size: 14px;
179
- }
180
-
181
- .profile {
182
- display: grid;
183
- grid-template-columns: auto 1fr;
184
- gap: 12px;
185
- align-items: center;
186
- border: 1px solid #31517fb5;
187
- border-radius: 14px;
188
- background: #1e293bbf;
189
- padding: 12px;
190
- }
191
-
192
- .avatar {
193
- width: 66px;
194
- height: 66px;
195
- border-radius: 16px;
196
- border: 1px solid #3c5a89;
197
- object-fit: cover;
198
- background: #0b1323;
199
- }
200
-
201
- .profile-meta h2 {
202
- margin: 0 0 4px;
203
- font-size: 20px;
204
- line-height: 1.2;
205
- }
206
-
207
- .profile-meta p {
208
- margin: 0;
209
- color: var(--muted);
210
- font-size: 14px;
211
- line-height: 1.45;
212
- word-break: break-word;
213
- }
214
-
215
- .grid {
216
- display: grid;
217
- grid-template-columns: repeat(4, minmax(0, 1fr));
218
- gap: 8px;
219
- }
220
-
221
- .metric {
222
- border: 1px solid #31517fb5;
223
- border-radius: 12px;
224
- background: #1e293bbf;
225
- padding: 10px;
226
- }
227
-
228
- .metric-label {
229
- margin: 0 0 4px;
230
- color: #94a3b8;
231
- font-size: 12px;
232
- }
233
-
234
- .metric-value {
235
- margin: 0;
236
- color: #e8f1ff;
237
- font-size: 19px;
238
- font-weight: 800;
239
- letter-spacing: -0.01em;
240
- }
241
-
242
- .summary {
243
- border: 1px solid #2b8b5d9c;
244
- border-radius: 12px;
245
- background: #11302294;
246
- padding: 10px;
247
- display: grid;
248
- gap: 6px;
249
- color: #dfffe8;
250
- font-size: 14px;
251
- }
252
-
253
- .summary strong {
254
- color: #f4fff8;
255
- }
256
-
257
- .actions {
258
- display: flex;
259
- flex-wrap: wrap;
260
- gap: 8px;
261
- }
262
-
263
- .footer {
264
- margin: 0;
265
- color: #7f94b8;
266
- font-size: 12px;
267
- }
268
-
269
- @media (max-width: 760px) {
270
- .grid {
271
- grid-template-columns: repeat(2, minmax(0, 1fr));
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>OmniZap System | Minha Conta</title>
7
+ <meta name="description" content="Painel de conta do OmniZap System com dados do usuário vinculado ao WhatsApp." />
8
+ <meta name="robots" content="noindex, nofollow" />
9
+ <meta name="theme-color" content="#0f172a" />
10
+ <link rel="canonical" href="https://omnizap.shop/user/" />
11
+ <link rel="icon" type="image/jpeg" href="https://iili.io/FC3FABe.jpg" />
12
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
13
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
14
+ <link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&family=Sora:wght@500;600;700&display=swap" rel="stylesheet" />
15
+ <style>
16
+ :root {
17
+ --bg: #0f172a;
18
+ --bg-2: #111827;
19
+ --card: #1e293bcf;
20
+ --line: rgba(255, 255, 255, 0.05);
21
+ --text: #f8fafc;
22
+ --muted: #94a3b8;
23
+ --primary: #22c55e;
24
+ --radius: 18px;
25
+ }
26
+
27
+ * {
28
+ box-sizing: border-box;
29
+ }
30
+
31
+ html,
32
+ body {
33
+ margin: 0;
34
+ padding: 0;
35
+ min-height: 100%;
36
+ }
37
+
38
+ body {
39
+ color: var(--text);
40
+ font-family: 'Manrope', system-ui, sans-serif;
41
+ background: radial-gradient(55rem 22rem at -10% -10%, #2563eb30, transparent 60%), radial-gradient(55rem 22rem at 110% -8%, #7c3aed22, transparent 56%), linear-gradient(160deg, var(--bg), var(--bg-2));
42
+ min-height: 100vh;
43
+ display: flex;
44
+ align-items: center;
45
+ justify-content: center;
46
+ padding: 24px 14px;
47
+ }
48
+
49
+ .page {
50
+ width: min(840px, 100%);
51
+ border: 1px solid rgba(255, 255, 255, 0.05);
52
+ border-radius: 24px;
53
+ background: linear-gradient(150deg, #111827e8, #1e293bee);
54
+ box-shadow:
55
+ 0 18px 44px #0209166e,
56
+ inset 0 1px 0 #95c1ff1a;
57
+ overflow: hidden;
272
58
  }
273
- }
274
59
 
275
- @media (max-width: 620px) {
276
60
  .head {
277
- padding: 16px;
61
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
62
+ padding: 20px 22px;
63
+ display: flex;
64
+ align-items: center;
65
+ justify-content: space-between;
66
+ gap: 14px;
67
+ flex-wrap: wrap;
68
+ }
69
+
70
+ .brand {
71
+ display: inline-flex;
72
+ align-items: center;
73
+ gap: 10px;
74
+ font-family: 'Sora', sans-serif;
75
+ font-weight: 700;
76
+ letter-spacing: 0.2px;
77
+ text-decoration: none;
78
+ color: var(--text);
79
+ }
80
+
81
+ .brand img {
82
+ width: 30px;
83
+ height: 30px;
84
+ border-radius: 50%;
85
+ border: 1px solid rgba(255, 255, 255, 0.05);
86
+ object-fit: cover;
87
+ }
88
+
89
+ .head-actions {
90
+ display: flex;
91
+ flex-wrap: wrap;
92
+ gap: 8px;
93
+ }
94
+
95
+ .btn {
96
+ border: 1px solid var(--line);
97
+ border-radius: 12px;
98
+ background: #101a2f;
99
+ color: var(--text);
100
+ text-decoration: none;
101
+ padding: 9px 12px;
102
+ font-size: 14px;
103
+ font-weight: 600;
104
+ transition:
105
+ transform 0.2s ease,
106
+ border-color 0.2s ease,
107
+ box-shadow 0.2s ease;
108
+ cursor: pointer;
109
+ }
110
+
111
+ .btn:hover {
112
+ transform: translateY(-1px);
113
+ border-color: #2563eb;
114
+ box-shadow: 0 10px 20px #02091650;
115
+ }
116
+
117
+ .btn.primary {
118
+ border-color: transparent;
119
+ background: #22c55e;
120
+ color: #0f172a;
121
+ box-shadow: 0 10px 22px #22c55e30;
122
+ }
123
+
124
+ .btn.primary:hover {
125
+ background: #16a34a;
278
126
  }
279
127
 
280
128
  .content {
281
- padding: 18px 16px;
129
+ padding: 24px 22px;
130
+ display: grid;
131
+ gap: 14px;
132
+ }
133
+
134
+ h1 {
135
+ margin: 0;
136
+ font-family: 'Sora', sans-serif;
137
+ font-size: clamp(26px, 3.6vw, 36px);
138
+ line-height: 1.08;
139
+ letter-spacing: -0.02em;
140
+ background: linear-gradient(90deg, #eef5ff 0%, #60a5fa 46%, #a78bfa 100%);
141
+ -webkit-background-clip: text;
142
+ background-clip: text;
143
+ color: transparent;
144
+ }
145
+
146
+ .lead {
147
+ margin: 0;
148
+ color: #bfd1ea;
149
+ line-height: 1.6;
150
+ font-size: 16px;
151
+ }
152
+
153
+ .card {
154
+ border: 1px solid #334f7bc7;
155
+ border-radius: var(--radius);
156
+ background: var(--card);
157
+ padding: 16px;
158
+ display: grid;
159
+ gap: 12px;
160
+ backdrop-filter: blur(8px);
161
+ }
162
+
163
+ .status {
164
+ margin: 0;
165
+ color: #dce8fa;
166
+ font-size: 15px;
167
+ line-height: 1.5;
168
+ }
169
+
170
+ .error {
171
+ margin: 0;
172
+ border: 1px solid #a74949;
173
+ border-radius: 12px;
174
+ background: #3b181899;
175
+ color: #ffd7d7;
176
+ padding: 9px 10px;
177
+ font-size: 14px;
282
178
  }
283
179
 
284
180
  .profile {
285
- grid-template-columns: 1fr;
286
- text-align: center;
181
+ display: grid;
182
+ grid-template-columns: auto 1fr;
183
+ gap: 12px;
184
+ align-items: center;
185
+ border: 1px solid #31517fb5;
186
+ border-radius: 14px;
187
+ background: #1e293bbf;
188
+ padding: 12px;
287
189
  }
288
190
 
289
191
  .avatar {
290
- margin-inline: auto;
291
- }
292
-
293
- .actions .btn {
294
- width: 100%;
295
- text-align: center;
296
- }
297
- }
298
- </style>
299
- </head>
300
- <body>
301
- <main id="user-app-root" class="page" data-api-base-path="/api/sticker-packs" data-login-path="/login" data-stickers-path="/stickers">
302
- <header class="head">
303
- <a href="/" class="brand">
304
- <img src="https://iili.io/FC3FABe.jpg" alt="OmniZap" loading="lazy" decoding="async" />
305
- <span>OmniZap System</span>
306
- </a>
307
- <div class="head-actions">
308
- <a class="btn" href="/">Home</a>
309
- <a id="user-manage-head-link" class="btn" href="/stickers/perfil">Gerenciar Stickers</a>
310
- </div>
311
- </header>
312
-
313
- <section class="content">
314
- <h1>Minha Conta</h1>
315
- <p class="lead">Informações da sua conta vinculada ao OmniZap e atalhos rápidos de acesso.</p>
316
-
317
- <article class="card">
318
- <p id="user-status" class="status">Carregando dados da conta...</p>
319
- <p id="user-error" class="error" hidden></p>
320
-
321
- <div id="user-profile" class="profile" hidden>
322
- <img id="user-avatar" class="avatar" src="https://iili.io/FC3FABe.jpg" alt="Avatar do usuário" />
323
- <div class="profile-meta">
324
- <h2 id="user-name">Conta</h2>
325
- <p id="user-email"></p>
326
- <p id="user-whatsapp"></p>
327
- </div>
328
- </div>
192
+ width: 66px;
193
+ height: 66px;
194
+ border-radius: 16px;
195
+ border: 1px solid #3c5a89;
196
+ object-fit: cover;
197
+ background: #0b1323;
198
+ }
329
199
 
330
- <div id="user-grid" class="grid" hidden>
331
- <article class="metric">
332
- <p class="metric-label">Packs</p>
333
- <p id="metric-packs" class="metric-value">0</p>
334
- </article>
335
- <article class="metric">
336
- <p class="metric-label">Stickers</p>
337
- <p id="metric-stickers" class="metric-value">0</p>
338
- </article>
339
- <article class="metric">
340
- <p class="metric-label">Downloads</p>
341
- <p id="metric-downloads" class="metric-value">0</p>
342
- </article>
343
- <article class="metric">
344
- <p class="metric-label">Likes</p>
345
- <p id="metric-likes" class="metric-value">0</p>
346
- </article>
347
- </div>
200
+ .profile-meta h2 {
201
+ margin: 0 0 4px;
202
+ font-size: 20px;
203
+ line-height: 1.2;
204
+ }
348
205
 
349
- <div id="user-summary" class="summary" hidden>
350
- <div><strong>Owner JID:</strong> <span id="user-owner-jid"></span></div>
351
- <div><strong>Google ID:</strong> <span id="user-google-sub"></span></div>
352
- <div><strong>Sessão expira:</strong> <span id="user-expires-at"></span></div>
353
- </div>
206
+ .profile-meta p {
207
+ margin: 0;
208
+ color: var(--muted);
209
+ font-size: 14px;
210
+ line-height: 1.45;
211
+ word-break: break-word;
212
+ }
213
+
214
+ .grid {
215
+ display: grid;
216
+ grid-template-columns: repeat(4, minmax(0, 1fr));
217
+ gap: 8px;
218
+ }
354
219
 
355
- <div id="user-actions" class="actions" hidden>
356
- <a id="user-chat-link" class="btn primary" href="https://api.whatsapp.com/send/?text=%2Fmenu&type=custom_url&app_absent=0" target="_blank" rel="noreferrer noopener">
357
- Voltar ao chat do bot (/menu)
358
- </a>
359
- <a id="user-manage-main-link" class="btn" href="/stickers/perfil">Gerenciar meus stickers</a>
360
- <a class="btn" href="/">Voltar para Home</a>
361
- <button id="user-logout-btn" type="button" class="btn">Encerrar sessão</button>
220
+ .metric {
221
+ border: 1px solid #31517fb5;
222
+ border-radius: 12px;
223
+ background: #1e293bbf;
224
+ padding: 10px;
225
+ }
226
+
227
+ .metric-label {
228
+ margin: 0 0 4px;
229
+ color: #94a3b8;
230
+ font-size: 12px;
231
+ }
232
+
233
+ .metric-value {
234
+ margin: 0;
235
+ color: #e8f1ff;
236
+ font-size: 19px;
237
+ font-weight: 800;
238
+ letter-spacing: -0.01em;
239
+ }
240
+
241
+ .summary {
242
+ border: 1px solid #2b8b5d9c;
243
+ border-radius: 12px;
244
+ background: #11302294;
245
+ padding: 10px;
246
+ display: grid;
247
+ gap: 6px;
248
+ color: #dfffe8;
249
+ font-size: 14px;
250
+ }
251
+
252
+ .summary strong {
253
+ color: #f4fff8;
254
+ }
255
+
256
+ .admin-panel {
257
+ border: 1px solid #5b4a8f8f;
258
+ border-radius: 12px;
259
+ background: #1a1d3aa8;
260
+ padding: 12px;
261
+ display: grid;
262
+ gap: 10px;
263
+ }
264
+
265
+ .admin-headline {
266
+ display: flex;
267
+ align-items: center;
268
+ justify-content: space-between;
269
+ gap: 8px;
270
+ flex-wrap: wrap;
271
+ }
272
+
273
+ .admin-title {
274
+ margin: 0;
275
+ font-size: 17px;
276
+ color: #eef3ff;
277
+ }
278
+
279
+ .admin-role {
280
+ border: 1px solid #6f5cc2;
281
+ border-radius: 999px;
282
+ padding: 4px 10px;
283
+ font-size: 12px;
284
+ font-weight: 700;
285
+ color: #dad1ff;
286
+ background: #2a2155;
287
+ }
288
+
289
+ .admin-note {
290
+ margin: 0;
291
+ color: #d8d2ff;
292
+ font-size: 14px;
293
+ line-height: 1.45;
294
+ }
295
+
296
+ .admin-error {
297
+ margin: 0;
298
+ border: 1px solid #a74949;
299
+ border-radius: 10px;
300
+ background: #3b181899;
301
+ color: #ffd7d7;
302
+ padding: 8px 10px;
303
+ font-size: 13px;
304
+ }
305
+
306
+ .admin-form {
307
+ display: grid;
308
+ gap: 8px;
309
+ }
310
+
311
+ .admin-label {
312
+ color: #d8d2ff;
313
+ font-size: 13px;
314
+ font-weight: 600;
315
+ }
316
+
317
+ .admin-form-row {
318
+ display: grid;
319
+ grid-template-columns: 1fr auto;
320
+ gap: 8px;
321
+ }
322
+
323
+ .admin-input {
324
+ min-height: 40px;
325
+ border: 1px solid #4f4a77;
326
+ border-radius: 10px;
327
+ background: #11162f;
328
+ color: #f4f7ff;
329
+ font-size: 14px;
330
+ padding: 0 10px;
331
+ }
332
+
333
+ .admin-input:focus {
334
+ outline: none;
335
+ border-color: #7c6be0;
336
+ }
337
+
338
+ .admin-grid {
339
+ display: grid;
340
+ grid-template-columns: repeat(4, minmax(0, 1fr));
341
+ gap: 8px;
342
+ }
343
+
344
+ .admin-metric {
345
+ border: 1px solid #45409d7d;
346
+ border-radius: 10px;
347
+ background: #1a2044bf;
348
+ padding: 9px;
349
+ }
350
+
351
+ .admin-metric-label {
352
+ margin: 0 0 4px;
353
+ color: #b9b3e8;
354
+ font-size: 12px;
355
+ }
356
+
357
+ .admin-metric-value {
358
+ margin: 0;
359
+ color: #f4f6ff;
360
+ font-size: 17px;
361
+ font-weight: 800;
362
+ }
363
+
364
+ .admin-actions {
365
+ display: flex;
366
+ flex-wrap: wrap;
367
+ gap: 8px;
368
+ }
369
+
370
+ .actions {
371
+ display: flex;
372
+ flex-wrap: wrap;
373
+ gap: 8px;
374
+ }
375
+
376
+ .footer {
377
+ margin: 0;
378
+ color: #7f94b8;
379
+ font-size: 12px;
380
+ }
381
+
382
+ @media (max-width: 760px) {
383
+ .grid {
384
+ grid-template-columns: repeat(2, minmax(0, 1fr));
385
+ }
386
+
387
+ .admin-grid {
388
+ grid-template-columns: repeat(2, minmax(0, 1fr));
389
+ }
390
+ }
391
+
392
+ @media (max-width: 620px) {
393
+ .head {
394
+ padding: 16px;
395
+ }
396
+
397
+ .content {
398
+ padding: 18px 16px;
399
+ }
400
+
401
+ .profile {
402
+ grid-template-columns: 1fr;
403
+ text-align: center;
404
+ }
405
+
406
+ .avatar {
407
+ margin-inline: auto;
408
+ }
409
+
410
+ .actions .btn {
411
+ width: 100%;
412
+ text-align: center;
413
+ }
414
+
415
+ .admin-form-row {
416
+ grid-template-columns: 1fr;
417
+ }
418
+ }
419
+ </style>
420
+ </head>
421
+ <body>
422
+ <main id="user-app-root" class="page" data-api-base-path="/api/sticker-packs" data-login-path="/login" data-stickers-path="/stickers">
423
+ <header class="head">
424
+ <a href="/" class="brand">
425
+ <img src="https://iili.io/FC3FABe.jpg" alt="OmniZap" loading="lazy" decoding="async" />
426
+ <span>OmniZap System</span>
427
+ </a>
428
+ <div class="head-actions">
429
+ <a class="btn" href="/">Home</a>
430
+ <a id="user-manage-head-link" class="btn" href="/stickers/perfil">Gerenciar Stickers</a>
362
431
  </div>
363
- </article>
432
+ </header>
433
+
434
+ <section class="content">
435
+ <h1>Minha Conta</h1>
436
+ <p class="lead">Informações da sua conta vinculada ao OmniZap e atalhos rápidos de acesso.</p>
437
+
438
+ <article class="card">
439
+ <p id="user-status" class="status">Carregando dados da conta...</p>
440
+ <p id="user-error" class="error" hidden></p>
441
+
442
+ <div id="user-profile" class="profile" hidden>
443
+ <img id="user-avatar" class="avatar" src="https://iili.io/FC3FABe.jpg" alt="Avatar do usuário" />
444
+ <div class="profile-meta">
445
+ <h2 id="user-name">Conta</h2>
446
+ <p id="user-email"></p>
447
+ <p id="user-whatsapp"></p>
448
+ </div>
449
+ </div>
450
+
451
+ <div id="user-grid" class="grid" hidden>
452
+ <article class="metric">
453
+ <p class="metric-label">Packs</p>
454
+ <p id="metric-packs" class="metric-value">0</p>
455
+ </article>
456
+ <article class="metric">
457
+ <p class="metric-label">Stickers</p>
458
+ <p id="metric-stickers" class="metric-value">0</p>
459
+ </article>
460
+ <article class="metric">
461
+ <p class="metric-label">Downloads</p>
462
+ <p id="metric-downloads" class="metric-value">0</p>
463
+ </article>
464
+ <article class="metric">
465
+ <p class="metric-label">Likes</p>
466
+ <p id="metric-likes" class="metric-value">0</p>
467
+ </article>
468
+ </div>
469
+
470
+ <div id="user-summary" class="summary" hidden>
471
+ <div><strong>Owner JID:</strong> <span id="user-owner-jid"></span></div>
472
+ <div><strong>Google ID:</strong> <span id="user-google-sub"></span></div>
473
+ <div><strong>Sessão expira:</strong> <span id="user-expires-at"></span></div>
474
+ </div>
475
+
476
+ <section id="user-admin-panel" class="admin-panel" hidden>
477
+ <div class="admin-headline">
478
+ <h3 class="admin-title">Área Admin</h3>
479
+ <span id="user-admin-role" class="admin-role">admin</span>
480
+ </div>
481
+ <p id="user-admin-status" class="admin-note"></p>
482
+ <p id="user-admin-error" class="admin-error" hidden></p>
483
+
484
+ <form id="user-admin-unlock-form" class="admin-form" hidden>
485
+ <label for="user-admin-password" class="admin-label">Senha do painel admin</label>
486
+ <div class="admin-form-row">
487
+ <input id="user-admin-password" class="admin-input" type="password" autocomplete="current-password" placeholder="Digite sua senha" />
488
+ <button id="user-admin-unlock-btn" type="submit" class="btn">Desbloquear</button>
489
+ </div>
490
+ </form>
491
+
492
+ <div id="user-admin-overview" hidden>
493
+ <div class="admin-grid">
494
+ <article class="admin-metric">
495
+ <p class="admin-metric-label">Packs (total)</p>
496
+ <p id="user-admin-total-packs" class="admin-metric-value">0</p>
497
+ </article>
498
+ <article class="admin-metric">
499
+ <p class="admin-metric-label">Stickers (total)</p>
500
+ <p id="user-admin-total-stickers" class="admin-metric-value">0</p>
501
+ </article>
502
+ <article class="admin-metric">
503
+ <p class="admin-metric-label">Bans ativos</p>
504
+ <p id="user-admin-active-bans" class="admin-metric-value">0</p>
505
+ </article>
506
+ <article class="admin-metric">
507
+ <p class="admin-metric-label">Usuários Google</p>
508
+ <p id="user-admin-known-users" class="admin-metric-value">0</p>
509
+ </article>
510
+ <article class="admin-metric">
511
+ <p class="admin-metric-label">Sessões Google</p>
512
+ <p id="user-admin-active-sessions" class="admin-metric-value">0</p>
513
+ </article>
514
+ <article class="admin-metric">
515
+ <p class="admin-metric-label">Visitas 24h</p>
516
+ <p id="user-admin-visits-24h" class="admin-metric-value">0</p>
517
+ </article>
518
+ <article class="admin-metric">
519
+ <p class="admin-metric-label">Visitas 7d</p>
520
+ <p id="user-admin-visits-7d" class="admin-metric-value">0</p>
521
+ </article>
522
+ <article class="admin-metric">
523
+ <p class="admin-metric-label">Visitantes 7d</p>
524
+ <p id="user-admin-unique-visitors-7d" class="admin-metric-value">0</p>
525
+ </article>
526
+ </div>
527
+ <div class="admin-actions">
528
+ <button id="user-admin-refresh-btn" type="button" class="btn">Atualizar dados admin</button>
529
+ <button id="user-admin-logout-btn" type="button" class="btn">Sair do admin</button>
530
+ </div>
531
+ </div>
532
+ </section>
533
+
534
+ <div id="user-actions" class="actions" hidden>
535
+ <a id="user-chat-link" class="btn primary" href="https://api.whatsapp.com/send/?text=%2Fmenu&type=custom_url&app_absent=0" target="_blank" rel="noreferrer noopener"> Voltar ao chat do bot (/menu) </a>
536
+ <a id="user-manage-main-link" class="btn" href="/stickers/perfil">Gerenciar meus stickers</a>
537
+ <a class="btn" href="/">Voltar para Home</a>
538
+ <button id="user-logout-btn" type="button" class="btn">Encerrar sessão</button>
539
+ </div>
540
+ </article>
364
541
 
365
- <p class="footer">OmniZap System · <span id="user-current-year"></span></p>
366
- </section>
367
- </main>
542
+ <p class="footer">OmniZap System · <span id="user-current-year"></span></p>
543
+ </section>
544
+ </main>
368
545
 
369
- <script type="module" src="/js/apps/userApp.js?v=20260228-user-page-v1"></script>
370
- </body>
546
+ <script type="module" src="/js/apps/userApp.js?v=20260228-user-page-admin-merge-v1"></script>
547
+ </body>
371
548
  </html>