236 lines
7.6 KiB
Python
236 lines
7.6 KiB
Python
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()
|