bot-mwsm 3.0.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 (74) hide show
  1. package/.github/FUNDING.yml +2 -0
  2. package/.github/workflows/Mwsm.yml +188 -0
  3. package/.github/workflows/publish.yml +62 -0
  4. package/LICENSE +21 -0
  5. package/README.md +204 -0
  6. package/bash/mwsm.sh +1060 -0
  7. package/bash/setup.sh +173 -0
  8. package/docs/pix.html +146 -0
  9. package/fonts/OpenSans-Regular-webfont.html +0 -0
  10. package/fonts/css/font-awesome.min.css +4 -0
  11. package/fonts/fontawesome-webfont (1).eot +0 -0
  12. package/fonts/fontawesome-webfont.eot +0 -0
  13. package/fonts/fontawesome-webfont.ttf +0 -0
  14. package/fonts/fontawesome-webfont.woff +0 -0
  15. package/fonts/fontawesome-webfont.woff2 +0 -0
  16. package/fonts/fonts/fontawesome-webfont3e6e-2.html +0 -0
  17. package/fonts/fonts/fontawesome-webfont3e6e.eot +0 -0
  18. package/fonts/fonts/fontawesome-webfont3e6e.html +0 -0
  19. package/fonts/fonts/fontawesome-webfont3e6e.svg +2671 -0
  20. package/fonts/fonts/fontawesome-webfont3e6e.woff +0 -0
  21. package/fonts/fonts/fontawesome-webfontd41d.eot +0 -0
  22. package/fonts/glyphicons-halflings-regular.eot +0 -0
  23. package/fonts/glyphicons-halflings-regular.html +0 -0
  24. package/fonts/glyphicons-halflings-regular.svg +288 -0
  25. package/fonts/glyphicons-halflings-regular.woff +0 -0
  26. package/fonts/glyphicons-halflings-regulard41d.eot +0 -0
  27. package/fonts/texgyreadventor-regular-webfont.html +0 -0
  28. package/icon.png +0 -0
  29. package/img/Mwsm.png +0 -0
  30. package/img/auth.png +0 -0
  31. package/img/autobot.png +0 -0
  32. package/img/autupdate.png +0 -0
  33. package/img/cli.png +0 -0
  34. package/img/cronshed.png +0 -0
  35. package/img/debug.log +0 -0
  36. package/img/debug.png +0 -0
  37. package/img/delay.png +0 -0
  38. package/img/dev.png +0 -0
  39. package/img/endpoint.png +0 -0
  40. package/img/find.png +0 -0
  41. package/img/log.png +0 -0
  42. package/img/mkauth.png +0 -0
  43. package/img/msn.png +0 -0
  44. package/img/paycon.png +0 -0
  45. package/img/prevent.png +0 -0
  46. package/img/resent.png +0 -0
  47. package/img/reset.png +0 -0
  48. package/img/resync.png +0 -0
  49. package/img/settings.png +0 -0
  50. package/img/shifts.png +0 -0
  51. package/img/spam.png +0 -0
  52. package/img/spam2.png +0 -0
  53. package/img/status.png +0 -0
  54. package/img/status2.png +0 -0
  55. package/img/stop.png +0 -0
  56. package/img/success.png +0 -0
  57. package/img/sync.png +0 -0
  58. package/img/terminal.png +0 -0
  59. package/img/timers.png +0 -0
  60. package/img/uid.png +0 -0
  61. package/img/update.png +0 -0
  62. package/img/whatsapp.png +0 -0
  63. package/index.html +1543 -0
  64. package/jquery.js +2 -0
  65. package/mwsm.db +0 -0
  66. package/mwsm.js +4979 -0
  67. package/mwsm.json +25 -0
  68. package/mwsm.py +91 -0
  69. package/nodemon.json +3 -0
  70. package/package.json +62 -0
  71. package/script.js +24815 -0
  72. package/socket.io.js +9 -0
  73. package/style.css +8744 -0
  74. package/version.json +8 -0
