import os, shutil import time import subprocess import json from datetime import datetime import psutil import stat # اطلاعات Gitea شما REPO_DIR = "bot_ea_db" GIT_REPO = "http://pythonkoft:2f135dee41b069f92413dd3f234e12cb8c20a96a@188.245.173.247:3080/pythonkoft/ea_shadow.git" LOG_FILE = "log.json" LAST_COMMIT_FILE = "last_commit.txt" PROCESS_NAME = "main.bat" PID_FILE = "main_pid.txt" def write_log(event, message): log_entry = { "time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "event": event, "message": message } if not os.path.exists(LOG_FILE): with open(LOG_FILE, "w", encoding="utf-8") as f: json.dump([log_entry], f, ensure_ascii=False, indent=2) else: try: with open(LOG_FILE, "r+", encoding="utf-8") as f: try: logs = json.load(f) except json.JSONDecodeError: f.seek(0) f.truncate() logs = [] logs.append(log_entry) f.seek(0) json.dump(logs, f, ensure_ascii=False, indent=2) except Exception as e: print("خطا در نوشتن لاگ:", e) def kill_old_process(): if not os.path.exists(PID_FILE): write_log("kill", "هیچ PIDی برای بستن وجود نداشت.") return try: with open(PID_FILE, "r") as f: pid = int(f.read().strip()) parent = psutil.Process(pid) children = parent.children(recursive=True) for child in children: child.terminate() gone, still_alive = psutil.wait_procs(children, timeout=5) write_log("kill", f"{len(gone)} تا subprocess بسته شد. هنوز زنده‌ها: {len(still_alive)}") os.remove(PID_FILE) except (psutil.NoSuchProcess, ValueError): write_log("kill", "PID معتبر نبود یا پروسه پیدا نشد.") except Exception as e: write_log("kill", f"خطا در بستن subprocessها: {str(e)}") def get_latest_commit(): try: result = subprocess.run( ["git", "-C", REPO_DIR, "rev-parse", "HEAD"], capture_output=True, text=True ) return result.stdout.strip() except Exception as e: write_log("error", f"get commit error: {str(e)}") return None def save_last_commit(commit_hash): with open(LAST_COMMIT_FILE, "w") as f: f.write(commit_hash) def load_last_commit(): if os.path.exists(LAST_COMMIT_FILE): with open(LAST_COMMIT_FILE, "r") as f: return f.read().strip() return None def clean_gitconfig(): home_dir = os.path.expanduser("~") gitconfig_path = os.path.join(home_dir, ".gitconfig") if not os.path.exists(gitconfig_path): return try: with open(gitconfig_path, "r", encoding="utf-8") as f: lines = f.readlines() new_lines = [] skip_next = False for line in lines: if line.strip().startswith('[credential "http://188.245.173.247:3080"]'): skip_next = True continue if skip_next: if line.strip().startswith("provider"): skip_next = False continue new_lines.append(line) # رفع مشکل Read-Only ویندوز if not os.access(gitconfig_path, os.W_OK): os.chmod(gitconfig_path, stat.S_IWRITE) with open(gitconfig_path, "w", encoding="utf-8") as f: f.writelines(new_lines) write_log("cleanup", ".gitconfig پاکسازی شد.") except Exception as e: write_log("error", f"خطا در پاکسازی .gitconfig: {e}") def clear_git_credentials(): # حذف credential helper subprocess.run(["git", "config", "--global", "--unset", "credential.helper"], capture_output=True) # پاک کردن فایل‌هایی که اسمشون git داره توی Home home_dir = os.path.expanduser("~") for fname in os.listdir(home_dir): if fname.lower().startswith(".git"): try: file_path = os.path.join(home_dir, fname) if not os.access(file_path, os.W_OK): os.chmod(file_path, stat.S_IWRITE) os.remove(file_path) write_log("cleanup", f"فایل {fname} از Home پاک شد.") except Exception as e: write_log("error", f"پاک کردن {fname} نشد: {e}") def clone_or_update_repo(): clean_gitconfig() clear_git_credentials() if os.path.exists(REPO_DIR): try: result = subprocess.run( ["git", "-C", REPO_DIR, "pull"], capture_output=True, text=True ) if result.returncode == 0: write_log("pull", "مخزن آپدیت شد.") else: write_log("error", f"خطا در git pull: {result.stderr}") except Exception as e: write_log("error", f"git pull failed: {str(e)}") else: result = subprocess.run( ["git", "clone", GIT_REPO, REPO_DIR], capture_output=True, text=True ) if result.returncode == 0: write_log("clone", "مخزن کلون شد.") else: write_log("error", f"خطا در کلون کردن: {result.stderr}") def run_main_bat(): try: shutil.copy(os.path.join(os.getcwd(), '.env'), os.path.join(os.getcwd(), 'bot_ea_db')) process = subprocess.Popen( ["cmd.exe", "/c", "main.bat"], cwd=REPO_DIR, creationflags=subprocess.CREATE_NEW_CONSOLE ) with open(PID_FILE, "w") as f: f.write(str(process.pid)) write_log("run", f"main.bat اجرا شد با PID={process.pid}.") except Exception as e: write_log("error", f"main.bat اجرا نشد: {str(e)}") def main_loop(): while True: try: print('1') clone_or_update_repo() print('2') latest_commit = get_latest_commit() print('3') saved_commit = load_last_commit() print('4') if latest_commit and latest_commit != saved_commit: print('5') write_log("update", f"کمیت جدید: {latest_commit}") print('6') kill_old_process() print('7') run_main_bat() print('8') save_last_commit(latest_commit) else: print(("check", "تغییری نبود.")) write_log("check", "تغییری نبود.") print(60) time.sleep(60) except Exception as e: print('EROR MSG :>>> ', e) def clean_initial_files(): # پاک کردن log.json if os.path.exists(LOG_FILE): try: os.remove(LOG_FILE) print(f"{LOG_FILE} پاک شد.") except Exception as e: print(f"پاک کردن {LOG_FILE} نشد:", e) # پاک کردن PID_FILE if os.path.exists(PID_FILE): try: os.remove(PID_FILE) print(f"{PID_FILE} پاک شد.") except Exception as e: print(f"پاک کردن {PID_FILE} نشد:", e) if os.path.exists('last_commit.txt'): try: os.remove('last_commit.txt') print(f"{PID_FILE} پاک شد.") except Exception as e: print(f"پاک کردن {PID_FILE} نشد:", e) if __name__ == "__main__": # پاکسازی اولیه قبل از حلقه clean_initial_files() main_loop()