Opera8 commited on
Commit
8166d74
·
verified ·
1 Parent(s): 881a092

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +36 -78
main.py CHANGED
@@ -93,7 +93,7 @@ def gregorian_to_jalali(gy, gm, gd):
93
  return jy, jm, jd
94
 
95
  # ==============================================================================
96
- # 🟢 پارت 4: دیتابیس SQLite (نسخه مجهز به موتور تعمیر خودکار و استخراج داده)
97
  # ==============================================================================
98
  import os
99
  import sqlite3
@@ -102,6 +102,7 @@ import copy
102
  import threading
103
 
104
  DB_FILE = "/data/users_v3.db"
 
105
  BACKUP_JSON = "/data/users_db.json.bak"
106
 
107
  last_saved_state = {}
@@ -111,72 +112,32 @@ recent_messages_dict = {}
111
  db_lock = threading.Lock()
112
  msg_cache_lock = threading.Lock()
113
 
114
- def auto_repair_database():
115
- print("🛠 در حال بازسازی فایل دیتابیس آسیب‌دیده...")
116
- corrupt_backup = DB_FILE + ".corrupt"
117
-
118
- # 1. تغییر نام فایل خراب به فایل بکاپ
119
- for ext in["", "-wal", "-shm"]:
120
- if os.path.exists(DB_FILE + ext):
121
- try:
122
- if ext == "":
123
- if os.path.exists(corrupt_backup): os.remove(corrupt_backup)
124
- os.rename(DB_FILE, corrupt_backup)
125
- else:
126
- os.remove(DB_FILE + ext)
127
- except Exception: pass
128
-
129
- # 2. ساخت دیتابیس تمیز و جدید
130
- conn = sqlite3.connect(DB_FILE, timeout=60.0)
131
- conn.execute('PRAGMA journal_mode=WAL;')
132
- conn.execute('CREATE TABLE IF NOT EXISTS users (chat_id TEXT PRIMARY KEY, user_data TEXT)')
133
-
134
- # 3. تلاش برای استخراج تمام داده‌های سالم از فایل خراب به دیتابیس جدید
135
- recovered = 0
136
- if os.path.exists(corrupt_backup):
137
- try:
138
- conn.execute(f"ATTACH DATABASE '{corrupt_backup}' AS old_db")
139
- conn.execute("INSERT OR IGNORE INTO users SELECT * FROM old_db.users")
140
- conn.commit()
141
- cursor = conn.cursor()
142
- cursor.execute("SELECT COUNT(*) FROM users")
143
- recovered = cursor.fetchone()[0]
144
- conn.execute("DETACH DATABASE old_db")
145
- except Exception as e:
146
- print(f"⚠️ استخراج با خطا مواجه شد، اما داده‌های سالم نجات یافتند: {e}")
147
-
148
- conn.close()
149
- print(f"✅ فایل بازسازی شد! تعداد {recovered} کاربر با موفقیت از فایل آسیب‌دیده استخراج شدند.")
150
-
151
- # 4. در نهایت از فایل متنی JSON هم بازیابی می‌کنیم تا هیچکس جا نماند
152
- restore_users_from_json()
153
-
154
  def init_sqlite_db():
155
  try:
156
  os.makedirs(os.path.dirname(DB_FILE), exist_ok=True)
157
  is_first_run = not os.path.exists(DB_FILE)
158
 
159
  conn = sqlite3.connect(DB_FILE, timeout=60.0)
160
- try:
161
- # 🚀 تنظیمات سرعت دیتابیس
162
- conn.execute('PRAGMA journal_mode=WAL;')
163
- conn.execute('PRAGMA synchronous=NORMAL;')
164
- conn.execute('CREATE TABLE IF NOT EXISTS users (chat_id TEXT PRIMARY KEY, user_data TEXT)')
165
- conn.execute('DROP TABLE IF EXISTS processed_messages')
166
- conn.commit()
167
- conn.execute('VACUUM')
168
- except sqlite3.DatabaseError as e:
169
- if "malformed" in str(e).lower():
170
- # اگر دیتابیس خراب بود، موتور تعمیر خودکار روشن میشود
171
- conn.close()
172
- auto_repair_database()
173
- return
174
- except Exception: pass
175
- finally:
176
- try: conn.close()
177
- except: pass
178
 
179
  if is_first_run:
 
180
  restore_users_from_json()
181
 
182
  except Exception as e:
@@ -184,7 +145,7 @@ def init_sqlite_db():
184
 
185
  def restore_users_from_json():
186
  if os.path.exists(BACKUP_JSON):
187
- print("📥 در حال بازیابی اعتبار کاربران از فایل پشتیبان JSON...")
188
  try:
189
  with open(BACKUP_JSON, "r", encoding="utf-8") as f:
190
  data = json.load(f)
@@ -192,10 +153,10 @@ def restore_users_from_json():
192
  conn = sqlite3.connect(DB_FILE, timeout=60.0)
193
  conn.execute('PRAGMA journal_mode=WAL;')
194
  for cid, udata in data.items():