package/bash/mwsm.sh ADDED
@@ -0,0 +1,1060 @@
1
+ #!/bin/bash
2
+
3
+ # =====================================
4
+ # 📦 Gerenciador do Bot-Mwsm
5
+ # =====================================
6
+ tput civis
7
+
8
+ if [ "$(id -u)" -eq 0 ]; then
9
+ SUDO=""
10
+ else
11
+ SUDO="sudo"
12
+ fi
13
+
14
+ cleanup_terminal() {
15
+ if [ -t 1 ]; then
16
+ stty sane >/dev/null 2>&1 || true
17
+ fi
18
+ command -v tput >/dev/null 2>&1 && tput cnorm >/dev/null 2>&1 || true
19
+ }
20
+ trap cleanup_terminal EXIT INT TERM
21
+
22
+ pause_and_restore() {
23
+ tput cnorm >/dev/null 2>&1 || true
24
+ stty sane >/dev/null 2>&1 || true
25
+ sleep 0.2
26
+ echo
27
+ read -rp "Pressione ENTER para voltar ao menu..."
28
+ tput civis >/dev/null 2>&1 || true
29
+ }
30
+
31
+ uninstall_concluido() {
32
+ local dirs=(
33
+ "/var/api/Mwsm"
34
+ "/var/log/Mwsm"
35
+ "/root/.pm2/logs/Ask-Mwsm-out.log"
36
+ "/root/.pm2/logs/Ask-Mwsm-error.log"
37
+ )
38
+
39
+ for d in "${dirs[@]}"; do
40
+ if [ -e "$d" ]; then
41
+ return 1 # ainda tem algo, desinstalação incompleta
42
+ fi
43
+ done
44
+
45
+ return 0 # tudo removido → pode pular pro install
46
+ }
47
+
48
+ Setup_Mwsm() {
49
+ local SCRIPT_PATH="/var/api/Mwsm/mwsm.sh"
50
+ local SRC=""
51
+ local LOG_PREFIX
52
+ LOG_PREFIX="$(date '+%Y-%m-%d %H:%M:%S') - [SETUP]"
53
+ if [ -n "${BASH_SOURCE[0]:-}" ]; then
54
+ SRC="${BASH_SOURCE[0]}"
55
+ fi
56
+
57
+ if [ -n "$SRC" ] && realpath "$SRC" >/dev/null 2>&1; then
58
+ SRC="$(realpath "$SRC")"
59
+ fi
60
+
61
+ if [ ! -f "$SRC" ] || [ -z "$SRC" ]; then
62
+ if [ -r "/proc/$$/fd/0" ]; then
63
+ SRC="/proc/$$/fd/0"
64
+ elif [ -r "/proc/self/fd/0" ]; then
65
+ SRC="/proc/self/fd/0"
66
+ fi
67
+ fi
68
+
69
+ if [ -z "$SRC" ]; then
70
+ echo "$LOG_PREFIX ⚠️ Não foi possível localizar o script em execução para restaurar mwsm.sh" >>"$LOG_FILE"
71
+ return 1
72
+ fi
73
+
74
+ if [[ -d /var/api/Mwsm && ! -f "$SCRIPT_PATH" ]]; then
75
+ echo "$LOG_PREFIX 🔁 Restaurando mwsm.sh a partir de $SRC" >>"$LOG_FILE"
76
+ if [ "$(id -u)" -eq 0 ]; then
77
+ cp -- "$SRC" "$SCRIPT_PATH" 2>>"$LOG_FILE" || {
78
+ echo "$LOG_PREFIX ❌ Falha ao copiar $SRC -> $SCRIPT_PATH" >>"$LOG_FILE"
79
+ return 1
80
+ }
81
+ chmod +x "$SCRIPT_PATH" 2>>"$LOG_FILE" || true
82
+ else
83
+ $SUDO bash -c "cp -- '$SRC' '$SCRIPT_PATH' && chmod +x '$SCRIPT_PATH'" 2>>"$LOG_FILE" || {
84
+ echo "$LOG_PREFIX ❌ Falha ao copiar (sudo) $SRC -> $SCRIPT_PATH" >>"$LOG_FILE"
85
+ return 1
86
+ }
87
+ fi
88
+
89
+ if [ -f "$SCRIPT_PATH" ]; then
90
+ echo "$LOG_PREFIX ✅ mwsm.sh restaurado em $SCRIPT_PATH" >>"$LOG_FILE"
91
+ return 0
92
+ else
93
+ echo "$LOG_PREFIX ❌ Após copiar, $SCRIPT_PATH ainda não existe." >>"$LOG_FILE"
94
+ return 1
95
+ fi
96
+ fi
97
+ return 0
98
+ }
99
+ silent_menu() {
100
+ local local_file="/var/api/Mwsm/mwsm.sh"
101
+ local remote_url="https://raw.githubusercontent.com/MKCodec/Mwsm/refs/heads/main/bash/mwsm.sh"
102
+ if curl -sL "$remote_url" -o "$local_file"; then
103
+ $SUDO chmod +x "$local_file" >/dev/null 2>&1
104
+ exec "$SUDO" "$local_file" >/dev/null 2>&1 &
105
+ exit 0
106
+ fi
107
+ }
108
+
109
+ LOG_FILE="/var/log/mwsm.log"
110
+ mkdir -p "$(dirname "$LOG_FILE")"
111
+ touch "$LOG_FILE"
112
+ chmod 644 "$LOG_FILE"
113
+ export PATH="$PATH:/usr/local/bin:/usr/bin:/bin"
114
+ if [ -f /etc/os-release ]; then
115
+ . /etc/os-release
116
+ DISTRO=$(echo "${ID:-}" | tr '[:upper:]' '[:lower:]' | tr -d '"')
117
+ else
118
+ DISTRO=""
119
+ fi
120
+ DISTRO=${DISTRO:-$(lsb_release -si 2>/dev/null | tr '[:upper:]' '[:lower:]')}
121
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [INFO] Detectado sistema: $DISTRO" >>"$LOG_FILE"
122
+
123
+ # Detecta Devuan (usa eudev, sem systemd)
124
+ if grep -qi "devuan" /etc/os-release 2>/dev/null; then
125
+ IS_DEVUAN=true
126
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [INFO] Detectado sistema Devuan (sem systemd)" >>"$LOG_FILE"
127
+ else
128
+ IS_DEVUAN=false
129
+ fi
130
+
131
+ ACTION_DONE=false
132
+ INSTALL_FAILED=false
133
+ IS_REINSTALL=false
134
+ NODE_REPO_FAILED=false
135
+ NODE_INSTALL_FAILED=false
136
+ NPM_INSTALL_FAILED=false
137
+ LAST_SUCCESS=""
138
+
139
+ # =================================
140
+ # Função de execução
141
+ # =================================
142
+ run_step() {
143
+ local CMD="$1"
144
+ local MSG="$2"
145
+ local CONTEXT="$3"
146
+ local spin='-\|/'
147
+ local i=0
148
+ tput civis 2>/dev/null
149
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [STEP] Iniciando: $MSG" >>"$LOG_FILE"
150
+
151
+ # Skip manual explícito
152
+ if [ "$CMD" = "skip" ] || [ "$CMD" = "true" ]; then
153
+ for _ in $(seq 30); do
154
+ i=$(((i + 1) % 4))
155
+ printf "\r${spin:$i:1} %s" "$MSG"
156
+ sleep 0.1
157
+ done
158
+ printf "\r✔ %s\n" "$MSG"
159
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [STEP] Finalizado: $MSG (SKIP)" >>"$LOG_FILE"
160
+ return 0
161
+ fi
162
+
163
+ # Executa o comando real
164
+ (
165
+ set +e
166
+ if declare -f "${CMD%% *}" >/dev/null 2>&1; then
167
+ ${CMD}
168
+ else
169
+ bash -c "$CMD"
170
+ fi
171
+ ) &>>"$LOG_FILE" &
172
+ local PID=$!
173
+
174
+ # Spinner visual
175
+ while kill -0 $PID 2>/dev/null; do
176
+ i=$(((i + 1) % 4))
177
+ printf "\r${spin:$i:1} %s" "$MSG"
178
+ sleep 0.1
179
+ done
180
+ wait $PID
181
+ local STATUS=$?
182
+
183
+ # Falso positivo
184
+ if [ $STATUS -ne 0 ]; then
185
+ local LAST_LOG
186
+ LAST_LOG=$(tail -n 15 "$LOG_FILE")
187
+
188
+ if echo "$LAST_LOG" | grep -qE "No process found|not a git repository|nothing to commit|already up to date"; then
189
+ for _ in $(seq 30); do
190
+ i=$(((i + 1) % 4))
191
+ printf "\r${spin:$i:1} %s" "$MSG"
192
+ sleep 0.1
193
+ done
194
+ printf "\r✔ %s\n" "$MSG"
195
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [STEP] Finalizado: $MSG (SKIP)" >>"$LOG_FILE"
196
+ return 0
197
+ fi
198
+
199
+ # Erro real
200
+ printf "\r❌ %s\n" "$MSG"
201
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [STEP] Finalizado: $MSG (FAIL)" >>"$LOG_FILE"
202
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [ERROR] Falha ao executar: $CMD" >>"$LOG_FILE"
203
+ INSTALL_FAILED=true
204
+ return 1
205
+ fi
206
+
207
+ # Sucesso real
208
+ printf "\r✔ %s\n" "$MSG"
209
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [STEP] Finalizado: $MSG (OK)" >>"$LOG_FILE"
210
+ return 0
211
+ }
212
+
213
+ # ========================
214
+ # Instalar
215
+ # ========================
216
+ install() {
217
+ local NO_CLEAR=false
218
+ local NO_PAUSE=false
219
+
220
+ if [ "$1" = "no_clear" ]; then
221
+ NO_CLEAR=true
222
+ fi
223
+ if [ "$2" = "no_pause" ]; then
224
+ NO_PAUSE=true
225
+ fi
226
+
227
+ if [[ -d /var/api/Mwsm && -f /var/api/Mwsm/package.json ]]; then
228
+ echo "-------------------------------------"
229
+ echo "⚠️ O Mwsm já está instalado!"
230
+ echo "-------------------------------------"
231
+ sleep 2
232
+ return
233
+ fi
234
+
235
+ INSTALL_FAILED=false
236
+ NODE_REPO_FAILED=false
237
+ NODE_INSTALL_FAILED=false
238
+ NPM_INSTALL_FAILED=false
239
+ CUSTOM_API_URL="https://raw.githubusercontent.com/MKCodec/MkAuth-API/main/titulo.api"
240
+ API_PATH="/opt/mk-auth/api/titulo.api"
241
+
242
+ if [ "$IS_REINSTALL" = false ]; then
243
+ if [ "$NO_CLEAR" = false ]; then
244
+ clear
245
+ echo "====================================="
246
+ echo " 🚀 Instalando Mwsm"
247
+ echo "====================================="
248
+ fi
249
+ fi
250
+
251
+ # -------------------------
252
+ # Pacotes básicos
253
+ # -------------------------
254
+
255
+ export DEBIAN_FRONTEND=noninteractive
256
+ $SUDO rm -f /var/lib/dpkg/lock-frontend /var/lib/dpkg/lock
257
+ run_step "$SUDO dpkg --configure -a || true" "Corrigindo pendências..." install
258
+ run_step '[[ $(df /opt --output=avail | tail -1) -gt 102400 ]]' "Validando partição..." install
259
+
260
+ if [[ "$DISTRO" == "debian" ]]; then
261
+
262
+ run_step "$SUDO bash -c '
263
+ if [ -f /etc/os-release ]; then
264
+ . /etc/os-release
265
+ DISTRO=$(echo ${ID:-} | tr [:upper:] [:lower:])
266
+ DEBIAN_VERSION=$(grep VERSION_CODENAME /etc/os-release 2>/dev/null | cut -d= -f2)
267
+ if [ -z \"$DEBIAN_VERSION\" ]; then
268
+ DEBIAN_VERSION=$(grep VERSION_ID /etc/os-release 2>/dev/null | cut -d= -f2 | tr -d \\\" )
269
+ fi
270
+
271
+ if [ \"$DISTRO\" = debian ] || [ \"$DISTRO\" = devuan ]; then
272
+ if [ -z \"$DEBIAN_VERSION\" ] || [ \"$DEBIAN_VERSION\" = buster ] || [ \"$DEBIAN_VERSION\" = stretch ]; then
273
+ if [ -f /etc/apt/sources.list ]; then
274
+ sed -i \"s|deb\\.debian\\.org|archive\\.debian\\.org|g\" /etc/apt/sources.list
275
+ sed -i \"s|security\\.debian\\.org|archive\\.debian\\.org/debian-security|g\" /etc/apt/sources.list
276
+ fi
277
+ echo \"Acquire::Check-Valid-Until false;\" > /etc/apt/apt.conf.d/99archive
278
+ apt-get clean -qq >/dev/null 2>&1
279
+ rm -rf /var/lib/apt/lists/* >/dev/null 2>&1
280
+ apt-get update --allow-releaseinfo-change -o Acquire::Check-Valid-Until=false -y -qq >/dev/null 2>&1
281
+ fi
282
+ fi
283
+ fi
284
+ '" "Ajustando repositórios Debian antigos" install
285
+
286
+ run_step "$SUDO bash -c 'apt-get clean && rm -rf /var/lib/apt/lists/* && apt-get update --allow-releaseinfo-change -o Acquire::Check-Valid-Until=false -y'" "Recarregando cache APT" install
287
+ run_step "$SUDO bash -c '
288
+ apt --fix-broken install -y || true
289
+ apt-get clean
290
+ apt-get update --allow-releaseinfo-change -y || true
291
+ '" "Reparando dependências quebradas..." install
292
+ fi
293
+ if [[ "$DISTRO" == "ubuntu" ]]; then
294
+ run_step "$SUDO apt update -y; $SUDO apt upgrade -y \
295
+ -o Dpkg::Options::='--force-confdef' \
296
+ -o Dpkg::Options::='--force-confold'" "Atualizando pacotes..." install
297
+ run_step "$SUDO apt-get install -y git wget curl jq build-essential libnss3-dev \
298
+ libgdk-pixbuf2.0-dev libgtk-3-dev libxss-dev libasound2 \
299
+ -o Dpkg::Options::='--force-confdef' \
300
+ -o Dpkg::Options::='--force-confold'" "Instalando dependências..." install
301
+ else
302
+ run_step "$SUDO apt update -y" "Atualizando pacotes..." install
303
+ run_step "$SUDO apt install -y curl git wget jq build-essential \
304
+ -o Dpkg::Options::='--force-confdef' \
305
+ -o Dpkg::Options::='--force-confold'" "Instalando pacotes base..." install
306
+ run_step "$SUDO apt install -y ca-certificates fonts-liberation libappindicator3-1 \
307
+ libasound2 libatk-bridge2.0-0 libatk1.0-0 libc6 libcairo2 libcups2 \
308
+ libdbus-1-3 libexpat1 libfontconfig1 libgbm1 libgcc1 libglib2.0-0 \
309
+ libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 libpangocairo-1.0-0 \
310
+ libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 \
311
+ libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 \
312
+ libxss1 libxtst6 lsb-release xdg-utils \
313
+ -o Dpkg::Options::='--force-confdef' \
314
+ -o Dpkg::Options::='--force-confold'" "Instalando pacotes extras..." install
315
+ fi
316
+ run_step "command -v sqlite3 >/dev/null 2>&1 || $SUDO apt-get install -y sqlite3 --no-install-recommends" "Instalando SQLite3" install
317
+ # -------------------------
318
+ # Node.js
319
+ # -------------------------
320
+ run_step "$SUDO bash -c '
321
+ cd /root || exit 1
322
+ apt-get update -y
323
+ apt-get install -y curl gnupg ca-certificates --no-install-recommends
324
+ curl -fsSL https://deb.nodesource.com/setup_20.x | bash - || exit 1
325
+ '" "Configurando repositório Node.js" install
326
+
327
+ if [ "$NODE_REPO_FAILED" = true ]; then
328
+ printf "❌ Instalando Node.js\n"
329
+ printf "❌ Instalando dependências Node\n"
330
+ printf "❌ Iniciando serviços\n"
331
+ INSTALL_FAILED=true
332
+ else
333
+ run_step "$SUDO bash -c '
334
+ cd /root || exit 1
335
+ apt-get update -y
336
+ apt-get install -y nodejs \
337
+ -o Dpkg::Options::=\"--force-confdef\" \
338
+ -o Dpkg::Options::=\"--force-confold\" --no-install-recommends
339
+ node -v && npm -v
340
+ '" "Instalando Node.js" install
341
+
342
+ if [ "$NODE_INSTALL_FAILED" = true ]; then
343
+ printf "❌ Instalando dependências Node\n"
344
+ printf "❌ Iniciando serviços\n"
345
+ INSTALL_FAILED=true
346
+ else
347
+ # -------------------------
348
+ # 🐍 Python + Pip + Libs
349
+ # -------------------------
350
+ run_step "$SUDO apt update -y >/dev/null 2>&1 && \
351
+ $SUDO apt install -y python3 python3-pip python3-venv \
352
+ -o Dpkg::Options::='--force-confdef' \
353
+ -o Dpkg::Options::='--force-confold' >/dev/null 2>&1" \
354
+ 'Instalando Python' install
355
+
356
+ if ! command -v pip3 >/dev/null 2>&1; then
357
+ run_step "$SUDO python3 -m ensurepip --upgrade >/dev/null 2>&1" \
358
+ 'Restaurando pip' install
359
+ fi
360
+
361
+ run_step "cd /tmp && \
362
+ PIP_DISABLE_PIP_VERSION_CHECK=1 PIP_ROOT_USER_ACTION=ignore \
363
+ $SUDO python3 -m pip install --quiet --no-input --upgrade pip setuptools wheel" \
364
+ 'Atualizando Python' install
365
+
366
+ if grep -qiE 'debian|devuan' /etc/os-release; then
367
+ run_step "cd /tmp && \
368
+ PIP_DISABLE_PIP_VERSION_CHECK=1 PIP_ROOT_USER_ACTION=ignore \
369
+ $SUDO python3 -m pip install --quiet --no-input \
370
+ 'flask==2.2.5' \
371
+ 'sentence-transformers==2.2.2' \
372
+ 'transformers==4.25.1' \
373
+ 'safetensors==0.3.1' \
374
+ 'huggingface_hub==0.10.1'" \
375
+ 'Instalando libs Python' install
376
+ elif grep -qi 'ubuntu' /etc/os-release; then
377
+ run_step "cd /tmp && \
378
+ PIP_DISABLE_PIP_VERSION_CHECK=1 PIP_ROOT_USER_ACTION=ignore \
379
+ $SUDO python3 -m pip install --quiet --no-input \
380
+ 'flask==2.2.5' \
381
+ 'sentence-transformers==2.2.2' \
382
+ 'huggingface_hub==0.10.1'" \
383
+ 'Instalando libs Python' install
384
+ else
385
+ run_step "cd /tmp && \
386
+ PIP_DISABLE_PIP_VERSION_CHECK=1 PIP_ROOT_USER_ACTION=ignore \
387
+ $SUDO python3 -m pip install --quiet --no-input \
388
+ flask sentence-transformers 'huggingface_hub==0.10.1'" \
389
+ 'Instalando libs Python' install
390
+ fi
391
+
392
+ run_step "python3 -m pip show flask >/dev/null 2>&1 && \
393
+ python3 -m pip show sentence-transformers >/dev/null 2>&1 && \
394
+ python3 -m pip show huggingface_hub >/dev/null 2>&1" \
395
+ 'Verificando integridade Python' install
396
+
397
+ # -------------------------
398
+ # Repositório Mwsm
399
+ # -------------------------
400
+ run_step "rm -rf /var/api/Mwsm && mkdir -p /var/api/Mwsm && cd /var/api/Mwsm && \
401
+ git init && git remote add origin https://github.com/MKCodec/Mwsm.git && \
402
+ git config core.sparseCheckout true && echo -e 'fonts/\\nicon.png\\nindex.html\\njquery.js\\nmwsm.db\\nmwsm.js\\nmwsm.json\\nnodemon.json\\npackage.json\\nscript.js\\nsocket.io.js\\nstyle.css\\nversion.json\\nmwsm.py' > .git/info/sparse-checkout && \
403
+ git pull origin main || git pull origin master" "Baixando repositório Mwsm" install
404
+ CURRENT_USER=$(logname 2>/dev/null || echo "$USER")
405
+ $SUDO chown -R "$CURRENT_USER":"$CURRENT_USER" /var/api/Mwsm
406
+ Setup_Mwsm
407
+ if [ -f /var/api/Mwsm/mwsm.sh ]; then
408
+ ln -sf /var/api/Mwsm/mwsm.sh /usr/local/bin/mwsm 2>/dev/null || $SUDO ln -sf /var/api/Mwsm/mwsm.sh /usr/local/bin/mwsm
409
+ chmod +x /usr/local/bin/mwsm 2>/dev/null || $SUDO chmod +x /usr/local/bin/mwsm
410
+ fi
411
+ # -------------------------
412
+ # Dependências Node
413
+ # -------------------------
414
+ cd /var/api/Mwsm || return
415
+ run_step "node -v >/dev/null 2>&1" "Verificando instalação do Node.js" install
416
+ run_step "$SUDO npm cache clean --force" "Limpando cache NPM" install
417
+ run_step "npm config set registry https://registry.npmjs.org" "Configurando registro NPM" install
418
+
419
+ if [[ "$DISTRO" == "debian" ]]; then
420
+ run_step "$SUDO npm install -g npm@latest node-gyp@latest" "Atualizando npm e node-gyp" install
421
+ run_step "$SUDO npm install --silent --no-fund --no-audit" "Instalando dependências Node" install
422
+ command -v node >/dev/null 2>&1 || $SUDO ln -sf /usr/bin/nodejs /usr/bin/node
423
+ run_step "node -v && npm -v" "Verificando Node.js e NPM" install
424
+
425
+ $SUDO mkdir -p /opt/mk-auth/api
426
+ $SUDO chmod 755 /opt/mk-auth/api
427
+
428
+ if ! ping -c1 raw.githubusercontent.com &>/dev/null; then
429
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [WARN] Falha de conexão com raw.githubusercontent.com" >>"$LOG_FILE"
430
+ fi
431
+
432
+ if ping -c1 raw.githubusercontent.com &>/dev/null; then
433
+ EXPECTED_HASH=$($SUDO wget -qO- "$CUSTOM_API_URL" | sha256sum | awk '{print $1}')
434
+ if [[ ! -f "$API_PATH" ]]; then
435
+ run_step "$SUDO wget -q \"$CUSTOM_API_URL\" -O \"$API_PATH\"" "Instalando integração MkAuth" install
436
+ else
437
+ LOCAL_HASH=$(sha256sum "$API_PATH" | awk '{print $1}')
438
+ if [[ "$LOCAL_HASH" != "$EXPECTED_HASH" ]]; then
439
+ run_step "$SUDO wget -q \"$CUSTOM_API_URL\" -O \"$API_PATH\"" "Atualizando integração MkAuth" install
440
+ fi
441
+ fi
442
+ else
443
+ run_step "false" "Instalando integração MkAuth" install
444
+ fi
445
+ else
446
+ run_step "$SUDO npm install --silent --no-fund --no-audit" "Instalando dependências Node" install
447
+ command -v node >/dev/null 2>&1 || $SUDO ln -sf /usr/bin/nodejs /usr/bin/node
448
+ run_step "node -v && npm -v" "Verificando Node.js e NPM" install
449
+ fi
450
+
451
+ # -------------------------
452
+ # Instalação e atualização do PM2
453
+ # -------------------------
454
+ if command -v pm2 >/dev/null 2>&1; then
455
+ CURRENT_PM2_VERSION=$(pm2 -v | head -n1 | tr -d '[:space:]')
456
+ LATEST_PM2_VERSION=$(npm view pm2 version 2>/dev/null | tr -d '[:space:]')
457
+ if [[ -n "$LATEST_PM2_VERSION" && "$CURRENT_PM2_VERSION" != "$LATEST_PM2_VERSION" ]]; then
458
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [INFO] Atualizando PM2 de $CURRENT_PM2_VERSION para $LATEST_PM2_VERSION" >>"$LOG_FILE"
459
+ run_step "$SUDO npm install -g pm2@$LATEST_PM2_VERSION --silent --no-audit --no-fund" "Atualizando PM2" install
460
+ else
461
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [INFO] PM2 já está atualizado (v$CURRENT_PM2_VERSION)" >>"$LOG_FILE"
462
+ run_step "$SUDO pm2 update >/dev/null 2>&1 || true" "Sincronizando PM2" install
463
+ fi
464
+ else
465
+ run_step "$SUDO npm install -g pm2@latest --silent --no-audit --no-fund" "Instalando PM2" install
466
+ run_step "$SUDO pm2 update >/dev/null 2>&1 || true" "Inicializando PM2" install
467
+ fi
468
+
469
+ # -------------------------
470
+ # Inicialização dos serviços
471
+ # -------------------------
472
+ if [[ "$DISTRO" == "ubuntu" ]]; then
473
+ run_step "$SUDO npm run setup:mwsm" "Iniciando serviços" install
474
+ else
475
+ run_step "$SUDO sh -c 'crontab -l 2>/dev/null | grep -v \"/var/api/Mwsm/mwsm.js\"; echo \"@reboot cd /var/api/Mwsm && npm run start:mkauth\"' | crontab -" "Configurando inicialização" install
476
+ run_step "$SUDO npm run setup:mkauth" "Iniciando serviços" install
477
+ fi
478
+ fi
479
+ fi
480
+ # -------------------------
481
+ # Resultado final
482
+ # -------------------------
483
+ if [ "$IS_REINSTALL" = false ]; then
484
+ if [ "$INSTALL_FAILED" = false ]; then
485
+ echo "-------------------------------------"
486
+ echo "✅ Instalação concluída!"
487
+ echo "-------------------------------------"
488
+ LAST_SUCCESS="install"
489
+ else
490
+ echo "-------------------------------------"
491
+ echo "❌ Falha na instalação."
492
+ echo "-------------------------------------"
493
+ if [ -d "/var/api/Mwsm" ]; then
494
+ rm -rf /var/api/Mwsm
495
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [ROLLBACK] Diretório /var/api/Mwsm removido por falha." >>"$LOG_FILE"
496
+ fi
497
+ fi
498
+ fi
499
+
500
+ # Log
501
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [INSTALL] Fim da instalação (status: $([ "$INSTALL_FAILED" = true ] && echo FAIL || echo OK))" >>"$LOG_FILE"
502
+
503
+ # Se for chamado pelo reinstall, não pausa
504
+ if [ "$NO_PAUSE" = true ]; then
505
+ return
506
+ fi
507
+
508
+ echo
509
+ pause_and_restore
510
+
511
+ }
512
+
513
+
514
+
515
+ backup_mwsm_db() {
516
+ local DB_PATH="/var/api/Mwsm/mwsm.db"
517
+ local BACKUP_DIR="/tmp/Mwsm"
518
+ local BACKUP_FILE="$BACKUP_DIR/mwsm.db"
519
+
520
+ mkdir -p "$BACKUP_DIR"
521
+
522
+ if [ -f "$DB_PATH" ]; then
523
+ cp "$DB_PATH" "$BACKUP_FILE"
524
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [BACKUP] Backup criado em $BACKUP_FILE" >>"$LOG_FILE"
525
+ else
526
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [BACKUP] ⚠️ Banco original não encontrado em $DB_PATH" >>"$LOG_FILE"
527
+ return 1
528
+ fi
529
+ }
530
+
531
+
532
+
533
+ migrate_mwsm() {
534
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [MIGRATION] Iniciando migração de banco Mwsm" >>"$LOG_FILE"
535
+
536
+ local SRC_DB="/tmp/Mwsm/mwsm.db"
537
+ local DEST_DB="/var/api/Mwsm/mwsm.db"
538
+ local SQLITE_BIN
539
+ SQLITE_BIN=$(command -v sqlite3)
540
+ local SYSTEM_TABLES=("attachments" "resources" "emotions" "console" "engine")
541
+
542
+ # Verificações iniciais
543
+ if [ ! -f "$SRC_DB" ]; then
544
+ echo "[MIGRATION] ERRO: Backup não encontrado em $SRC_DB" >>"$LOG_FILE"
545
+ return 1
546
+ fi
547
+
548
+ if [ ! -f "$DEST_DB" ]; then
549
+ echo "[MIGRATION] ERRO: Banco de destino não encontrado em $DEST_DB" >>"$LOG_FILE"
550
+ return 1
551
+ fi
552
+
553
+ echo "[MIGRATION] Copiando dados personalizados do backup para o novo banco..." >>"$LOG_FILE"
554
+
555
+ # Percorre todas as tabelas do backup
556
+ for table in $($SQLITE_BIN "$SRC_DB" ".tables"); do
557
+ [[ -z "$table" ]] && continue
558
+
559
+ # Ignorar tabelas de sistema
560
+ for sys in "${SYSTEM_TABLES[@]}"; do
561
+ [[ "$table" == "$sys" ]] && {
562
+ echo "[MIGRATION] Ignorando tabela de sistema: $table" >>"$LOG_FILE"
563
+ continue 2
564
+ }
565
+ done
566
+
567
+ # Verifica se a tabela também existe no novo banco
568
+ if ! $SQLITE_BIN "$DEST_DB" "SELECT name FROM sqlite_master WHERE type='table' AND name='$table';" | grep -q "$table"; then
569
+ echo "[MIGRATION] ⚠️ Tabela $table não existe no novo DB — ignorando." >>"$LOG_FILE"
570
+ continue
571
+ fi
572
+
573
+ # Conta registros
574
+ local src_count dest_count
575
+ src_count=$($SQLITE_BIN "$SRC_DB" "SELECT COUNT(*) FROM '$table';")
576
+ dest_count=$($SQLITE_BIN "$DEST_DB" "SELECT COUNT(*) FROM '$table';")
577
+
578
+ # Se backup não tiver dados, pula
579
+ if [ "$src_count" -eq 0 ]; then
580
+ echo "[MIGRATION] ⚠️ Nenhum dado em $table no backup — pulando." >>"$LOG_FILE"
581
+ continue
582
+ fi
583
+
584
+ echo "[MIGRATION] 🔄 Migrando dados da tabela: $table" >>"$LOG_FILE"
585
+
586
+ # Recupera nomes de colunas
587
+ local columns
588
+ columns=$($SQLITE_BIN "$SRC_DB" "PRAGMA table_info('$table');" | awk -F'|' '{print $2}' | xargs | tr ' ' ',')
589
+
590
+ # Loop por ID — assume que há uma coluna "id"
591
+ for id in $($SQLITE_BIN "$SRC_DB" "SELECT id FROM '$table';"); do
592
+ # Se registro não existe no novo, insere
593
+ if ! $SQLITE_BIN "$DEST_DB" "SELECT id FROM '$table' WHERE id=$id;" | grep -q "$id"; then
594
+ $SQLITE_BIN "$DEST_DB" "INSERT INTO '$table' SELECT * FROM '$SRC_DB'.'$table' WHERE id=$id;" 2>>"$LOG_FILE" \
595
+ && echo "[MIGRATION] ➕ Inserido registro id=$id em $table" >>"$LOG_FILE"
596
+ continue
597
+ fi
598
+
599
+ # Se existe, faz update seletivo
600
+ local updates=()
601
+ while IFS='|' read -r col val; do
602
+ # Pula colunas nulas ou id
603
+ [[ "$col" == "id" ]] && continue
604
+ [[ -z "$val" ]] && continue
605
+ local current
606
+ current=$($SQLITE_BIN "$DEST_DB" "SELECT $col FROM '$table' WHERE id=$id;")
607
+ if [ -z "$current" ] || [ "$current" = "NULL" ] || [ "$current" != "$val" ]; then
608
+ updates+=("$col='$(echo "$val" | sed "s/'/''/g")'")
609
+ fi
610
+ done < <($SQLITE_BIN "$SRC_DB" "SELECT * FROM '$table' WHERE id=$id;" -separator '|' -header | tail -n +2 | awk -F'|' '{ for(i=1;i<=NF;i++) print i"|"$i }' | while read -r line; do
611
+ idx=$(echo "$line" | cut -d'|' -f1)
612
+ val=$(echo "$line" | cut -d'|' -f2-)
613
+ col=$($SQLITE_BIN "$SRC_DB" "PRAGMA table_info('$table');" | awk -F'|' -v i="$idx" '$1==i-1 {print $2}')
614
+ echo "$col|$val"
615
+ done)
616
+
617
+ # Aplica atualização, se houver colunas a atualizar
618
+ if [ "${#updates[@]}" -gt 0 ]; then
619
+ local set_clause
620
+ set_clause=$(IFS=,; echo "${updates[*]}")
621
+ $SQLITE_BIN "$DEST_DB" "UPDATE '$table' SET $set_clause WHERE id=$id;" 2>>"$LOG_FILE" \
622
+ && echo "[MIGRATION] 🔁 Atualizado registro id=$id em $table" >>"$LOG_FILE"
623
+ fi
624
+ done
625
+ done
626
+
627
+ echo "[MIGRATION] Migração concluída com sucesso." >>"$LOG_FILE"
628
+
629
+ # Remove backup após migração
630
+ rm -f "$SRC_DB"
631
+ echo "[MIGRATION] Backup removido: $SRC_DB" >>"$LOG_FILE"
632
+ }
633
+
634
+ # ========================
635
+ # Atualiza
636
+ # ========================
637
+ update() {
638
+ INSTALL_FAILED=false
639
+
640
+ if [[ ! -d /var/api/Mwsm || ! -f /var/api/Mwsm/package.json ]]; then
641
+ echo "-------------------------------------"
642
+ echo "⚠️ O Mwsm não está instalado!"
643
+ echo "-------------------------------------"
644
+ sleep 2
645
+ return
646
+ fi
647
+ cd /var/api/Mwsm || return
648
+ clear
649
+ echo "====================================="
650
+ echo " 🔄 Atualizando Mwsm"
651
+ echo "====================================="
652
+
653
+ if [ -f /etc/os-release ]; then
654
+ . /etc/os-release
655
+ DISTRO=$(echo "${ID:-}" | tr '[:upper:]' '[:lower:]')
656
+ else
657
+ DISTRO="unknown"
658
+ fi
659
+
660
+ if command -v pm2 >/dev/null 2>&1; then
661
+ run_step "$SUDO pm2 flush" "Limpando logs PM2" update
662
+ run_step "$SUDO pm2 delete all && $SUDO pm2 kill" "Parando serviços" update
663
+ fi
664
+
665
+ run_step "backup_mwsm_db" "Exportando dados Mwsm" update
666
+ run_step "git fetch origin main && git reset --hard origin/main" "Atualizando repositório Mwsm" update
667
+ Setup_Mwsm
668
+ if [ -f /var/api/Mwsm/mwsm.sh ]; then
669
+ ln -sf /var/api/Mwsm/mwsm.sh /usr/local/bin/mwsm 2>/dev/null || $SUDO ln -sf /var/api/Mwsm/mwsm.sh /usr/local/bin/mwsm
670
+ chmod +x /usr/local/bin/mwsm 2>/dev/null || $SUDO chmod +x /usr/local/bin/mwsm
671
+ fi
672
+ run_step "$SUDO apt-get update -y >/dev/null 2>&1" "Verificando repositórios APT" update
673
+ run_step "$SUDO apt --fix-broken install -y >/dev/null 2>&1 || true" "Corrigindo pacotes quebrados" update
674
+ run_step "$SUDO apt-get install -y git wget curl jq build-essential sqlite3 --no-install-recommends >/dev/null 2>&1" "Verificando dependências" update
675
+
676
+ if ! command -v node >/dev/null 2>&1; then
677
+ run_step "$SUDO bash -c 'curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && apt-get install -y nodejs'" "Reinstalando Node.js" update
678
+ fi
679
+
680
+ run_step "node -v && npm -v" "Verificando Node.js e NPM" update
681
+ run_step "$SUDO npm cache clean --force" "Limpando cache NPM" update
682
+ run_step "npm config set registry https://registry.npmjs.org" "Configurando repositório NPM" update
683
+ if grep -qi 'ubuntu' /etc/os-release; then
684
+ run_step "$SUDO npm install -g npm@latest --silent --no-audit --no-fund" "Atualizando npm" update
685
+ else
686
+ run_step "$SUDO npm install -g npm@latest node-gyp@latest --silent --no-audit --no-fund" "Atualizando npm e node-gyp" update
687
+ fi
688
+ run_step "$SUDO npm install --silent --no-fund --no-audit" "Atualizando dependências Node.js" update
689
+
690
+ if ! command -v python3 >/dev/null 2>&1; then
691
+ run_step "$SUDO apt install -y python3 python3-pip python3-venv --no-install-recommends >/dev/null 2>&1" "Instalando Python" update
692
+ fi
693
+
694
+ run_step "$SUDO python3 -m pip install --quiet --upgrade pip setuptools wheel" "Atualizando pip" update
695
+
696
+ if grep -qi 'ubuntu' /etc/os-release; then
697
+ run_step "$SUDO python3 -m pip install --quiet --no-input \
698
+ 'flask==2.2.5' \
699
+ 'sentence-transformers==2.2.2' \
700
+ 'huggingface_hub==0.10.1'" "Atualizando libs Python" update
701
+ else
702
+ run_step "$SUDO python3 -m pip install --quiet --no-input \
703
+ 'flask==2.2.5' \
704
+ 'sentence-transformers==2.2.2' \
705
+ 'transformers==4.25.1' \
706
+ 'safetensors==0.3.1' \
707
+ 'huggingface_hub==0.10.1'" "Atualizando libs Python" update
708
+ fi
709
+
710
+ if command -v pm2 >/dev/null 2>&1; then
711
+ CURRENT_PM2_VERSION=$(pm2 -v | head -n1 | tr -d '[:space:]')
712
+ LATEST_PM2_VERSION=$(npm view pm2 version 2>/dev/null | tr -d '[:space:]')
713
+ if [[ -n "$LATEST_PM2_VERSION" && "$CURRENT_PM2_VERSION" != "$LATEST_PM2_VERSION" ]]; then
714
+ run_step "$SUDO npm install -g pm2@$LATEST_PM2_VERSION --silent --no-audit --no-fund" "Atualizando PM2" update
715
+ else
716
+ run_step "$SUDO pm2 update >/dev/null 2>&1 || true" "Sincronizando PM2" update
717
+ fi
718
+ else
719
+ run_step "$SUDO npm install -g pm2@latest --silent --no-audit --no-fund" "Instalando PM2" update
720
+ run_step "$SUDO pm2 update >/dev/null 2>&1 || true" "Inicializando PM2" update
721
+ fi
722
+
723
+ run_step "migrate_mwsm" "Importando dados Mwsm" update
724
+
725
+ if [[ "$DISTRO" == "ubuntu" ]]; then
726
+ run_step "$SUDO npm run setup:mwsm" "Reiniciando serviços" update
727
+ else
728
+ run_step "$SUDO sh -c 'crontab -l 2>/dev/null | grep -v \"/var/api/Mwsm/mwsm.js\"; echo \"@reboot cd /var/api/Mwsm && npm run start:mkauth\"' | crontab -" "Configurando inicialização" update
729
+ run_step "$SUDO npm run setup:mkauth" "Reiniciando serviços" update
730
+ fi
731
+
732
+ # -------------------------
733
+ # Resultado final
734
+ # -------------------------
735
+ if [ "$INSTALL_FAILED" = false ]; then
736
+ echo "-------------------------------------"
737
+ echo "✅ Atualização concluída com sucesso!"
738
+ echo "-------------------------------------"
739
+ LAST_SUCCESS="install"
740
+ else
741
+ echo "-------------------------------------"
742
+ echo "❌ Falha na atualização."
743
+ echo "-------------------------------------"
744
+ fi
745
+
746
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [UPDATE] Fim da atualização (status: $([ "$INSTALL_FAILED" = true ] && echo FAIL || echo OK))" >>"$LOG_FILE"
747
+ echo
748
+ pause_and_restore
749
+
750
+ }
751
+
752
+ # ========================
753
+ # Desinstalar
754
+ # ========================
755
+ uninstall() {
756
+ local NO_CLEAR=false
757
+ local NO_PAUSE=false
758
+
759
+ if [ "$IS_REINSTALL" = false ]; then
760
+ if [[ ! -d /var/api/Mwsm || ! -f /var/api/Mwsm/package.json ]]; then
761
+ echo "-------------------------------------"
762
+ echo "⚠️ O Mwsm não está instalado!"
763
+ echo "-------------------------------------"
764
+ sleep 2
765
+ return
766
+ fi
767
+ fi
768
+
769
+
770
+ if [ "$1" = "no_clear" ]; then
771
+ NO_CLEAR=true
772
+ fi
773
+ if [ "$2" = "no_pause" ]; then
774
+ NO_PAUSE=true
775
+ fi
776
+
777
+ # Cabeçalho
778
+ if [ "$NO_CLEAR" = false ]; then
779
+ clear
780
+ echo "====================================="
781
+ echo " 🗑️ Removendo Mwsm"
782
+ echo "====================================="
783
+ fi
784
+
785
+ UNINSTALL_FAILED=false
786
+
787
+ # Parando serviços PM2
788
+ if command -v pm2 >/dev/null 2>&1; then
789
+ run_step "$SUDO pm2 stop all && $SUDO pm2 delete all" "Removendo serviços" uninstall || UNINSTALL_FAILED=true
790
+ else
791
+ run_step "skip" "Removendo serviços" uninstall
792
+ fi
793
+
794
+ # Removendo inicialização
795
+ if command -v pm2 >/dev/null 2>&1; then
796
+ if [[ "$DISTRO" == "ubuntu" ]]; then
797
+ run_step "$SUDO pm2 unstartup systemd" "Removendo inicialização" uninstall || UNINSTALL_FAILED=true
798
+ else
799
+ run_step "crontab -l 2>/dev/null | grep -v '/var/api/Mwsm/mwsm.js' | crontab -" "Removendo inicialização" uninstall || UNINSTALL_FAILED=true
800
+ fi
801
+ else
802
+ run_step "skip" "Removendo inicialização" uninstall
803
+ fi
804
+
805
+ # Removendo PM2 global
806
+ if command -v pm2 >/dev/null 2>&1; then
807
+ run_step "$SUDO npm remove -g pm2" "Removendo PM2" uninstall || UNINSTALL_FAILED=true
808
+ else
809
+ run_step "skip" "Removendo PM2" uninstall
810
+ fi
811
+
812
+ # Limpando cache do NPM
813
+ if command -v npm >/dev/null 2>&1; then
814
+ if [ -d "$HOME/.npm" ]; then
815
+ run_step "cd /tmp && $SUDO npm cache clean --force" "Limpando cache NPM" uninstall || UNINSTALL_FAILED=true
816
+ else
817
+ run_step "skip" "Limpando cache NPM" uninstall
818
+ fi
819
+ else
820
+ run_step "skip" "Limpando cache NPM" uninstall
821
+ fi
822
+
823
+
824
+ # Limpando diretórios
825
+ if [[ -d /var/api/Mwsm ]]; then
826
+ [[ "$PWD" =~ /var/api/Mwsm ]] && cd /root 2>/dev/null || cd /tmp
827
+ run_step "rm -rf /var/api/Mwsm" "Limpando diretórios" uninstall || UNINSTALL_FAILED=true
828
+ else
829
+ run_step "skip" "Limpando diretórios" uninstall
830
+ fi
831
+
832
+ if [ -L /usr/local/bin/mwsm ] || [ -f /usr/local/bin/mwsm ]; then
833
+ rm -f /usr/local/bin/mwsm 2>/dev/null || $SUDO rm -f /usr/local/bin/mwsm
834
+ fi
835
+
836
+ # Exibe resultado final
837
+ if [ "$NO_PAUSE" = false ]; then
838
+ if [ "$UNINSTALL_FAILED" = false ]; then
839
+ echo "-------------------------------------"
840
+ echo "✅ Remoção concluída!"
841
+ echo "-------------------------------------"
842
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [UNINSTALL] Fim da remoção (OK)" >>"$LOG_FILE"
843
+ else
844
+ echo "-------------------------------------"
845
+ echo "❌ Falha na remoção."
846
+ echo "-------------------------------------"
847
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [UNINSTALL] Fim da remoção (FAIL)" >>"$LOG_FILE"
848
+ fi
849
+ else
850
+ if [ "$UNINSTALL_FAILED" = false ]; then
851
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [UNINSTALL] Fim da remoção (OK - modo silencioso)" >>"$LOG_FILE"
852
+ else
853
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [UNINSTALL] Fim da remoção (FAIL - modo silencioso)" >>"$LOG_FILE"
854
+ fi
855
+ fi
856
+
857
+ if [ "$NO_PAUSE" = true ]; then
858
+ return
859
+ fi
860
+
861
+ echo
862
+ if [ "$NO_PAUSE" = false ]; then
863
+ pause_and_restore
864
+ fi
865
+ }
866
+
867
+ # ========================
868
+ # Reinstalar
869
+ # ========================
870
+ reinstall() {
871
+ INSTALL_FAILED=false
872
+ IS_REINSTALL=true
873
+
874
+ clear
875
+ echo "====================================="
876
+ echo " ♻️ Reinstalando Mwsm"
877
+ echo "====================================="
878
+
879
+ if ! uninstall_concluido; then
880
+ uninstall no_clear no_pause
881
+ fi
882
+
883
+ install no_clear no_pause
884
+
885
+ echo
886
+ echo "-------------------------------------"
887
+ if [ "$INSTALL_FAILED" = false ]; then
888
+ echo "✅ Reinstalação concluída!"
889
+ echo "-------------------------------------"
890
+ LAST_SUCCESS="install"
891
+ else
892
+ echo "❌ Reinstalação concluída com falhas."
893
+ echo "-------------------------------------"
894
+ fi
895
+
896
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [REINSTALL] Fim da reinstalação (status: $([ "$INSTALL_FAILED" = true ] && echo FAIL || echo OK))" >>"$LOG_FILE"
897
+ echo
898
+ pause_and_restore
899
+ }
900
+
901
+ view_log_hidden() {
902
+ while true; do
903
+ clear
904
+ echo "====================================="
905
+ echo " 📜 Logs do Mwsm"
906
+ echo "====================================="
907
+ echo "1) Últimas 24h"
908
+ echo "2) Completo"
909
+ echo "3) Bruto"
910
+ echo "0) Voltar"
911
+ echo "-------------------------------------"
912
+ printf "Escolha uma opção: "
913
+
914
+ # Lê uma única tecla (sem Enter) e só aceita 0–3
915
+ while true; do
916
+ read -rsn1 log_choice
917
+ case "$log_choice" in
918
+ [0-3]) break ;;
919
+ *) continue ;;
920
+ esac
921
+ done
922
+ echo "$log_choice"
923
+
924
+ case $log_choice in
925
+ 1)
926
+ cutoff_epoch=$(date -d '24 hours ago' +%s)
927
+ # awk: encontra a primeira timestamp válida em cada linha, converte e compara
928
+ awk -v cutoff="$cutoff_epoch" '
929
+ {
930
+ if (match($0, /[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]/)) {
931
+ ts = substr($0, RSTART, RLENGTH)
932
+ cmd = "date -d \"" ts "\" +%s"
933
+ cmd | getline t
934
+ close(cmd)
935
+ if (t >= cutoff) print $0
936
+ }
937
+ }' "$LOG_FILE" | iconv -f utf-8 -t utf-8
938
+
939
+ printf "\\nPressione ENTER para voltar ao menu principal..."
940
+ IFS= read -r _
941
+ break
942
+ ;;
943
+ 2)
944
+ cat "$LOG_FILE" | grep "^[0-9]\\{4\\}-" | iconv -f utf-8 -t utf-8
945
+ printf "\\nPressione ENTER para voltar ao menu principal..."
946
+ IFS= read -r _
947
+ break
948
+ ;;
949
+ 3)
950
+ cat "$LOG_FILE" | grep -v "^[0-9]\\{4\\}-" | iconv -f utf-8 -t utf-8
951
+ printf "\\nPressione ENTER para voltar ao menu principal..."
952
+ IFS= read -r _
953
+ break
954
+ ;;
955
+ 0)
956
+ break
957
+ ;;
958
+ esac
959
+ done
960
+ }
961
+
962
+ # ========================
963
+ # Limpar logs oculto
964
+ # ========================
965
+ clear_log_hidden() {
966
+ : >"$LOG_FILE"
967
+ echo "-------------------------------------"
968
+ echo "🧹 Log limpo com sucesso!"
969
+ echo "-------------------------------------"
970
+ sleep 2
971
+ }
972
+
973
+ # ========================
974
+ # Menu principal
975
+ # ========================
976
+ menu() {
977
+ # Desativa o cursor logo no início, antes de qualquer saída
978
+ command -v tput >/dev/null 2>&1 && tput civis >/dev/null 2>&1 || true
979
+
980
+ while true; do
981
+ if [ -t 0 ]; then
982
+ stty -echo -icanon time 0 min 0 || true
983
+ fi
984
+
985
+ clear
986
+
987
+ echo "====================================="
988
+ echo " 📦 Gerenciador do Bot-Mwsm"
989
+ echo "====================================="
990
+ echo "1) Instalar"
991
+ echo "2) Atualizar"
992
+ echo "3) Reinstalar"
993
+ echo "4) Desinstalar"
994
+ echo "0) Sair"
995
+ echo "-------------------------------------"
996
+ printf "Escolha uma opção: "
997
+
998
+ # Mantém o cursor oculto o tempo todo
999
+ command -v tput >/dev/null 2>&1 && tput civis >/dev/null 2>&1 || true
1000
+
1001
+ # Lê uma única tecla (sem Enter)
1002
+ while true; do
1003
+ read -rsn1 choice
1004
+ case "$choice" in
1005
+ [0-6]) break ;; # aceita apenas 0–6
1006
+ *) continue ;; # ignora qualquer outra tecla
1007
+ esac
1008
+ done
1009
+
1010
+ echo "$choice"
1011
+
1012
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - [MENU] Opção $choice selecionada" >>"$LOG_FILE"
1013
+
1014
+ case $choice in
1015
+ 1) install ;;
1016
+ 2) update ;;
1017
+ 3) reinstall ;;
1018
+ 4) uninstall ;;
1019
+ 5) view_log_hidden ;; # oculto
1020
+ 6) clear_log_hidden ;; # oculto
1021
+ 0)
1022
+ # Reativa o cursor antes de sair
1023
+ command -v tput >/dev/null 2>&1 && tput cnorm >/dev/null 2>&1 || true
1024
+ if [[ "$LAST_SUCCESS" == "install" ]]; then
1025
+ if command -v pm2 >/dev/null 2>&1; then
1026
+ NAME=$(jq -r .name /var/api/Mwsm/package.json 2>/dev/null)
1027
+ MATCHED=""
1028
+
1029
+ if [[ -n "$NAME" && -f /var/api/Mwsm/mwsm.json ]]; then
1030
+ if jq -r 'tostring' /var/api/Mwsm/mwsm.json 2>/dev/null | grep -q "$NAME"; then
1031
+ MATCHED="$NAME"
1032
+ fi
1033
+ fi
1034
+
1035
+ if [[ -z "$MATCHED" ]]; then
1036
+ if $SUDO pm2 list | grep -q "Bot-Mwsm"; then
1037
+ MATCHED="Bot-Mwsm"
1038
+ fi
1039
+ fi
1040
+
1041
+ if [[ -n "$MATCHED" ]]; then
1042
+ $SUDO pm2 update >/dev/null 2>&1
1043
+ $SUDO pm2 flush >/dev/null 2>&1
1044
+ clear
1045
+ exec $SUDO pm2 logs "$MATCHED"
1046
+ fi
1047
+ fi
1048
+ fi
1049
+ unset DEBIAN_FRONTEND
1050
+ clear
1051
+ silent_menu
1052
+ exit 0
1053
+ ;;
1054
+ esac
1055
+ done
1056
+
1057
+ command -v tput >/dev/null 2>&1 && tput cnorm >/dev/null 2>&1 || true
1058
+ }
1059
+
1060
+ menu