Abdelrhman2008 commited on
Commit
88739ff
·
verified ·
1 Parent(s): 3f98e3c

Update sync_data.sh

Browse files
Files changed (1) hide show
  1. sync_data.sh +110 -238
sync_data.sh CHANGED
@@ -1,60 +1,39 @@
1
  #!/bin/bash
2
 
3
  # ========================================
4
- # Open WebUI GitHub Sync - Fixed v4
5
- # مزامنة ثنائية الاتجاه مُصححة
6
- # ========================================
7
- #
8
- # إصلاحات v4:
9
- # ✅ يقرأ من GitHub عند البداية وفي كل دورة
10
- # ✅ يرفع التغييرات المحلية بشكل صحيح
11
- # ✅ مقارنة Hash صحيحة (GitHub vs Local)
12
- # ✅ لا يخرج مبكراً بعد Pull
13
- # ✅ فصل واضح بين Pull و Push
14
  # ========================================
15
 
16
  set -eo pipefail
17
 
18
  # ========================================
19
- # الإعدادات الثابتة
20
  # ========================================
21
  readonly DB_FILE="/app/backend/data/webui.db"
22
  readonly DATA_DIR="./data"
23
  readonly TEMP_DIR="$DATA_DIR/git_temp"
24
- readonly LOCAL_HASH_FILE="$DATA_DIR/local_hash.txt" # Hash آخر نسخة محلية تم رفعها
25
- readonly GITHUB_HASH_FILE="$DATA_DIR/github_hash.txt" # Hash آخر نسخة من GitHub
26
  readonly BACKUP_DIR="$DATA_DIR/backups"
27
  readonly MAX_BACKUPS=5
28
- readonly SYNC_INTERVAL=3600 # ساعة واحدة
29
 
30
  # ========================================
31
- # دوال الـ Logging
32
  # ========================================
33
- log_info() {
34
- echo "[$(date '+%Y-%m-%d %H:%M:%S')] ℹ️ $1"
35
- }
36
-
37
- log_success() {
38
- echo "[$(date '+%Y-%m-%d %H:%M:%S')] ✅ $1"
39
- }
40
-
41
- log_error() {
42
- echo "[$(date '+%Y-%m-%d %H:%M:%S')] ❌ $1" >&2
43
- }
44
-
45
- log_warn() {
46
- echo "[$(date '+%Y-%m-%d %H:%M:%S')] ⚠️ $1"
47
- }
48
 
49
  # ========================================
50
- # التحقق من المتطلبات الأساسية
51
  # ========================================
52
  check_requirements() {
53
  log_info "التحقق من المتطلبات..."
54
 
55
  if [[ -z "${G_NAME:-}" ]]; then
56
  log_error "المتغير G_NAME غير موجود!"
57
- log_info "مثال: export G_NAME=username/repo-name"
58
  return 1
59
  fi
60
 
@@ -64,49 +43,37 @@ check_requirements() {
64
  fi
65
 
66
  if [[ ! "$G_NAME" =~ ^[^/]+/[^/]+$ ]]; then
67
- log_error "صيغة G_NAME غير صحيحة. يجب أن تكون: username/repo"
68
  return 1
69
  fi
70
 
71
- local token_length=${#G_TOKEN}
72
- if [[ $token_length -lt 40 ]]; then
73
- log_warn "Token قصير جداً ($token_length حرف)"
74
- fi
75
-
76
  mkdir -p "$DATA_DIR" "$BACKUP_DIR"
77
 
78
- log_success "جميع المتطلبات متوفرة"
79
- log_info "Repository: $G_NAME"
80
- log_info "Token: ${G_TOKEN:0:10}... ($token_length chars)"
81
-
82
  return 0
83
  }
84
 
85
  # ========================================
86
- # التحقق من صحة الـ Token
87
  # ========================================
88
  verify_token() {
89
- log_info "التحقق من صحة الـ Token..."
90
 
91
- local response
92
- response=$(curl -s -w "\n%{http_code}" \
93
  -H "Authorization: token $G_TOKEN" \
94
- -H "Accept: application/vnd.github.v3+json" \
95
  "https://api.github.com/repos/$G_NAME" 2>/dev/null)
96
 
97
- local http_code=$(echo "$response" | tail -n1)
98
-
99
  case $http_code in
100
  200) log_success "Token صحيح"; return 0 ;;
101
  401) log_error "Token غير صحيح"; return 1 ;;
102
  404) log_warn "المستودع غير موجود - سيتم إنشاؤه"; return 0 ;;