195
- conn.execute("INSERT OR IGNORE INTO users VALUES (?, ?)", (str(cid), json.dumps(udata)))
196
  conn.commit()
197
  conn.close()
198
- print(f"✅ اعتبار {len(data)} کاربر از فایل JSON بازیابی شد.")
199
  except Exception as e:
200
  print(f"❌ خطا در بازیابی اعتبارها: {e}")
201
 
@@ -208,7 +169,7 @@ def load_db():
208
  conn.execute('PRAGMA journal_mode=WAL;')
209
  cursor = conn.cursor()
210
 
211
- # 🟢 فقط لود کردن اطلاعات کاربران
212
  cursor.execute("SELECT chat_id, user_data FROM users")
213
  for row in cursor.fetchall():
214
  db_dict[row[0]] = json.loads(row[1])
@@ -231,17 +192,12 @@ def background_save_worker(changed_data):
231
  conn.executemany("INSERT OR REPLACE INTO users (chat_id, user_data) VALUES (?, ?)", changed_data)
232
  conn.commit()
233
  conn.close()
234
- except sqlite3.DatabaseError as e:
235
- # مانیتورینگ زنده: اگر وسط کار فایل خراب شد سریعاً تعمیر می‌شود
236
- if "malformed" in str(e).lower():
237
- print("❌ دیتابیس هنگام ذخیره خراب شد! در حال تعمیر خودکار...")
238
- auto_repair_database()
239
  except Exception as e:
240
  print(f"❌ خطا در ذخیره بک‌گراند: {e}")
241
 
242
  def save_db(db_data):
243
  global last_saved_state
244
- changed =[]
245
  for cid, data in db_data.items():
246
  if cid not in last_saved_state or last_saved_state[cid] != data:
247
  changed.append((str(cid), json.dumps(data, ensure_ascii=False)))
@@ -256,16 +212,22 @@ def save_db(db_data):
256
 
257
  # --- سیستم ضد تکرار پیام کاملاً منتقل شده به RAM ---
258
  def is_message_processed(message_id):
 
259
  return str(message_id) in recent_messages_dict
260
 
261
  def mark_message_processed(message_id):
262
  msg_id_str = str(message_id)
263
  with msg_cache_lock:
 
264
  recent_messages_dict[msg_id_str] = True
 
 
265
  if len(recent_messages_dict) > 15000:
266
  oldest_key = next(iter(recent_messages_dict))
267
  del recent_messages_dict[oldest_key]
268
 
 
 
269
  # ==============================================================================
270
  # 🟢 پارت 5: توابع کد معرف، مدیریت سهمیه حساب کاربری و تبدیل اعداد
271
  # ==============================================================================
@@ -2166,12 +2128,12 @@ else:
2166
  except Exception:
2167
  pass
2168
 
 
 
 
2169
  if is_old:
2170
- # پیام‌های تلنبار شده و قدیمی اصلا در دیتابیس و حافظه ذخیره نمی‌شوند و درجا دور ریخته می‌شوند
2171
  return
2172
-
2173
- # ربات فقط شناسه‌های پیام‌های کاملاً جدید را در کش رم ذخیره می‌کند
2174
- mark_message_processed(str_msg_id)
2175
  # ===================================================================
2176
 
2177
  user_text = getattr(update, "text", "") or getattr(msg_obj, "text", "")
@@ -2346,11 +2308,7 @@ else:
2346
  payload = {"chat_id": chat_id, "text": join_msg, "chat_keypad_type": "New", "chat_keypad": JOIN_KEYPAD_DICT}
2347
  await client._make_request("sendMessage", payload)
2348
  except Exception:
2349
- # 🔴 رفع خطای مسدودیت: اگر کاربر ربات را بلاک کرده باشد و خطا دهد، ربات با آرامش عبور میکن��.
2350
- try:
2351
- await client.send_message(chat_id, join_msg)
2352
- except Exception:
2353
- pass
2354
  return
2355
 
2356
  if user_text_lower.startswith("/start"):
 
93
  return jy, jm, jd
94
 
95
  # ==============================================================================
96
+ # 🟢 پارت 4: دیتابیس SQLite (نسخه فوق‌سریع - فقط RAM برای پیام‌ها + پاکسازی هارد)
97
  # ==============================================================================
98
  import os
99
  import sqlite3
 
102
  import threading
103
 
104
  DB_FILE = "/data/users_v3.db"
105
+ CORRUPT_FILE = "/data/users_db.db"
106
  BACKUP_JSON = "/data/users_db.json.bak"
107
 
108
  last_saved_state = {}
 
112
  db_lock = threading.Lock()
113
  msg_cache_lock = threading.Lock()
114
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  def init_sqlite_db():
116
  try:
117
  os.makedirs(os.path.dirname(DB_FILE), exist_ok=True)
118
  is_first_run = not os.path.exists(DB_FILE)
119
 
120
  conn = sqlite3.connect(DB_FILE, timeout=60.0)
