@kaikybrofc/omnizap-system 2.3.3 → 2.3.5
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 -22
- package/app/modules/stickerModule/stickerCommand.js +1 -6
- package/app/modules/stickerModule/stickerTextCommand.js +1 -6
- package/package.json +1 -1
- package/public/api-docs/index.html +3 -2
- package/public/apple-touch-icon.png +0 -0
- package/public/bot-whatsapp-para-grupo/index.html +3 -1
- package/public/bot-whatsapp-sem-programar/index.html +3 -1
- package/public/comandos/index.html +3 -2
- package/public/como-automatizar-avisos-no-whatsapp/index.html +3 -1
- package/public/como-criar-comandos-whatsapp/index.html +3 -1
- package/public/como-evitar-spam-no-whatsapp/index.html +3 -1
- package/public/como-moderar-grupo-whatsapp/index.html +3 -1
- package/public/como-organizar-comunidade-whatsapp/index.html +3 -1
- package/public/favicon-16x16.png +0 -0
- package/public/favicon-32x32.png +0 -0
- package/public/favicon.ico +0 -0
- package/public/index.html +11 -10
- package/public/js/apps/homeApp.js +22 -18
- package/public/js/apps/loginApp.js +3 -1
- package/public/js/apps/userProfileApp.js +0 -9
- package/public/licenca/index.html +3 -2
- package/public/login/index.html +3 -1
- package/public/melhor-bot-whatsapp-para-grupos/index.html +3 -1
- package/public/site.webmanifest +24 -0
- package/public/stickers/create/index.html +3 -1
- package/public/stickers/index.html +3 -1
- package/public/termos-de-uso/index.html +3 -2
- package/public/user/index.html +227 -121
- package/public/user/systemadm/index.html +3 -1
- package/server/controllers/admin/adminBanService.js +138 -0
- package/server/controllers/admin/adminPanelHandlers.js +1965 -0
- package/server/controllers/{systemAdminController.js → admin/systemAdminController.js} +2 -2
- package/server/controllers/{stickerCatalogController.js → sticker/stickerCatalogController.js} +129 -2116
- package/server/controllers/userController.js +1 -1
- package/server/routes/admin/systemAdminRouter.js +1 -1
- package/server/routes/indexRouter.js +3 -3
- package/server/routes/{stickerCatalog → sticker}/stickerApiRouter.js +1 -1
- package/server/routes/{stickerCatalog → sticker}/stickerDataRouter.js +1 -1
- package/server/routes/{stickerCatalog → sticker}/stickerSiteRouter.js +1 -1
- /package/server/controllers/{stickerCatalog → sticker}/nonCatalogHandlers.js +0 -0
- /package/server/routes/{stickerCatalog → sticker}/catalogHandlers/catalogAdminHttp.js +0 -0
- /package/server/routes/{stickerCatalog → sticker}/catalogHandlers/catalogAuthHttp.js +0 -0
- /package/server/routes/{stickerCatalog → sticker}/catalogHandlers/catalogPublicHttp.js +0 -0
- /package/server/routes/{stickerCatalog → sticker}/catalogHandlers/catalogUploadHttp.js +0 -0
- /package/server/routes/{stickerCatalog → sticker}/catalogRouter.js +0 -0
package/public/user/index.html
CHANGED
|
@@ -8,20 +8,29 @@
|
|
|
8
8
|
<meta name="robots" content="noindex, nofollow" />
|
|
9
9
|
<meta name="theme-color" content="#0f172a" />
|
|
10
10
|
<link rel="canonical" href="https://omnizap.shop/user/" />
|
|
11
|
-
<link rel="icon"
|
|
11
|
+
<link rel="icon" href="/favicon.ico" sizes="any" />
|
|
12
|
+
<link rel="manifest" href="/site.webmanifest" />
|
|
13
|
+
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
|
12
14
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
13
15
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
14
16
|
<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
17
|
<style>
|
|
16
18
|
:root {
|
|
17
|
-
--bg: #
|
|
18
|
-
--bg-2: #
|
|
19
|
-
--
|
|
20
|
-
--
|
|
21
|
-
--
|
|
22
|
-
--
|
|
23
|
-
--
|
|
24
|
-
--
|
|
19
|
+
--bg: #060d1a;
|
|
20
|
+
--bg-2: #0c1a31;
|
|
21
|
+
--bg-3: #102542;
|
|
22
|
+
--surface: #132340d6;
|
|
23
|
+
--surface-2: #152948f0;
|
|
24
|
+
--line: #8ab4ff2b;
|
|
25
|
+
--line-strong: #9fc4ff61;
|
|
26
|
+
--text: #f5f9ff;
|
|
27
|
+
--muted: #9eb2ce;
|
|
28
|
+
--primary: #1fd08b;
|
|
29
|
+
--accent: #5a8fff;
|
|
30
|
+
--danger: #ffb3b3;
|
|
31
|
+
--radius-xl: 26px;
|
|
32
|
+
--radius-lg: 18px;
|
|
33
|
+
--radius-md: 14px;
|
|
25
34
|
}
|
|
26
35
|
|
|
27
36
|
* {
|
|
@@ -38,33 +47,33 @@
|
|
|
38
47
|
body {
|
|
39
48
|
color: var(--text);
|
|
40
49
|
font-family: 'Manrope', system-ui, sans-serif;
|
|
41
|
-
background:
|
|
50
|
+
background:
|
|
51
|
+
radial-gradient(70rem 40rem at -12% -18%, #1d4ed855, transparent 62%),
|
|
52
|
+
radial-gradient(55rem 30rem at 108% -6%, #0ea5e941, transparent 66%),
|
|
53
|
+
linear-gradient(160deg, var(--bg), var(--bg-2) 52%, var(--bg-3));
|
|
42
54
|
min-height: 100vh;
|
|
43
|
-
|
|
44
|
-
align-items: center;
|
|
45
|
-
justify-content: center;
|
|
46
|
-
padding: 24px 14px;
|
|
55
|
+
padding: clamp(12px, 2.2vw, 28px);
|
|
47
56
|
}
|
|
48
57
|
|
|
49
58
|
.page {
|
|
50
|
-
width: min(
|
|
51
|
-
|
|
52
|
-
border
|
|
53
|
-
|
|
59
|
+
width: min(1080px, 100%);
|
|
60
|
+
margin-inline: auto;
|
|
61
|
+
border: 1px solid #8ab4ff1f;
|
|
62
|
+
border-radius: var(--radius-xl);
|
|
63
|
+
background: linear-gradient(145deg, #101d37ef 2%, #0f1b33f3 44%, #13294af2 100%);
|
|
54
64
|
box-shadow:
|
|
55
|
-
0
|
|
56
|
-
inset 0 1px 0 #
|
|
65
|
+
0 25px 70px #01091585,
|
|
66
|
+
inset 0 1px 0 #d3e4ff2e;
|
|
57
67
|
overflow: hidden;
|
|
58
68
|
}
|
|
59
69
|
|
|
60
70
|
.head {
|
|
61
|
-
border-bottom: 1px solid
|
|
62
|
-
padding:
|
|
63
|
-
display:
|
|
71
|
+
border-bottom: 1px solid var(--line);
|
|
72
|
+
padding: clamp(16px, 2.1vw, 24px);
|
|
73
|
+
display: grid;
|
|
74
|
+
grid-template-columns: 1fr auto;
|
|
75
|
+
gap: 12px 16px;
|
|
64
76
|
align-items: center;
|
|
65
|
-
justify-content: space-between;
|
|
66
|
-
gap: 14px;
|
|
67
|
-
flex-wrap: wrap;
|
|
68
77
|
}
|
|
69
78
|
|
|
70
79
|
.brand {
|
|
@@ -73,71 +82,93 @@
|
|
|
73
82
|
gap: 10px;
|
|
74
83
|
font-family: 'Sora', sans-serif;
|
|
75
84
|
font-weight: 700;
|
|
76
|
-
letter-spacing: 0.
|
|
85
|
+
letter-spacing: 0.03em;
|
|
77
86
|
text-decoration: none;
|
|
78
87
|
color: var(--text);
|
|
79
88
|
}
|
|
80
89
|
|
|
81
90
|
.brand img {
|
|
82
|
-
width:
|
|
83
|
-
height:
|
|
84
|
-
border-radius:
|
|
85
|
-
border: 1px solid
|
|
91
|
+
width: 34px;
|
|
92
|
+
height: 34px;
|
|
93
|
+
border-radius: 12px;
|
|
94
|
+
border: 1px solid var(--line);
|
|
86
95
|
object-fit: cover;
|
|
96
|
+
box-shadow: 0 10px 22px #0000004b;
|
|
87
97
|
}
|
|
88
98
|
|
|
89
99
|
.head-actions {
|
|
90
|
-
display:
|
|
91
|
-
|
|
100
|
+
display: grid;
|
|
101
|
+
grid-auto-flow: column;
|
|
102
|
+
grid-auto-columns: max-content;
|
|
92
103
|
gap: 8px;
|
|
93
104
|
}
|
|
94
105
|
|
|
95
106
|
.btn {
|
|
96
107
|
border: 1px solid var(--line);
|
|
97
108
|
border-radius: 12px;
|
|
98
|
-
background: #
|
|
109
|
+
background: #0e1b33;
|
|
99
110
|
color: var(--text);
|
|
100
111
|
text-decoration: none;
|
|
101
|
-
padding:
|
|
112
|
+
padding: 10px 14px;
|
|
102
113
|
font-size: 14px;
|
|
103
|
-
font-weight:
|
|
114
|
+
font-weight: 700;
|
|
115
|
+
line-height: 1.2;
|
|
116
|
+
text-align: center;
|
|
117
|
+
display: inline-flex;
|
|
118
|
+
justify-content: center;
|
|
119
|
+
align-items: center;
|
|
104
120
|
transition:
|
|
105
121
|
transform 0.2s ease,
|
|
106
122
|
border-color 0.2s ease,
|
|
107
|
-
box-shadow 0.2s ease
|
|
123
|
+
box-shadow 0.2s ease,
|
|
124
|
+
background-color 0.2s ease;
|
|
108
125
|
cursor: pointer;
|
|
109
126
|
}
|
|
110
127
|
|
|
111
128
|
.btn:hover {
|
|
112
129
|
transform: translateY(-1px);
|
|
113
|
-
border-color:
|
|
114
|
-
box-shadow: 0
|
|
130
|
+
border-color: var(--line-strong);
|
|
131
|
+
box-shadow: 0 12px 24px #01091557;
|
|
115
132
|
}
|
|
116
133
|
|
|
117
134
|
.btn.primary {
|
|
118
135
|
border-color: transparent;
|
|
119
|
-
background: #22c55e;
|
|
120
|
-
color: #
|
|
121
|
-
box-shadow: 0
|
|
136
|
+
background: linear-gradient(120deg, #1fd08b, #22c55e);
|
|
137
|
+
color: #072116;
|
|
138
|
+
box-shadow: 0 12px 24px #22c55e3d;
|
|
122
139
|
}
|
|
123
140
|
|
|
124
141
|
.btn.primary:hover {
|
|
125
|
-
background: #
|
|
142
|
+
background: linear-gradient(120deg, #2be09b, #33d46d);
|
|
126
143
|
}
|
|
127
144
|
|
|
128
145
|
.content {
|
|
129
|
-
padding:
|
|
146
|
+
padding: clamp(18px, 2.6vw, 30px);
|
|
147
|
+
display: grid;
|
|
148
|
+
gap: clamp(14px, 2vw, 22px);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.intro {
|
|
130
152
|
display: grid;
|
|
131
|
-
gap:
|
|
153
|
+
gap: 8px;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.eyebrow {
|
|
157
|
+
margin: 0;
|
|
158
|
+
font-family: 'Sora', sans-serif;
|
|
159
|
+
font-size: 12px;
|
|
160
|
+
letter-spacing: 0.16em;
|
|
161
|
+
text-transform: uppercase;
|
|
162
|
+
color: #95b8ff;
|
|
132
163
|
}
|
|
133
164
|
|
|
134
165
|
h1 {
|
|
135
166
|
margin: 0;
|
|
136
167
|
font-family: 'Sora', sans-serif;
|
|
137
|
-
font-size: clamp(
|
|
138
|
-
line-height: 1.
|
|
139
|
-
letter-spacing: -0.
|
|
140
|
-
background: linear-gradient(
|
|
168
|
+
font-size: clamp(28px, 4vw, 46px);
|
|
169
|
+
line-height: 1.05;
|
|
170
|
+
letter-spacing: -0.03em;
|
|
171
|
+
background: linear-gradient(100deg, #f6fbff 0%, #9bc5ff 52%, #77b4ff 100%);
|
|
141
172
|
-webkit-background-clip: text;
|
|
142
173
|
background-clip: text;
|
|
143
174
|
color: transparent;
|
|
@@ -145,141 +176,205 @@
|
|
|
145
176
|
|
|
146
177
|
.lead {
|
|
147
178
|
margin: 0;
|
|
148
|
-
color: #
|
|
179
|
+
color: #bfd3ef;
|
|
149
180
|
line-height: 1.6;
|
|
150
181
|
font-size: 16px;
|
|
182
|
+
max-width: 68ch;
|
|
151
183
|
}
|
|
152
184
|
|
|
153
185
|
.card {
|
|
154
|
-
border: 1px solid #
|
|
155
|
-
border-radius: var(--radius);
|
|
156
|
-
background: var(--
|
|
157
|
-
padding:
|
|
186
|
+
border: 1px solid #5d8dd23b;
|
|
187
|
+
border-radius: var(--radius-lg);
|
|
188
|
+
background: linear-gradient(150deg, var(--surface) 0%, var(--surface-2) 100%);
|
|
189
|
+
padding: clamp(14px, 2.2vw, 20px);
|
|
158
190
|
display: grid;
|
|
159
191
|
gap: 12px;
|
|
160
|
-
backdrop-filter: blur(
|
|
192
|
+
backdrop-filter: blur(9px);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.dashboard-card {
|
|
196
|
+
position: relative;
|
|
197
|
+
overflow: hidden;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.dashboard-card::before {
|
|
201
|
+
content: '';
|
|
202
|
+
position: absolute;
|
|
203
|
+
inset: 0;
|
|
204
|
+
pointer-events: none;
|
|
205
|
+
background: linear-gradient(160deg, #8fb3ff10 0%, transparent 36%, #1fd08b0f 100%);
|
|
161
206
|
}
|
|
162
207
|
|
|
163
208
|
.status {
|
|
209
|
+
position: relative;
|
|
164
210
|
margin: 0;
|
|
165
|
-
color: #
|
|
211
|
+
color: #e7f0ff;
|
|
166
212
|
font-size: 15px;
|
|
213
|
+
font-weight: 600;
|
|
167
214
|
line-height: 1.5;
|
|
215
|
+
padding: 12px 14px;
|
|
216
|
+
border: 1px solid #6d9de440;
|
|
217
|
+
border-radius: var(--radius-md);
|
|
218
|
+
background: #112647d1;
|
|
168
219
|
}
|
|
169
220
|
|
|
170
221
|
.error {
|
|
222
|
+
position: relative;
|
|
171
223
|
margin: 0;
|
|
172
|
-
border: 1px solid #
|
|
173
|
-
border-radius:
|
|
174
|
-
background: #
|
|
175
|
-
color:
|
|
176
|
-
padding:
|
|
224
|
+
border: 1px solid #ff8f8f87;
|
|
225
|
+
border-radius: var(--radius-md);
|
|
226
|
+
background: #3d1e2fb0;
|
|
227
|
+
color: var(--danger);
|
|
228
|
+
padding: 10px 12px;
|
|
177
229
|
font-size: 14px;
|
|
178
230
|
}
|
|
179
231
|
|
|
180
232
|
.profile {
|
|
233
|
+
position: relative;
|
|
181
234
|
display: grid;
|
|
182
235
|
grid-template-columns: auto 1fr;
|
|
183
|
-
gap: 12px;
|
|
236
|
+
gap: 12px 14px;
|
|
184
237
|
align-items: center;
|
|
185
|
-
border: 1px solid #
|
|
186
|
-
border-radius:
|
|
187
|
-
background: #
|
|
188
|
-
padding: 12px;
|
|
238
|
+
border: 1px solid #7facf249;
|
|
239
|
+
border-radius: var(--radius-md);
|
|
240
|
+
background: #0f1f38bf;
|
|
241
|
+
padding: clamp(12px, 1.8vw, 16px);
|
|
189
242
|
}
|
|
190
243
|
|
|
191
244
|
.avatar {
|
|
192
|
-
width:
|
|
193
|
-
height:
|
|
245
|
+
width: clamp(64px, 8vw, 82px);
|
|
246
|
+
height: clamp(64px, 8vw, 82px);
|
|
194
247
|
border-radius: 16px;
|
|
195
|
-
border: 1px solid #
|
|
248
|
+
border: 1px solid #7ca8e178;
|
|
196
249
|
object-fit: cover;
|
|
197
|
-
background: #
|
|
250
|
+
background: #0b1528;
|
|
251
|
+
box-shadow: 0 10px 24px #030b1961;
|
|
198
252
|
}
|
|
199
253
|
|
|
200
254
|
.profile-meta h2 {
|
|
201
|
-
margin: 0 0
|
|
202
|
-
font-size: 20px;
|
|
255
|
+
margin: 0 0 6px;
|
|
256
|
+
font-size: clamp(20px, 2.1vw, 26px);
|
|
203
257
|
line-height: 1.2;
|
|
258
|
+
letter-spacing: -0.02em;
|
|
204
259
|
}
|
|
205
260
|
|
|
206
261
|
.profile-meta p {
|
|
207
262
|
margin: 0;
|
|
208
263
|
color: var(--muted);
|
|
209
264
|
font-size: 14px;
|
|
210
|
-
line-height: 1.
|
|
265
|
+
line-height: 1.5;
|
|
211
266
|
word-break: break-word;
|
|
212
267
|
}
|
|
213
268
|
|
|
214
269
|
.grid {
|
|
270
|
+
position: relative;
|
|
215
271
|
display: grid;
|
|
216
|
-
grid-template-columns: repeat(
|
|
217
|
-
gap:
|
|
272
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
273
|
+
gap: 10px;
|
|
218
274
|
}
|
|
219
275
|
|
|
220
276
|
.metric {
|
|
221
|
-
border: 1px solid #
|
|
222
|
-
border-radius:
|
|
223
|
-
background: #
|
|
224
|
-
padding:
|
|
277
|
+
border: 1px solid #7facf242;
|
|
278
|
+
border-radius: var(--radius-md);
|
|
279
|
+
background: #0f1f39b8;
|
|
280
|
+
padding: 12px;
|
|
281
|
+
min-height: 94px;
|
|
282
|
+
display: grid;
|
|
283
|
+
align-content: space-between;
|
|
225
284
|
}
|
|
226
285
|
|
|
227
286
|
.metric-label {
|
|
228
|
-
margin: 0
|
|
229
|
-
color: #
|
|
287
|
+
margin: 0;
|
|
288
|
+
color: #9bb2d2;
|
|
230
289
|
font-size: 12px;
|
|
290
|
+
font-weight: 600;
|
|
291
|
+
letter-spacing: 0.05em;
|
|
292
|
+
text-transform: uppercase;
|
|
231
293
|
}
|
|
232
294
|
|
|
233
295
|
.metric-value {
|
|
234
|
-
margin: 0;
|
|
235
|
-
color: #
|
|
236
|
-
font-size:
|
|
296
|
+
margin: 6px 0 0;
|
|
297
|
+
color: #f1f7ff;
|
|
298
|
+
font-size: clamp(22px, 3vw, 28px);
|
|
237
299
|
font-weight: 800;
|
|
238
|
-
letter-spacing: -0.
|
|
300
|
+
letter-spacing: -0.02em;
|
|
301
|
+
line-height: 1.05;
|
|
239
302
|
}
|
|
240
303
|
|
|
241
|
-
.
|
|
242
|
-
|
|
243
|
-
border-radius: 12px;
|
|
244
|
-
background: #11302294;
|
|
245
|
-
padding: 10px;
|
|
304
|
+
.actions {
|
|
305
|
+
position: relative;
|
|
246
306
|
display: grid;
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
font-size: 14px;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
.summary strong {
|
|
253
|
-
color: #f4fff8;
|
|
307
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
308
|
+
gap: 10px;
|
|
254
309
|
}
|
|
255
310
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
flex-wrap: wrap;
|
|
259
|
-
gap: 8px;
|
|
311
|
+
#user-chat-link {
|
|
312
|
+
grid-column: 1 / -1;
|
|
260
313
|
}
|
|
261
314
|
|
|
262
315
|
.footer {
|
|
263
316
|
margin: 0;
|
|
264
|
-
color: #
|
|
317
|
+
color: #88a2c8;
|
|
265
318
|
font-size: 12px;
|
|
266
|
-
|
|
319
|
+
text-align: center;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
@media (min-width: 920px) {
|
|
323
|
+
.dashboard-card {
|
|
324
|
+
grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
|
|
325
|
+
grid-template-areas:
|
|
326
|
+
'status status'
|
|
327
|
+
'error error'
|
|
328
|
+
'profile grid'
|
|
329
|
+
'actions actions';
|
|
330
|
+
gap: 14px;
|
|
331
|
+
}
|
|
267
332
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
333
|
+
#user-status {
|
|
334
|
+
grid-area: status;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
#user-error {
|
|
338
|
+
grid-area: error;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
#user-profile {
|
|
342
|
+
grid-area: profile;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
#user-grid {
|
|
346
|
+
grid-area: grid;
|
|
347
|
+
align-self: start;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
#user-actions {
|
|
351
|
+
grid-area: actions;
|
|
352
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
#user-chat-link {
|
|
356
|
+
grid-column: span 2;
|
|
271
357
|
}
|
|
272
358
|
}
|
|
273
359
|
|
|
274
|
-
@media (max-width:
|
|
360
|
+
@media (max-width: 840px) {
|
|
275
361
|
.head {
|
|
276
|
-
|
|
362
|
+
grid-template-columns: 1fr;
|
|
277
363
|
}
|
|
278
364
|
|
|
279
|
-
.
|
|
280
|
-
|
|
365
|
+
.head-actions {
|
|
366
|
+
width: 100%;
|
|
367
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
368
|
+
grid-auto-flow: row;
|
|
369
|
+
grid-auto-columns: 1fr;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.head-actions .btn {
|
|
373
|
+
width: 100%;
|
|
281
374
|
}
|
|
375
|
+
}
|
|
282
376
|
|
|
377
|
+
@media (max-width: 620px) {
|
|
283
378
|
.profile {
|
|
284
379
|
grid-template-columns: 1fr;
|
|
285
380
|
text-align: center;
|
|
@@ -289,9 +384,23 @@
|
|
|
289
384
|
margin-inline: auto;
|
|
290
385
|
}
|
|
291
386
|
|
|
292
|
-
.actions
|
|
387
|
+
.actions {
|
|
388
|
+
grid-template-columns: 1fr;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
#user-chat-link {
|
|
392
|
+
grid-column: auto;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.actions .btn,
|
|
396
|
+
.actions button.btn {
|
|
293
397
|
width: 100%;
|
|
294
|
-
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
@media (max-width: 430px) {
|
|
402
|
+
.grid {
|
|
403
|
+
grid-template-columns: 1fr;
|
|
295
404
|
}
|
|
296
405
|
}
|
|
297
406
|
</style>
|
|
@@ -310,10 +419,13 @@
|
|
|
310
419
|
</header>
|
|
311
420
|
|
|
312
421
|
<section class="content">
|
|
313
|
-
<
|
|
314
|
-
|
|
422
|
+
<div class="intro">
|
|
423
|
+
<p class="eyebrow">Painel do usuário</p>
|
|
424
|
+
<h1>Minha Conta</h1>
|
|
425
|
+
<p class="lead">Informações da sua conta vinculada ao OmniZap e atalhos rápidos para gerenciar seus stickers com agilidade no desktop e no celular.</p>
|
|
426
|
+
</div>
|
|
315
427
|
|
|
316
|
-
<article class="card">
|
|
428
|
+
<article class="card dashboard-card">
|
|
317
429
|
<p id="user-status" class="status">Carregando dados da conta...</p>
|
|
318
430
|
<p id="user-error" class="error" hidden></p>
|
|
319
431
|
|
|
@@ -345,12 +457,6 @@
|
|
|
345
457
|
</article>
|
|
346
458
|
</div>
|
|
347
459
|
|
|
348
|
-
<div id="user-summary" class="summary" hidden>
|
|
349
|
-
<div><strong>Owner JID:</strong> <span id="user-owner-jid"></span></div>
|
|
350
|
-
<div><strong>Google ID:</strong> <span id="user-google-sub"></span></div>
|
|
351
|
-
<div><strong>Sessão expira:</strong> <span id="user-expires-at"></span></div>
|
|
352
|
-
</div>
|
|
353
|
-
|
|
354
460
|
<div id="user-actions" class="actions" hidden>
|
|
355
461
|
<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>
|
|
356
462
|
<a id="user-manage-main-link" class="btn" href="/stickers/perfil">Gerenciar meus stickers</a>
|
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
<meta name="robots" content="noindex, nofollow" />
|
|
9
9
|
<meta name="theme-color" content="#0f172a" />
|
|
10
10
|
<link rel="canonical" href="https://omnizap.shop/user/systemadm/" />
|
|
11
|
-
<link rel="icon"
|
|
11
|
+
<link rel="icon" href="/favicon.ico" sizes="any" />
|
|
12
|
+
<link rel="manifest" href="/site.webmanifest" />
|
|
13
|
+
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
|
12
14
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
13
15
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
14
16
|
<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" />
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
|
|
3
|
+
export const createStickerCatalogAdminBanService = ({ executeQuery, tables, sanitizeText, normalizeGoogleSubject, normalizeEmail, normalizeJid, toIsoOrNull, revokeGoogleWebSessionsByIdentity = async () => 0 }) => {
|
|
4
|
+
const TABLES = tables;
|
|
5
|
+
|
|
6
|
+
const mapAdminBanRow = (row) => {
|
|
7
|
+
if (!row || typeof row !== 'object') return null;
|
|
8
|
+
return {
|
|
9
|
+
id: String(row.id || '').trim(),
|
|
10
|
+
google_sub: normalizeGoogleSubject(row.google_sub),
|
|
11
|
+
email: normalizeEmail(row.email),
|
|
12
|
+
owner_jid: normalizeJid(row.owner_jid) || null,
|
|
13
|
+
reason: sanitizeText(row.reason || '', 255, { allowEmpty: true }) || null,
|
|
14
|
+
created_by_google_sub: normalizeGoogleSubject(row.created_by_google_sub),
|
|
15
|
+
created_by_email: normalizeEmail(row.created_by_email),
|
|
16
|
+
created_at: toIsoOrNull(row.created_at),
|
|
17
|
+
updated_at: toIsoOrNull(row.updated_at),
|
|
18
|
+
revoked_at: toIsoOrNull(row.revoked_at),
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const findActiveAdminBanForIdentity = async ({ googleSub = '', email = '', ownerJid = '' } = {}) => {
|
|
23
|
+
const normalizedSub = normalizeGoogleSubject(googleSub);
|
|
24
|
+
const normalizedEmail = normalizeEmail(email);
|
|
25
|
+
const normalizedOwnerJid = normalizeJid(ownerJid) || '';
|
|
26
|
+
const clauses = [];
|
|
27
|
+
const params = [];
|
|
28
|
+
if (normalizedSub) {
|
|
29
|
+
clauses.push('google_sub = ?');
|
|
30
|
+
params.push(normalizedSub);
|
|
31
|
+
}
|
|
32
|
+
if (normalizedEmail) {
|
|
33
|
+
clauses.push('email = ?');
|
|
34
|
+
params.push(normalizedEmail);
|
|
35
|
+
}
|
|
36
|
+
if (normalizedOwnerJid) {
|
|
37
|
+
clauses.push('owner_jid = ?');
|
|
38
|
+
params.push(normalizedOwnerJid);
|
|
39
|
+
}
|
|
40
|
+
if (!clauses.length) return null;
|
|
41
|
+
|
|
42
|
+
const rows = await executeQuery(
|
|
43
|
+
`SELECT *
|
|
44
|
+
FROM ${TABLES.STICKER_WEB_ADMIN_BAN}
|
|
45
|
+
WHERE revoked_at IS NULL
|
|
46
|
+
AND (${clauses.join(' OR ')})
|
|
47
|
+
ORDER BY created_at DESC
|
|
48
|
+
LIMIT 1`,
|
|
49
|
+
params,
|
|
50
|
+
);
|
|
51
|
+
return mapAdminBanRow(Array.isArray(rows) ? rows[0] : null);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const listAdminBans = async ({ activeOnly = false, limit = 100 } = {}) => {
|
|
55
|
+
const safeLimit = Math.max(1, Math.min(500, Number(limit || 100)));
|
|
56
|
+
const rows = await executeQuery(
|
|
57
|
+
`SELECT *
|
|
58
|
+
FROM ${TABLES.STICKER_WEB_ADMIN_BAN}
|
|
59
|
+
${activeOnly ? 'WHERE revoked_at IS NULL' : ''}
|
|
60
|
+
ORDER BY created_at DESC
|
|
61
|
+
LIMIT ${safeLimit}`,
|
|
62
|
+
);
|
|
63
|
+
return (Array.isArray(rows) ? rows : []).map(mapAdminBanRow).filter(Boolean);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const createAdminBanRecord = async ({ googleSub = '', email = '', ownerJid = '', reason = '', adminSession = null }) => {
|
|
67
|
+
const normalizedSub = normalizeGoogleSubject(googleSub);
|
|
68
|
+
const normalizedEmail = normalizeEmail(email);
|
|
69
|
+
const normalizedOwnerJid = normalizeJid(ownerJid) || '';
|
|
70
|
+
if (!normalizedSub && !normalizedEmail && !normalizedOwnerJid) {
|
|
71
|
+
const error = new Error('Informe google_sub, email ou owner_jid para banir.');
|
|
72
|
+
error.statusCode = 400;
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const existing = await findActiveAdminBanForIdentity({
|
|
77
|
+
googleSub: normalizedSub,
|
|
78
|
+
email: normalizedEmail,
|
|
79
|
+
ownerJid: normalizedOwnerJid,
|
|
80
|
+
});
|
|
81
|
+
if (existing) return { created: false, ban: existing };
|
|
82
|
+
|
|
83
|
+
const banId = randomUUID();
|
|
84
|
+
await executeQuery(
|
|
85
|
+
`INSERT INTO ${TABLES.STICKER_WEB_ADMIN_BAN}
|
|
86
|
+
(id, google_sub, email, owner_jid, reason, created_by_google_sub, created_by_email)
|
|
87
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
88
|
+
[banId, normalizedSub || null, normalizedEmail || null, normalizedOwnerJid || null, sanitizeText(reason || '', 255, { allowEmpty: true }) || null, normalizeGoogleSubject(adminSession?.googleSub) || null, normalizeEmail(adminSession?.email) || null],
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
if (normalizedSub || normalizedEmail || normalizedOwnerJid) {
|
|
92
|
+
await revokeGoogleWebSessionsByIdentity({
|
|
93
|
+
googleSub: normalizedSub,
|
|
94
|
+
email: normalizedEmail,
|
|
95
|
+
ownerJid: normalizedOwnerJid,
|
|
96
|
+
}).catch(() => {});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const rows = await executeQuery(`SELECT * FROM ${TABLES.STICKER_WEB_ADMIN_BAN} WHERE id = ? LIMIT 1`, [banId]);
|
|
100
|
+
return { created: true, ban: mapAdminBanRow(Array.isArray(rows) ? rows[0] : null) };
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const revokeAdminBanRecord = async (banId) => {
|
|
104
|
+
const normalizedId = sanitizeText(banId, 36, { allowEmpty: false });
|
|
105
|
+
if (!normalizedId) {
|
|
106
|
+
const error = new Error('ban_id invalido.');
|
|
107
|
+
error.statusCode = 400;
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
await executeQuery(
|
|
111
|
+
`UPDATE ${TABLES.STICKER_WEB_ADMIN_BAN}
|
|
112
|
+
SET revoked_at = COALESCE(revoked_at, UTC_TIMESTAMP())
|
|
113
|
+
WHERE id = ?`,
|
|
114
|
+
[normalizedId],
|
|
115
|
+
);
|
|
116
|
+
const rows = await executeQuery(`SELECT * FROM ${TABLES.STICKER_WEB_ADMIN_BAN} WHERE id = ? LIMIT 1`, [normalizedId]);
|
|
117
|
+
return mapAdminBanRow(Array.isArray(rows) ? rows[0] : null);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const assertGoogleIdentityNotBanned = async ({ sub = '', email = '', ownerJid = '' } = {}) => {
|
|
121
|
+
const ban = await findActiveAdminBanForIdentity({ googleSub: sub, email, ownerJid });
|
|
122
|
+
if (!ban) return null;
|
|
123
|
+
const error = new Error('Conta bloqueada pela administracao.');
|
|
124
|
+
error.statusCode = 403;
|
|
125
|
+
error.code = 'ADMIN_BANNED';
|
|
126
|
+
error.ban = ban;
|
|
127
|
+
throw error;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
mapAdminBanRow,
|
|
132
|
+
findActiveAdminBanForIdentity,
|
|
133
|
+
listAdminBans,
|
|
134
|
+
createAdminBanRecord,
|
|
135
|
+
revokeAdminBanRecord,
|
|
136
|
+
assertGoogleIdentityNotBanned,
|
|
137
|
+
};
|
|
138
|
+
};
|