103
- 403) log_error "صلاحيات غير كافية"; return 1 ;;
104
  *) log_error "خطأ: HTTP $http_code"; return 1 ;;
105
  esac
106
  }
107
 
108
  # ========================================
109
- # حساب hash للملف
110
  # ========================================
111
  get_file_hash() {
112
  if [[ -f "$1" ]] && [[ -s "$1" ]]; then
@@ -117,74 +84,46 @@ get_file_hash() {
117
  }
118
 
119
  # ========================================
120
- # إنشاء نسخة احتياطية
121
  # ========================================
122
  create_backup() {
123
- local source_file="${1:-$DB_FILE}"
124
- local prefix="${2:-backup}"
125
-
126
- if [[ ! -f "$source_file" ]]; then
127
- return 1
128
- fi
129
 
130
  local backup_file="$BACKUP_DIR/${prefix}_$(date '+%Y%m%d_%H%M%S').db"
 
131
 
132
- if cp "$source_file" "$backup_file" 2>/dev/null; then
133
- log_info "نسخة احتياطية: $(basename "$backup_file")"
134
-
135
- # حذف القديمة
136
- local backup_count=$(ls -1 "$BACKUP_DIR"/*.db 2>/dev/null | wc -l)
137
- if [[ $backup_count -gt $MAX_BACKUPS ]]; then
138
- ls -1t "$BACKUP_DIR"/*.db | tail -n +$((MAX_BACKUPS + 1)) | xargs rm -f 2>/dev/null
139
- fi
140
- return 0
141
- fi
142
- return 1
143
  }
144
 
145
  # ========================================
146
- # جلب Hash من GitHub بدون تحميل الملف
147
  # ========================================
148
- get_github_hash() {
149
- local repo_url="https://${G_TOKEN}@github.com/${G_NAME}.git"
150
-
151
- rm -rf "$TEMP_DIR"
152
- mkdir -p "$TEMP_DIR"
153
-
154
- if GIT_TERMINAL_PROMPT=0 git clone --depth 1 --quiet "$repo_url" "$TEMP_DIR" 2>/dev/null; then
155
- if [[ -f "$TEMP_DIR/webui.db" ]] && [[ -s "$TEMP_DIR/webui.db" ]]; then
156
- local hash=$(get_file_hash "$TEMP_DIR/webui.db")
157
- echo "$hash"
158
- return 0
159
- fi
160
- fi
161
-
162
- echo "none"
163
- return 1
164
  }
165
 
166
  # ========================================
167
- # تحميل من GitHub (Pull)
168
  # ========================================
169
  pull_from_github() {
170
- log_info "⬇️ فحص GitHub للتحديثات..."
171
 
172
- local repo_url="https://${G_TOKEN}@github.com/${G_NAME}.git"
173
-
174
- rm -rf "$TEMP_DIR"
175
  mkdir -p "$TEMP_DIR"
176
 
177
- # Clone المستودع
 
178
  if ! GIT_TERMINAL_PROMPT=0 git clone --depth 1 --quiet "$repo_url" "$TEMP_DIR" 2>/dev/null; then
179
- log_info "المستودع غير موجود أو فارغ"
180
- rm -rf "$TEMP_DIR"
181
  return 1
182
  fi
183
 
184
- # التحقق من وجود الملف
185
  if [[ ! -f "$TEMP_DIR/webui.db" ]] || [[ ! -s "$TEMP_DIR/webui.db" ]]; then
186
  log_info "لا يوجد webui.db في GitHub"
187
- rm -rf "$TEMP_DIR"
188
  return 1
189
  fi
190
 
@@ -192,240 +131,174 @@ pull_from_github() {
192
  local local_hash=$(get_file_hash "$DB_FILE")
193
  local saved_github_hash=$(cat "$GITHUB_HASH_FILE" 2>/dev/null || echo "none")
194
 
195
- log_info "Hash GitHub: $github_hash"
196
- log_info "Hash Local: $local_hash"
197
- log_info "Hash GitHub سابق: $saved_github_hash"
198
 
199
- # هل GitHub تغير عن آخر مرة حملنا منه؟
200
  if [[ "$github_hash" != "$saved_github_hash" ]] && [[ "$github_hash" != "$local_hash" ]]; then
201
- log_info "🔄 يوجد تحديث جديد في GitHub!"
202
 
203
- # نسخة احتياطية من المحلي
204
- if [[ -f "$DB_FILE" ]]; then
205
- create_backup "$DB_FILE" "before_pull"
206
- fi
207
 
208
- # نسخ الملف
209
  mkdir -p "$(dirname "$DB_FILE")"
210
  cp "$TEMP_DIR/webui.db" "$DB_FILE"
211
  chmod 666 "$DB_FILE"
212
 
213
- # التحقق
214
- local copied_hash=$(get_file_hash "$DB_FILE")
215
- if [[ "$copied_hash" != "$github_hash" ]]; then
216
- log_error "فشل التحقق من الملف المنسوخ!"
217
- rm -rf "$TEMP_DIR"
218
- return 1
219
- fi
220
-
221
- # حفظ الـ hashes
222
  echo "$github_hash" > "$GITHUB_HASH_FILE"
223
  echo "$github_hash" > "$LOCAL_HASH_FILE"
224
 
225
  local size=$(du -h "$DB_FILE" | cut -f1)
226
- log_success "⬇️ تم تحميل التحديثات من GitHub (الحجم: $size)"
227
 
228
- rm -rf "$TEMP_DIR"
229
  return 0
230
- else
231
- log_info "✓ لا توجد تحديثات جديدة في GitHub"
232
- echo "$github_hash" > "$GITHUB_HASH_FILE"
233
- rm -rf "$TEMP_DIR"
234
- return 2
235
  fi
 
 
 
 
 
236
  }
237
 
238
  # ========================================
239
- # رفع إلى GitHub (Push)
240
  # ========================================
241
  push_to_github() {
242
- log_info "⬆️ فحص التغييرات المحلية للرفع..."
243
 
244
- # التحقق من وجود الملف
245
  if [[ ! -f "$DB_FILE" ]] || [[ ! -s "$DB_FILE" ]]; then
246
- log_warn "لا يوجد ملف محلي للرفع"
247
  return 1
248
  fi
249
 
250
  local current_hash=$(get_file_hash "$DB_FILE")
251
- local last_pushed_hash=$(cat "$LOCAL_HASH_FILE" 2>/dev/null || echo "none")
252
 
253
- log_info "Hash الحالي: $current_hash"
254
- log_info "Hash آخر رفع: $last_pushed_hash"
255
 
256
- # هل الملف المحلي تغير عن آخر رفع؟
257
- if [[ "$current_hash" == "$last_pushed_hash" ]]; then
258
- log_info "✓ لا توجد تغييرات محلية جديدة"
259
  return 0
260
  fi
261
 
262
- log_info "🔄 يوجد تغييرات محلية جديدة - جاري الرفع..."
 
263
 
264
- # نسخة احتياطية قبل الرفع
265
- create_backup "$DB_FILE" "before_push"
266
 
267
- local file_size=$(du -h "$DB_FILE" | cut -f1)
268
  local repo_url="https://${G_TOKEN}@github.com/${G_NAME}.git"
 
269
 
270
- rm -rf "$TEMP_DIR"
271
- mkdir -p "$TEMP_DIR"
272
-
273
- # Clone أو إنشاء repo
274
  if ! GIT_TERMINAL_PROMPT=0 git clone --depth 1 --quiet "$repo_url" "$TEMP_DIR" 2>/dev/null; then
275
- log_info "إنشاء مستودع جديد..."
276
  cd "$TEMP_DIR"
277
  git init --quiet
278
  git remote add origin "$repo_url"
279
-
280
- cat > README.md << 'EOF'
281
- # 🔄 Open WebUI Database Backup
282
- Automatic bidirectional sync every hour.
283
- EOF
284
  git add README.md
285
- git config user.name "OpenWebUI AutoSync"
286
- git config user.email "autosync@openwebui.local"
287
- git commit --quiet -m "🎉 Initial commit"
288
  git push --quiet -u origin HEAD:main 2>/dev/null || git push --quiet -u origin HEAD:master 2>/dev/null || true
289
  cd - > /dev/null
290
  fi
291
 
292
  cd "$TEMP_DIR"
 
 
293
 
294
- git config user.name "OpenWebUI AutoSync"
295
- git config user.email "autosync@openwebui.local"
296
-
297
- # نسخ الملف
298
  cp "$DB_FILE" ./webui.db
299
-
300
- # التحقق من النسخ
301
- local copied_hash=$(get_file_hash "./webui.db")
302
- if [[ "$copied_hash" != "$current_hash" ]]; then
303
- log_error "فشل التحقق من الملف المنسوخ!"
304
- cd - > /dev/null
305
- rm -rf "$TEMP_DIR"
306
- return 1
307
- fi
308
-
309
  git add webui.db
310
 
311
  if git diff --staged --quiet 2>/dev/null; then
312
- log_info "Git يقول لا توجد تغييرات"
313
  cd - > /dev/null
314
- rm -rf "$TEMP_DIR"
315
  echo "$current_hash" > "$LOCAL_HASH_FILE"
316
  return 0
317
  fi
318
 
319
- local commit_msg="⬆️ Sync: $(date '+%Y-%m-%d %H:%M:%S') | Size: $file_size | Hash: ${current_hash:0:8}"
 
320
 
321
- if git commit --quiet -m "$commit_msg"; then
322
- local max_retries=3
323
- local retry=0
324
-
325
- while [[ $retry -lt $max_retries ]]; do
326
- git pull --rebase --quiet origin main 2>/dev/null || \
327
- git pull --rebase --quiet origin master 2>/dev/null || true
328
-
329
- if git push --quiet origin HEAD:main 2>/dev/null || \
330
- git push --quiet origin HEAD:master 2>/dev/null; then
331
-
332
- echo "$current_hash" > "$LOCAL_HASH_FILE"
333
- echo "$current_hash" > "$GITHUB_HASH_FILE"
334
-
335
- log_success "⬆️ تم رفع التغييرات بنجاح! 🎉"
336
- cd - > /dev/null
337
- rm -rf "$TEMP_DIR"
338
- return 0
339
- fi
340
-
341
- retry=$((retry + 1))
342
- [[ $retry -lt $max_retries ]] && sleep 3
343
- done
344
-
345
- log_error "فشل الرفع بعد $max_retries محاولات"
346
  fi
347
 
 
348
  cd - > /dev/null
349
- rm -rf "$TEMP_DIR"
350
  return 1
351
  }
352
 
353
  # ========================================
354
- # دورة المزامنة الرئيسية
355
  # ========================================
356
  sync_cycle() {
357
  log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
358
- log_info "🔄 بدء دورة المزامنة الثنائية..."
359
 
360
- if [[ -f "$DB_FILE" ]]; then
361
- local db_size=$(du -h "$DB_FILE" | cut -f1)
362
- log_info "📊 حجم الملف المحلي: $db_size"
363
- fi
364
 
365
- # ===== الخطوة 1: Pull من GitHub =====
366
  pull_from_github
367
  local pull_result=$?
368
 
369
- # ===== الخطوة 2: Push إلى GitHub =====
370
- # نفعل Push بغض النظر عن نتيجة Pull
371
- # (ما عدا إذا كان Pull ناجح = 0، فالملف المحلي الآن = GitHub)
372
-
373
- if [[ $pull_result -eq 0 ]]; then
374
- # تم تحديث الملف المحلي من GitHub
375
- # لا حاجة للـ Push لأن المحلي = GitHub الآن
376
- log_info "✓ تم التحديث من GitHub - لا حاجة للرفع"
377
- else
378
- # إما لا يوجد تحديثات في GitHub (2) أو GitHub فارغ (1)
379
- # في كلتا الحالتين، نحاول Push
380
  push_to_github
 
 
381
  fi
382
 
383
- log_success "انتهت دورة المزامنة"
 
384
  }
385
 
386
  # ========================================
387
- # البرنامج الرئيسي
388
  # ========================================
389
  main() {
390
  log_info "=========================================="
391
- log_info " 🔄 Open WebUI ↔ GitHub Sync v4"
392
- log_info " ⏰ مزامنة ثنائية كل ساعة"
393
- log_info " ✅ يقرأ ويكتب بشكل صحيح"
394
  log_info "=========================================="
395
 
396
- if ! check_requirements; then
397
- log_error "فشل التحقق من المتطلبات"
398
- exit 1
399
- fi
400
-
401
- if ! verify_token; then
402
- log_error "Token غير صحيح"
403
- exit 1
404
- fi
405
 
406
- log_info "الانتظار 30 ثانية لبدء Open WebUI..."
407
  sleep 30
408
 
409
  # المزامنة الأولية
410
- log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
411
  log_info "🚀 المزامنة الأولية..."
412
  sync_cycle
413
 
414
- # حلقة المزامنة
415
  local cycle=0
416
  while true; do
417
  cycle=$((cycle + 1))
418
 
419
- log_info ""
420
- log_info "🔁 دورة المزامنة #$cycle"
421
-
422
- sync_cycle
423
-
424
- local next_sync=$(date -d "+${SYNC_INTERVAL} seconds" '+%H:%M:%S' 2>/dev/null || echo "بعد ساعة")
425
- log_info "⏰ المزامنة القادمة: $next_sync"
426
- log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
427
 
 
428
  sleep $SYNC_INTERVAL
 
 
 
 
 
429
  done
430
  }
431
 
@@ -433,7 +306,6 @@ main() {
433
  # التشغيل
434
  # ========================================
435
  main &
436
-
437
  SYNC_PID=$!
438
- log_info "تم بدء المزامنة (PID: $SYNC_PID)"
439
- echo $SYNC_PID > "$DATA_DIR/sync.pid"
 
1
  #!/bin/bash
2
 
3
  # ========================================
4
+ # Open WebUI GitHub Sync - Fixed v5
 
 
 
 
 
 
 
 
 
5
  # ========================================
6
 
7
  set -eo pipefail
8
 
9
  # ========================================
10
+ # الإعدادات
11
  # ========================================
12
  readonly DB_FILE="/app/backend/data/webui.db"
13
  readonly DATA_DIR="./data"
14
  readonly TEMP_DIR="$DATA_DIR/git_temp"
15
+ readonly LOCAL_HASH_FILE="$DATA_DIR/local_hash.txt"
16
+ readonly GITHUB_HASH_FILE="$DATA_DIR/github_hash.txt"
17
  readonly BACKUP_DIR="$DATA_DIR/backups"
18
  readonly MAX_BACKUPS=5
19
+ readonly SYNC_INTERVAL=3600
20
 
21
  # ========================================
22
+ # Logging
23
  # ========================================
24
+ log_info() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] ℹ️ $1"; }
25
+ log_success() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"; }
26
+ log_error() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] ❌ $1" >&2; }
27
+ log_warn() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] ⚠️ $1"; }
 
 
 
 
 
 
 
 
 
 
 
28
 
29
  # ========================================
30
+ # التحقق من المتطلبات
31
  # ========================================
32
  check_requirements() {
33
  log_info "التحقق من المتطلبات..."
34
 
35
  if [[ -z "${G_NAME:-}" ]]; then
36
  log_error "المتغير G_NAME غير موجود!"
 
37
  return 1
38
  fi
39
 
 
43
  fi
44
 
45
  if [[ ! "$G_NAME" =~ ^[^/]+/[^/]+$ ]]; then
46
+ log_error "صيغة G_NAME غير صحيحة"
47
  return 1
48
  fi
49
 
 
 
 
 
 
50
  mkdir -p "$DATA_DIR" "$BACKUP_DIR"
51
 
52
+ log_success "المتطلبات متوفرة | Repo: $G_NAME"
 
 
 
53
  return 0
54
  }
55
 
56
  # ========================================
57
+ # التحقق من Token
58
  # ========================================
59
  verify_token() {
60
+ log_info "التحقق من الـ Token..."
61
 
62
+ local http_code
63
+ http_code=$(curl -s -o /dev/null -w "%{http_code}" \
64
  -H "Authorization: token $G_TOKEN" \
 
65
  "https://api.github.com/repos/$G_NAME" 2>/dev/null)
66
 
 
 
67
  case $http_code in
68
  200) log_success "Token صحيح"; return 0 ;;
69
  401) log_error "Token غير صحيح"; return 1 ;;
70
  404) log_warn "المستودع غير موجود - سيتم إنشاؤه"; return 0 ;;
 
71
  *) log_error "خطأ: HTTP $http_code"; return 1 ;;
72
  esac
73
  }
74
 
75
  # ========================================
76
+ # حساب Hash
77
  # ========================================
78
  get_file_hash() {
79
  if [[ -f "$1" ]] && [[ -s "$1" ]]; then
 
84
  }
85
 
86
  # ========================================
87
+ # نسخة احتياطية
88
  # ========================================
89
  create_backup() {
90
+ local prefix="${1:-backup}"
91
+ [[ ! -f "$DB_FILE" ]] && return 1
 
 
 
 
92
 
93
  local backup_file="$BACKUP_DIR/${prefix}_$(date '+%Y%m%d_%H%M%S').db"
94
+ cp "$DB_FILE" "$backup_file" 2>/dev/null && log_info "Backup: $(basename "$backup_file")"
95
 
96
+ # تنظيف القديمة
97
+ ls -1t "$BACKUP_DIR"/*.db 2>/dev/null | tail -n +$((MAX_BACKUPS + 1)) | xargs rm -f 2>/dev/null || true
 
 
 
 
 
 
 
 
 
98
  }
99
 
100
  # ========================================
101
+ # تنظيف المجلد المؤقت
102
  # ========================================
103
+ cleanup_temp() {
104
+ rm -rf "$TEMP_DIR" 2>/dev/null || true
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  }
106
 
107
  # ========================================
108
+ # Pull من GitHub
109
  # ========================================
110
  pull_from_github() {
111
+ log_info "⬇️ فحص GitHub..."
112
 
113
+ cleanup_temp
 
 
114
  mkdir -p "$TEMP_DIR"
115
 
116
+ local repo_url="https://${G_TOKEN}@github.com/${G_NAME}.git"
117
+
118
  if ! GIT_TERMINAL_PROMPT=0 git clone --depth 1 --quiet "$repo_url" "$TEMP_DIR" 2>/dev/null; then
119
+ log_info "المستودع فارغ أو غير موجود"
120
+ cleanup_temp
121
  return 1
122
  fi
123
 
 
124
  if [[ ! -f "$TEMP_DIR/webui.db" ]] || [[ ! -s "$TEMP_DIR/webui.db" ]]; then
125
  log_info "لا يوجد webui.db في GitHub"
126
+ cleanup_temp
127
  return 1
128
  fi
129
 
 
131
  local local_hash=$(get_file_hash "$DB_FILE")
132
  local saved_github_hash=$(cat "$GITHUB_HASH_FILE" 2>/dev/null || echo "none")
133
 
134
+ log_info "GitHub: ${github_hash:0:16}... | Local: ${local_hash:0:16}..."
 
 
135
 
136
+ # هل GitHub مختلف؟
137
  if [[ "$github_hash" != "$saved_github_hash" ]] && [[ "$github_hash" != "$local_hash" ]]; then
138
+ log_info "🔄 تحديث جديد من GitHub!"
139
 
140
+ [[ -f "$DB_FILE" ]] && create_backup "before_pull"
 
 
 
141
 
 
142
  mkdir -p "$(dirname "$DB_FILE")"
143
  cp "$TEMP_DIR/webui.db" "$DB_FILE"
144
  chmod 666 "$DB_FILE"
145
 
 
 
 
 
 
 
 
 
 
146
  echo "$github_hash" > "$GITHUB_HASH_FILE"
147
  echo "$github_hash" > "$LOCAL_HASH_FILE"
148
 
149
  local size=$(du -h "$DB_FILE" | cut -f1)
150
+ log_success "⬇️ تم التحميل من GitHub ($size)"
151
 
152
+ cleanup_temp
153
  return 0
 
 
 
 
 
154
  fi
155
+
156
+ log_info "✓ النسخة المحلية محدّثة"
157
+ echo "$github_hash" > "$GITHUB_HASH_FILE"
158
+ cleanup_temp
159
+ return 2
160
  }
161
 
162
  # ========================================
163
+ # Push إلى GitHub
164
  # ========================================
165
  push_to_github() {
166
+ log_info "⬆️ فحص التغييرات المحلية..."
167
 
 
168
  if [[ ! -f "$DB_FILE" ]] || [[ ! -s "$DB_FILE" ]]; then
169
+ log_warn "لا يوجد ملف محلي"
170
  return 1
171
  fi
172
 
173
  local current_hash=$(get_file_hash "$DB_FILE")
174
+ local last_pushed=$(cat "$LOCAL_HASH_FILE" 2>/dev/null || echo "none")
175
 
176
+ log_info "Current: ${current_hash:0:16}... | Last Push: ${last_pushed:0:16}..."
 
177
 
178
+ if [[ "$current_hash" == "$last_pushed" ]]; then
179
+ log_info " لا توجد تغييرات للرفع"
 
180
  return 0
181
  fi
182
 
183
+ log_info "🔄 رفع التغييرات..."
184
+ create_backup "before_push"
185
 
186
+ cleanup_temp
187
+ mkdir -p "$TEMP_DIR"
188
 
 
189
  local repo_url="https://${G_TOKEN}@github.com/${G_NAME}.git"
190
+ local file_size=$(du -h "$DB_FILE" | cut -f1)
191
 
192
+ # Clone أو init
 
 
 
193
  if ! GIT_TERMINAL_PROMPT=0 git clone --depth 1 --quiet "$repo_url" "$TEMP_DIR" 2>/dev/null; then
 
194
  cd "$TEMP_DIR"
195
  git init --quiet
196
  git remote add origin "$repo_url"
197
+ echo "# Open WebUI Backup" > README.md
 
 
 
 
198
  git add README.md
199
+ git config user.name "AutoSync"
200
+ git config user.email "sync@local"
201
+ git commit --quiet -m "Init" 2>/dev/null || true
202
  git push --quiet -u origin HEAD:main 2>/dev/null || git push --quiet -u origin HEAD:master 2>/dev/null || true
203
  cd - > /dev/null
204
  fi
205
 
206
  cd "$TEMP_DIR"
207
+ git config user.name "AutoSync"
208
+ git config user.email "sync@local"
209
 
 
 
 
 
210
  cp "$DB_FILE" ./webui.db
 
 
 
 
 
 
 
 
 
 
211
  git add webui.db
212
 
213
  if git diff --staged --quiet 2>/dev/null; then
214
+ log_info "Git: لا تغييرات"
215
  cd - > /dev/null
216
+ cleanup_temp
217
  echo "$current_hash" > "$LOCAL_HASH_FILE"
218
  return 0
219
  fi
220
 
221
+ local msg="Sync $(date '+%Y-%m-%d %H:%M') | $file_size"
222
+ git commit --quiet -m "$msg" 2>/dev/null
223
 
224
+ # Pull ثم Push
225
+ git pull --rebase --quiet origin main 2>/dev/null || git pull --rebase --quiet origin master 2>/dev/null || true
226
+
227
+ if git push --quiet origin HEAD:main 2>/dev/null || git push --quiet origin HEAD:master 2>/dev/null; then
228
+ echo "$current_hash" > "$LOCAL_HASH_FILE"
229
+ echo "$current_hash" > "$GITHUB_HASH_FILE"
230
+ log_success "⬆️ تم الرفع بنجاح!"
231
+ cd - > /dev/null
232
+ cleanup_temp
233
+ return 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  fi
235
 
236
+ log_error "فشل الرفع"
237
  cd - > /dev/null
238
+ cleanup_temp
239
  return 1
240
  }
241
 
242
  # ========================================
243
+ # دورة المزامنة
244
  # ========================================
245
  sync_cycle() {
246
  log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
247
+ log_info "🔄 دورة المزامنة"
248
 
249
+ [[ -f "$DB_FILE" ]] && log_info "📊 DB Size: $(du -h "$DB_FILE" | cut -f1)"
 
 
 
250
 
251
+ # Pull
252
  pull_from_github
253
  local pull_result=$?
254
 
255
+ # Push فقط إذا لم يتم التحديث من GitHub
256
+ if [[ $pull_result -ne 0 ]]; then
 
 
 
 
 
 
 
 
 
257
  push_to_github
258
+ else
259
+ log_info "✓ تم التحديث من GitHub"
260
  fi
261
 
262
+ log_success "انتهت الدورة"
263
+ log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
264
  }
265
 
266
  # ========================================
267
+ # Main
268
  # ========================================
269
  main() {
270
  log_info "=========================================="
271
+ log_info " 🔄 Open WebUI ↔ GitHub Sync v5"
272
+ log_info " ⏰ كل ساعة"
 
273
  log_info "=========================================="
274
 
275
+ check_requirements || exit 1
276
+ verify_token || exit 1
 
 
 
 
 
 
 
277
 
278
+ log_info "انتظار 30 ثانية..."
279
  sleep 30
280
 
281
  # المزامنة الأولية
 
282
  log_info "🚀 المزامنة الأولية..."
283
  sync_cycle
284
 
285
+ # الحلقة الرئيسية
286
  local cycle=0
287
  while true; do
288
  cycle=$((cycle + 1))
289
 
290
+ # حساب وقت المزامنة القادمة
291
+ local next_time=$(date -d "+1 hour" '+%H:%M:%S' 2>/dev/null || echo "بعد ساعة")
292
+ log_info "⏰ المزامنة القادمة #$((cycle+1)) في: $next_time"
293
+ log_info "💤 انتظار $SYNC_INTERVAL ثانية..."
 
 
 
 
294
 
295
+ # الانتظار
296
  sleep $SYNC_INTERVAL
297
+
298
+ # دورة جديدة
299
+ log_info ""
300
+ log_info "🔁 دورة #$((cycle+1))"
301
+ sync_cycle
302
  done
303
  }
304
 
 
306
  # التشغيل
307
  # ========================================
308
  main &
 
309
  SYNC_PID=$!
310
+ echo $SYNC_PID > "$DATA_DIR/sync.pid" 2>/dev/null || true
311
+ log_info "🚀 بدأت المزامنة (PID: $SYNC_PID)"