121
+ cursor = conn.cursor()
122
+
123
+ # 🚀 تنظیمات سرعت دیتابیس
124
+ cursor.execute('PRAGMA journal_mode=WAL;')
125
+ cursor.execute('PRAGMA synchronous=NORMAL;')
126
+
127
+ # 1️⃣ اطمینان از وجود و سلامت جدول کاربران (اطلاعات اصلی که نباید پاک شود)
128
+ cursor.execute('CREATE TABLE IF NOT EXISTS users (chat_id TEXT PRIMARY KEY, user_data TEXT)')
129
+
130
+ # 2️⃣ حذف جدول شناسه‌های قدیمی پیام‌ها برای همیشه
131
+ cursor.execute('DROP TABLE IF EXISTS processed_messages')
132
+ conn.commit()
133
+
134
+ # 3️⃣ آزادسازی فضای هارد دیسک و کاهش حجم فایل دیتابیس (حذف فیزیکی شناسه‌های قدیمی)
135
+ conn.execute('VACUUM')
136
+
137
+ conn.close()
 
138
 
139
  if is_first_run:
140
+ print("🚨 عملیات نجات آغاز شد...")
141
  restore_users_from_json()
142
 
143
  except Exception as e:
 
145
 
146
  def restore_users_from_json():
147
  if os.path.exists(BACKUP_JSON):
148
+ print("📥 در حال بازیابی اعتبار کاربران از فایل پشتیبان...")
149
  try:
150
  with open(BACKUP_JSON, "r", encoding="utf-8") as f:
151
  data = json.load(f)
 
153
  conn = sqlite3.connect(DB_FILE, timeout=60.0)
154
  conn.execute('PRAGMA journal_mode=WAL;')
155
  for cid, udata in data.items():
156
+ conn.execute("INSERT OR REPLACE INTO users VALUES (?, ?)", (str(cid), json.dumps(udata)))
157
  conn.commit()
158
  conn.close()
159
+ print(f"✅ اعتبار {len(data)} کاربر با موفقیت بازیابی شد.")
160
  except Exception as e:
161
  print(f"❌ خطا در بازیابی اعتبارها: {e}")
162
 
 
169
  conn.execute('PRAGMA journal_mode=WAL;')
170
  cursor = conn.cursor()
171
 
172
+ # 🟢 فقط لود کردن اطلاعات کاربران (بدون دست زدن به شناسه‌های پیام)
173
  cursor.execute("SELECT chat_id, user_data FROM users")
174
  for row in cursor.fetchall():
175
  db_dict[row[0]] = json.loads(row[1])
 
192
  conn.executemany("INSERT OR REPLACE INTO users (chat_id, user_data) VALUES (?, ?)", changed_data)
193
  conn.commit()
194
  conn.close()
 
 
 
 
 
195
  except Exception as e:
196
  print(f"❌ خطا در ذخیره بک‌گراند: {e}")
197
 
198
  def save_db(db_data):
199
  global last_saved_state
200
+ changed = []
201
  for cid, data in db_data.items():
202
  if cid not in last_saved_state or last_saved_state[cid] != data:
203
  changed.append((str(cid), json.dumps(data, ensure_ascii=False)))
 
212
 
213
  # --- سیستم ضد تکرار پیام کاملاً منتقل شده به RAM ---
214
  def is_message_processed(message_id):
215
+ # چک کردن داخل RAM در کسری از ثانیه
216
  return str(message_id) in recent_messages_dict
217
 
218
  def mark_message_processed(message_id):
219
  msg_id_str = str(message_id)
220
  with msg_cache_lock:
221
+ # ثبت فقط در RAM
222
  recent_messages_dict[msg_id_str] = True
223
+
224
+ # جلوگیری از پر شدن بیش از حد RAM (نگه داشتن فقط 15000 پیام آخر)
225
  if len(recent_messages_dict) > 15000:
226
  oldest_key = next(iter(recent_messages_dict))
227
  del recent_messages_dict[oldest_key]
228
 
229
+ user_credits_db = load_db()
230
+
231
  # ==============================================================================
232
  # 🟢 پارت 5: توابع کد معرف، مدیریت سهمیه حساب کاربری و تبدیل اعداد
233
  # ==============================================================================
 
2128
  except Exception:
2129
  pass
2130
 
2131
+ # پیام چه قدیمی باشد چه جدید، در دیتابیس ثبت می‌شود که دیگر خوانده نشود
2132
+ mark_message_processed(str_msg_id)
2133
+
2134
  if is_old:
2135
+ # پیام تلنبار شده و قدیمی است، کاملا بیسروصدا دور ریخته می‌شود (بدون جواب دادن)
2136
  return
 
 
 
2137
  # ===================================================================
2138
 
2139
  user_text = getattr(update, "text", "") or getattr(msg_obj, "text", "")
 
2308
  payload = {"chat_id": chat_id, "text": join_msg, "chat_keypad_type": "New", "chat_keypad": JOIN_KEYPAD_DICT}
2309
  await client._make_request("sendMessage", payload)
2310
  except Exception:
2311
+ await client.send_message(chat_id, join_msg)
 
 
 
 
2312
  return
2313
 
2314
  if user_text_lower.startswith("/start"):