From 5ab0a40b037d6ce3707e7d76b5fa9746af8c5480 Mon Sep 17 00:00:00 2001 From: Antigravity Bot Date: Sun, 30 Aug 2026 21:23:34 +0330 Subject: [PATCH] =?UTF-8?q?AI=20Update:=20=D8=AA=D8=B3=D8=AA=20=D8=A7?= =?UTF-8?q?=D9=81=20=D8=AA=DB=8C=20=D9=BE=DB=8C=20=D9=86=D8=AA=DB=8C=D8=AC?= =?UTF-8?q?=D9=87=20=D8=B1=D9=88=20=D8=AF=D8=B1=D8=B3=D8=AA=20=D9=86=D9=85?= =?UTF-8?q?=DB=8C=DA=AF=D9=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- telegram-agy-bot/agy_engine.py | 7 +++ telegram-agy-bot/bot.py | 19 ++++++++- telegram-agy-bot/ftp_manager.py | 75 ++++++++++++++++++++++++++------- telegram-agy-bot/sessions.json | 16 +++---- 4 files changed, 91 insertions(+), 26 deletions(-) diff --git a/telegram-agy-bot/agy_engine.py b/telegram-agy-bot/agy_engine.py index 21531d7..22e5160 100644 --- a/telegram-agy-bot/agy_engine.py +++ b/telegram-agy-bot/agy_engine.py @@ -360,6 +360,13 @@ class SessionManager: "created_at": p_obj.created_at, "description": p_obj.description, "conversation_titles": p_obj.conversation_titles, + "active_branch": p_obj.active_branch, + "ftp_host": p_obj.ftp_host, + "ftp_port": p_obj.ftp_port, + "ftp_user": p_obj.ftp_user, + "ftp_password": p_obj.ftp_password, + "ftp_path": p_obj.ftp_path, + "ftp_tls": p_obj.ftp_tls, } curr = self.get_current_project(sess.chat_id) data[str(k)] = { diff --git a/telegram-agy-bot/bot.py b/telegram-agy-bot/bot.py index 42c7fe4..801c57c 100644 --- a/telegram-agy-bot/bot.py +++ b/telegram-agy-bot/bot.py @@ -4832,9 +4832,24 @@ async def callback_handler(update: Update, context: ContextTypes.DEFAULT_TYPE): path=curr_proj.ftp_path or "/", tls=curr_proj.ftp_tls, ) + icon = "✅" if test_ok else "❌" + res_card = ( + f"{icon} نتیجه تست اتصال FTP:\n\n" + f"• 🌐 هاست: {escape_html(curr_proj.ftp_host)}:{curr_proj.ftp_port}\n" + f"• 👤 نام کاربری: {escape_html(curr_proj.ftp_user or '(بدون نام کاربری)')}\n" + f"• 📂 مسیر: {escape_html(curr_proj.ftp_path or '/')}\n" + f"• 🔒 پروتکل: {'FTPS/TLS امن 🔒' if curr_proj.ftp_tls else 'FTP معمولی'}\n\n" + f"📋 گزارش ارتباط:\n{test_msg}" + ) if is_fa else ( + f"{icon} FTP Connection Test Result:\n\n" + f"• 🌐 Host: {escape_html(curr_proj.ftp_host)}:{curr_proj.ftp_port}\n" + f"• 👤 User: {escape_html(curr_proj.ftp_user or '(none)')}\n" + f"• 📂 Path: {escape_html(curr_proj.ftp_path or '/')}\n" + f"• 🔒 Protocol: {'Secure FTPS/TLS 🔒' if curr_proj.ftp_tls else 'Standard FTP'}\n\n" + f"📋 Status:\n{test_msg}" + ) try: - alert_text = ("✅ اتصال FTP برقرار است" if test_ok else "❌ خطا در اتصال FTP") + f"\n{test_msg}" - await query.answer(alert_text[:200], show_alert=True) + await query.message.reply_html(res_card, disable_web_page_preview=True) except Exception: pass else: diff --git a/telegram-agy-bot/ftp_manager.py b/telegram-agy-bot/ftp_manager.py index 616db7e..4434975 100644 --- a/telegram-agy-bot/ftp_manager.py +++ b/telegram-agy-bot/ftp_manager.py @@ -116,17 +116,27 @@ class FTPManager: timeout: int = 15, ) -> ftplib.FTP: """Helper to create and authenticate an FTP or FTPS client.""" + clean_host = host.strip() + clean_user = user.strip() if user else "" + clean_pass = password.strip() if password else "" + if tls: ftp = ftplib.FTP_TLS(timeout=timeout) else: ftp = ftplib.FTP(timeout=timeout) - ftp.connect(host=host, port=port, timeout=timeout) - ftp.login(user=user or "anonymous", passwd=password or "") - + ftp.encoding = "utf-8" + ftp.connect(host=clean_host, port=int(port), timeout=timeout) + if tls and isinstance(ftp, ftplib.FTP_TLS): + ftp.auth() + ftp.login(user=clean_user or "anonymous", passwd=clean_pass) ftp.prot_p() # Secure data connection - + else: + ftp.login(user=clean_user or "anonymous", passwd=clean_pass) + + # Force passive mode (standard for firewalls / NAT) + ftp.set_pasv(True) return ftp async def test_connection( @@ -137,39 +147,72 @@ class FTPManager: password: str = "", path: str = "/", tls: bool = False, - timeout: int = 10, + timeout: int = 12, ) -> Tuple[bool, str]: """Tests FTP credentials and verifies access to the target remote directory.""" if not host or not host.strip(): return False, "آدرس هاست (Host) FTP مشخص نشده است." def _test(): + ftp = None try: ftp = self._create_ftp_client(host.strip(), int(port), user.strip(), password, tls, timeout) + + # Check root PWD + init_pwd = ftp.pwd() + # Test CWD to target path if specified target_path = path.strip() if path else "/" if target_path and target_path != "/": try: ftp.cwd(target_path) except Exception as e: - pwd = ftp.pwd() - ftp.quit() - return False, f"اتصال به FTP برقرار شد، اما مسیر ریموت «{target_path}» یافت نشد (مسیر فعلی: {pwd}): {e}" + curr_pwd = ftp.pwd() if ftp else "/" + try: + ftp.quit() + except Exception: + pass + return False, f"اتصال به سرور برقرار شد، اما مسیر ریموت «{target_path}» یافت نشد (مسیر فعلی: {curr_pwd}): {e}" - pwd = ftp.pwd() + final_pwd = ftp.pwd() + + # Test directory listing + item_count = 0 try: listing = ftp.nlst() - count = len(listing) + item_count = len(listing) except Exception: - count = 0 - ftp.quit() - return True, f"اتصال با موفقیت برقرار شد. مسیر فعلی: {pwd} (تعداد آیتم‌ها: {count})" - except (socket.gaierror, socket.timeout) as e: - return False, f"خطای شبکه / نامعتبر بودن آدرس سرور ({host}:{port}): {e}" + try: + lines = [] + ftp.dir(lines.append) + item_count = len(lines) + except Exception: + item_count = 0 + + try: + ftp.quit() + except Exception: + pass + + tls_label = " (FTPS/TLS امن)" if tls else " (FTP معمولی)" + return True, f"اتصال با موفقیت برقرار شد{tls_label} | مسیر: {final_pwd} | تعداد فایل‌ها و پوشه‌ها: {item_count}" + + except socket.gaierror as e: + return False, f"نام دامنه/هاست سرور یافت نشد ({host}): {e}" + except (socket.timeout, TimeoutError) as e: + return False, f"مهلت زمانی اتصال به سرور به پایان رسید (Timeout روی پورت {port}): {e}" + except ConnectionRefusedError as e: + return False, f"اتصال توسط سرور رد شد (پورت {port} بسته است یا FTP روی آن فعال نیست): {e}" except ftplib.error_perm as e: - return False, f"خطای احراز هویت / دسترسی FTP: {e}" + return False, f"خطای نام کاربری یا رمز عبور (دسترسی نامعتبر): {e}" except Exception as e: return False, f"خطا در برقراری ارتباط با FTP: {e}" + finally: + if ftp: + try: + ftp.close() + except Exception: + pass return await asyncio.to_thread(_test) diff --git a/telegram-agy-bot/sessions.json b/telegram-agy-bot/sessions.json index c6c32e3..5a50d87 100644 --- a/telegram-agy-bot/sessions.json +++ b/telegram-agy-bot/sessions.json @@ -20,9 +20,9 @@ "model": "gemini-3.7-flash-auto", "effort": "high", "language": "fa", - "last_context_length": 41556, - "last_total_tokens": 332309, - "last_response": "\u0642\u0627\u0628\u0644\u06cc\u062a \u0645\u062f\u06cc\u0631\u06cc\u062a \u06a9\u0627\u0645\u0644 \u0648 \u062a\u0639\u0627\u0645\u0644\u06cc \u062a\u0646\u0638\u06cc\u0645\u0627\u062a FTP \u0645\u0633\u062a\u0642\u06cc\u0645\u0627\u064b \u0628\u0627 \u062f\u06a9\u0645\u0647\u200c\u0647\u0627\u06cc \u0631\u0628\u0627\u062a \u062a\u0644\u06af\u0631\u0627\u0645 \u067e\u06cc\u0627\u062f\u0647\u200c\u0633\u0627\u0632\u06cc \u0648 \u0641\u0639\u0627\u0644 \u0634\u062f.\n\n---\n\n### \u2728 \u0627\u0645\u06a9\u0627\u0646\u0627\u062a \u0648 \u062f\u06a9\u0645\u0647\u200c\u0647\u0627\u06cc \u062c\u062f\u06cc\u062f \u0627\u0636\u0627\u0641\u0647 \u0634\u062f\u0647:\n\n1. **\ud83c\udf10 \u0648\u06cc\u0631\u0627\u06cc\u0634 \u0647\u0627\u0633\u062a / \u067e\u0648\u0631\u062a (`ftp_set:host`):**\n - \u0628\u0627 \u06a9\u0644\u06cc\u06a9 \u0631\u0648\u06cc \u062f\u06a9\u0645\u0647\u060c \u0631\u0628\u0627\u062a \u0645\u0646\u062a\u0638\u0631 \u062f\u0631\u06cc\u0627\u0641\u062a \u0622\u062f\u0631\u0633 \u0647\u0627\u0633\u062a \u0645\u06cc\u200c\u0645\u0627\u0646\u062f (\u0645\u062b\u0627\u0644: `ftp.mysite.com` \u06cc\u0627 `1.2.3.4:2121`).\n2. **\ud83d\udc64 \u0648\u06cc\u0631\u0627\u06cc\u0634 \u0646\u0627\u0645 \u06a9\u0627\u0631\u0628\u0631\u06cc (`ftp_set:user`):**\n - \u0628\u0631\u0627\u06cc \u0648\u0627\u0631\u062f \u06a9\u0631\u062f\u0646 \u06cc\u0648\u0632\u0631\u0646\u06cc\u0645 \u0627\u06a9\u0627\u0646\u062a FTP.\n3. **\ud83d\udd11 \u0648\u06cc\u0631\u0627\u06cc\u0634 \u0631\u0645\u0632 \u0639\u0628\u0648\u0631 (`ftp_set:pass`):**\n - \u0628\u0631\u0627\u06cc \u0648\u0627\u0631\u062f \u06a9\u0631\u062f\u0646 \u0631\u0645\u0632 \u0639\u0628\u0648\u0631 (\u067e\u0633 \u0627\u0632 \u062f\u0631\u06cc\u0627\u0641\u062a\u060c \u067e\u06cc\u0627\u0645 \u0628\u0631\u0627\u06cc \u0627\u0645\u0646\u06cc\u062a \u0628\u06cc\u0634\u062a\u0631 \u062d\u0630\u0641 \u0645\u06cc\u200c\u0634\u0648\u062f \u0648 \u062f\u0631 \u0645\u0646\u0648 \u0628\u0647 \u0635\u0648\u0631\u062a \u0645\u0627\u0633\u06a9\u200c\u0634\u062f\u0647 `\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022` \u0646\u0645\u0627\u06cc\u0634 \u062f\u0627\u062f\u0647 \u0645\u06cc\u200c\u0634\u0648\u062f).\n4. **\ud83d\udcc2 \u0648\u06cc\u0631\u0627\u06cc\u0634 \u0645\u0633\u06cc\u0631 \u0631\u06cc\u0645\u0648\u062a \u0631\u0648\u06cc \u0647\u0627\u0633\u062a (`ftp_set:path`):**\n - \u0628\u0631\u0627\u06cc \u0645\u0634\u062e\u0635 \u06a9\u0631\u062f\u0646 \u0645\u0633\u06cc\u0631 \u067e\u0648\u0634\u0647 \u062f\u0631 \u0647\u0627\u0633\u062a (\u0645\u0627\u0646\u0646\u062f `/public_html` \u06cc\u0627 `/domains/mysite.com/public_html`).\n5. **\ud83d\udd12 \u0633\u0648\u06cc\u06cc\u0686 \u067e\u0631\u0648\u062a\u06a9\u0644 \u0627\u0645\u0646 FTPS / TLS (`ftp_toggle_tls`):**\n - \u0628\u0627 \u06cc\u06a9 \u06a9\u0644\u06cc\u06a9 \u0628\u06cc\u0646 FTP \u0645\u0639\u0645\u0648\u0644\u06cc \u0648 TLS \u0627\u0645\u0646 \u062a\u063a\u06cc\u06cc\u0631 \u0648\u0636\u0639\u06cc\u062a \u0645\u06cc\u200c\u062f\u0647\u062f.\n6. **\ud83d\udd0d \u062a\u0633\u062a \u062e\u0648\u062f\u06a9\u0627\u0631 \u0648 \u0622\u0646\u0644\u0627\u06cc\u0646 \u0627\u062a\u0635\u0627\u0644 FTP (`btn_ftp_test`):**\n - \u0628\u0631\u0631\u0633\u06cc \u0632\u0646\u062f\u0647 \u0635\u062d\u062a \u0645\u0634\u062e\u0635\u0627\u062a \u0627\u062a\u0635\u0627\u0644 \u0628\u0627 \u0647\u0627\u0633\u062a \u0648 \u0646\u0645\u0627\u06cc\u0634 \u0648\u0636\u0639\u06cc\u062a \u0627\u0631\u062a\u0628\u0627\u0637.\n7. **\ud83d\uddd1\ufe0f \u067e\u0627\u06a9\u200c\u0633\u0627\u0632\u06cc \u0645\u0634\u062e\u0635\u0627\u062a FTP (`ftp_clear_conf`):**\n - \u0631\u06cc\u0633\u062a \u0648 \u067e\u0627\u06a9 \u06a9\u0631\u062f\u0646 \u06a9\u0627\u0645\u0644 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u0627\u062a\u0635\u0627\u0644 \u062f\u0631 \u0635\u0648\u0631\u062a \u0646\u06cc\u0627\u0632.\n\n---\n\n[[RESTART_BOT]]\n\n[[BUTTONS: layout=[\n [{\"text\": \"\ud83d\ude80 \u0628\u0627\u0632 \u06a9\u0631\u062f\u0646 \u0645\u0646\u0648\u06cc FTP\", \"cmd\": \"/ftp\"}, {\"text\": \"\ud83c\udfe0 \u0645\u0646\u0648\u06cc \u0627\u0635\u0644\u06cc\", \"cmd\": \"/menu\"}]\n]]]\n\n\u2022 \u0646\u0627\u0645 \u067e\u0631\u0648\u0698\u0647: default \n\u2022 \u0622\u062f\u0631\u0633 \u0645\u062e\u0632\u0646: https://git.msa.artacloud.ir/root/default\n", + "last_context_length": 78747, + "last_total_tokens": 774548, + "last_response": "\u0628\u0631\u0631\u0633\u06cc \u0639\u0645\u06cc\u0642 \u0648 \u0631\u06cc\u0634\u0647\u200c\u06cc\u0627\u0628\u06cc \u0639\u0645\u0644\u06a9\u0631\u062f \u062a\u0633\u062a \u0627\u062a\u0635\u0627\u0644 FTP \u0627\u0646\u062c\u0627\u0645 \u0634\u062f \u0648 \u062f\u0648 \u0645\u0634\u06a9\u0644 \u0627\u0635\u0644\u06cc \u0634\u0646\u0627\u0633\u0627\u06cc\u06cc \u0648 \u0628\u0631\u0637\u0631\u0641 \u06af\u0631\u062f\u06cc\u062f:\n\n---\n\n### \ud83d\udd0d \u0631\u06cc\u0634\u0647\u200c\u06cc\u0627\u0628\u06cc \u0648 \u0627\u0635\u0644\u0627\u062d\u0627\u062a \u0627\u0646\u062c\u0627\u0645\u200c\u0634\u062f\u0647:\n\n1. **\u0630\u062e\u06cc\u0631\u0647\u200c\u0633\u0627\u0632\u06cc \u067e\u0627\u06cc\u062f\u0627\u0631 \u0645\u0634\u062e\u0635\u0627\u062a FTP \u062f\u0631 \u0641\u0627\u06cc\u0644 \u0646\u0634\u0633\u062a\u200c\u0647\u0627 (`sessions.json`):**\n - **\u0639\u0644\u062a:** \u0641\u06cc\u0644\u062f\u0647\u0627\u06cc FTP \u062f\u0631 \u0632\u0645\u0627\u0646 \u0633\u0631\u06cc\u0627\u0644\u200c\u0633\u0627\u0632\u06cc \u0648 \u0630\u062e\u06cc\u0631\u0647 \u0646\u0634\u0633\u062a \u062f\u0631 `SessionManager.save()` \u0644\u062d\u0627\u0638 \u0646\u0634\u062f\u0647 \u0628\u0648\u062f\u0646\u062f\u061b \u062f\u0631 \u0646\u062a\u06cc\u062c\u0647 \u067e\u0633 \u0627\u0632 \u0630\u062e\u06cc\u0631\u0647 \u06cc\u0627 \u0631\u06cc\u200c\u0627\u0633\u062a\u0627\u0631\u062a \u0631\u0628\u0627\u062a\u060c \u0645\u0642\u0627\u062f\u06cc\u0631 \u0641\u06cc\u0644\u062f\u0647\u0627 \u0631\u06cc\u0633\u062a \u0645\u06cc\u200c\u0634\u062f\u0646\u062f \u0648 \u062a\u0633\u062a \u0628\u0627 \u0645\u0642\u0627\u062f\u06cc\u0631 \u062e\u0627\u0644\u06cc \u0627\u0646\u062c\u0627\u0645 \u0645\u06cc\u200c\u06af\u0631\u0641\u062a.\n - **\u0627\u0635\u0644\u0627\u062d:** \u062a\u0645\u0627\u0645 \u0641\u06cc\u0644\u062f\u0647\u0627\u06cc `ftp_host`\u060c `ftp_port`\u060c `ftp_user`\u060c `ftp_password`\u060c `ftp_path` \u0648 `ftp_tls` \u0628\u0647 \u0633\u0631\u06cc\u0627\u0644\u200c\u0633\u0627\u0632\u06cc \u0646\u0634\u0633\u062a\u200c\u0647\u0627 \u0627\u0636\u0627\u0641\u0647 \u0634\u062f\u0646\u062f.\n\n2. **\u0645\u062f\u06cc\u0631\u06cc\u062a \u062d\u0627\u0644\u062a Passive \u0648 \u067e\u0631\u0648\u062a\u06a9\u0644 TLS \u062f\u0631 \u06a9\u062a\u0627\u0628\u062e\u0627\u0646\u0647 `ftplib`:**\n - **\u0639\u0644\u062a:** \u062f\u0631 \u0627\u0631\u062a\u0628\u0627\u0637 \u0628\u0627 \u0628\u0631\u062e\u06cc \u0647\u0627\u0633\u062a\u200c\u0647\u0627 (\u0628\u0647 \u062f\u0644\u06cc\u0644 \u0641\u0627\u06cc\u0631\u0648\u0627\u0644 \u06cc\u0627 NAT \u0633\u0631\u0648\u0631\u0647\u0627)\u060c \u0639\u062f\u0645 \u0641\u0639\u0627\u0644\u200c\u0633\u0627\u0632\u06cc \u0635\u0631\u06cc\u062d \u062d\u0627\u0644\u062a Passive \u0648 \u06a9\u062f\u06af\u0630\u0627\u0631\u06cc UTF-8 \u062f\u0631 \u062f\u0631\u06cc\u0627\u0641\u062a \u0644\u06cc\u0633\u062a \u062f\u0627\u06cc\u0631\u06a9\u062a\u0648\u0631\u06cc\u060c \u0628\u0627\u0639\u062b \u062e\u0637\u0627\u06cc \u06a9\u0627\u0630\u0628 \u062f\u0631 \u0645\u0631\u062d\u0644\u0647 \u0646\u0647\u0627\u06cc\u06cc \u062a\u0633\u062a \u0645\u06cc\u200c\u0634\u062f. \u0647\u0645\u0686\u0646\u06cc\u0646 \u062f\u0631 FTPS \u0647\u0646\u062f\u0634\u06cc\u06a9 `auth()` \u0628\u0647 \u0635\u0648\u0631\u062a \u0627\u0633\u062a\u0627\u0646\u062f\u0627\u0631\u062f \u0627\u0636\u0627\u0641\u0647 \u0634\u062f.\n - **\u0627\u0635\u0644\u0627\u062d:** \u062a\u0646\u0638\u06cc\u0645 \u0635\u0631\u06cc\u062d Passive Mode (`ftp.set_pasv(True)`)\u060c \u0647\u0646\u062f\u0634\u06cc\u06a9 \u0627\u0645\u0646 FTPS\u060c \u0627\u0646\u06a9\u0648\u062f\u06cc\u0646\u06af UTF-8 \u0648 \u0641\u0627\u0644\u200c\u0628\u06a9 \u062f\u0631\u06cc\u0627\u0641\u062a \u0644\u06cc\u0633\u062a \u062f\u0627\u06cc\u0631\u06a9\u062a\u0648\u0631\u06cc \u0627\u0639\u0645\u0627\u0644 \u0634\u062f.\n\n3. **\u0646\u0645\u0627\u06cc\u0634 \u06a9\u0627\u0645\u0644 \u0648 \u062f\u0642\u06cc\u0642 \u06af\u0632\u0627\u0631\u0634 \u062a\u0633\u062a \u062f\u0631 \u0686\u062a:**\n - \u0628\u0647 \u062c\u0627\u06cc \u0647\u0634\u062f\u0627\u0631 \u06a9\u0648\u062a\u0627\u0647 \u062a\u0644\u06af\u0631\u0627\u0645 (Popup Alert) \u06a9\u0647 \u062e\u0637\u0627\u0647\u0627\u06cc \u0637\u0648\u0644\u0627\u0646\u06cc \u0631\u0627 \u06a9\u0648\u062a\u0627\u0647 \u0645\u06cc\u200c\u06a9\u0631\u062f\u060c \u0627\u06a9\u0646\u0648\u0646 \u06cc\u06a9 \u06a9\u0627\u0631\u062a \u06af\u0632\u0627\u0631\u0634 \u062a\u0641\u0635\u06cc\u0644\u06cc \u0628\u0627 \u062a\u0645\u0627\u0645 \u062c\u0632\u0626\u06cc\u0627\u062a \u062e\u0637\u0627 (\u0646\u0627\u0645 \u06a9\u0627\u0631\u0628\u0631\u06cc\u060c \u0631\u0645\u0632 \u0639\u0628\u0648\u0631\u060c \u067e\u0648\u0631\u062a\u060c \u0641\u0627\u06cc\u0631\u0648\u0627\u0644 \u06cc\u0627 \u0645\u0633\u06cc\u0631 \u0646\u0627\u0645\u0639\u062a\u0628\u0631) \u0645\u0633\u062a\u0642\u06cc\u0645\u0627\u064b \u062f\u0631 \u0686\u062a \u0627\u0631\u0633\u0627\u0644 \u0645\u06cc\u200c\u0634\u0648\u062f.\n\n---\n\n[[RESTART_BOT]]\n\n[[BUTTONS: layout=[\n [{\"text\": \"\ud83d\ude80 \u0628\u0627\u0632 \u06a9\u0631\u062f\u0646 \u0645\u0646\u0648\u06cc FTP\", \"cmd\": \"/ftp\"}, {\"text\": \"\ud83d\udd0d \u062a\u0633\u062a \u0627\u062a\u0635\u0627\u0644 FTP\", \"prompt\": \"\u0648\u0636\u0639\u06cc\u062a \u0627\u062a\u0635\u0627\u0644 FTP \u067e\u0631\u0648\u0698\u0647 \u0631\u0648 \u062a\u0633\u062a \u06a9\u0646\"}]\n]]]\n\n\u2022 \u0646\u0627\u0645 \u067e\u0631\u0648\u0698\u0647: default \n\u2022 \u0622\u062f\u0631\u0633 \u0645\u062e\u0632\u0646: https://git.msa.artacloud.ir/root/default\n", "created_at": 1787995349.975879, "description": "", "conversation_titles": { @@ -97,19 +97,19 @@ } }, "turn_in_progress": false, - "last_prompt": "\u0628\u0644\u0647", - "last_response": "\u0642\u0627\u0628\u0644\u06cc\u062a \u0645\u062f\u06cc\u0631\u06cc\u062a \u06a9\u0627\u0645\u0644 \u0648 \u062a\u0639\u0627\u0645\u0644\u06cc \u062a\u0646\u0638\u06cc\u0645\u0627\u062a FTP \u0645\u0633\u062a\u0642\u06cc\u0645\u0627\u064b \u0628\u0627 \u062f\u06a9\u0645\u0647\u200c\u0647\u0627\u06cc \u0631\u0628\u0627\u062a \u062a\u0644\u06af\u0631\u0627\u0645 \u067e\u06cc\u0627\u062f\u0647\u200c\u0633\u0627\u0632\u06cc \u0648 \u0641\u0639\u0627\u0644 \u0634\u062f.\n\n---\n\n### \u2728 \u0627\u0645\u06a9\u0627\u0646\u0627\u062a \u0648 \u062f\u06a9\u0645\u0647\u200c\u0647\u0627\u06cc \u062c\u062f\u06cc\u062f \u0627\u0636\u0627\u0641\u0647 \u0634\u062f\u0647:\n\n1. **\ud83c\udf10 \u0648\u06cc\u0631\u0627\u06cc\u0634 \u0647\u0627\u0633\u062a / \u067e\u0648\u0631\u062a (`ftp_set:host`):**\n - \u0628\u0627 \u06a9\u0644\u06cc\u06a9 \u0631\u0648\u06cc \u062f\u06a9\u0645\u0647\u060c \u0631\u0628\u0627\u062a \u0645\u0646\u062a\u0638\u0631 \u062f\u0631\u06cc\u0627\u0641\u062a \u0622\u062f\u0631\u0633 \u0647\u0627\u0633\u062a \u0645\u06cc\u200c\u0645\u0627\u0646\u062f (\u0645\u062b\u0627\u0644: `ftp.mysite.com` \u06cc\u0627 `1.2.3.4:2121`).\n2. **\ud83d\udc64 \u0648\u06cc\u0631\u0627\u06cc\u0634 \u0646\u0627\u0645 \u06a9\u0627\u0631\u0628\u0631\u06cc (`ftp_set:user`):**\n - \u0628\u0631\u0627\u06cc \u0648\u0627\u0631\u062f \u06a9\u0631\u062f\u0646 \u06cc\u0648\u0632\u0631\u0646\u06cc\u0645 \u0627\u06a9\u0627\u0646\u062a FTP.\n3. **\ud83d\udd11 \u0648\u06cc\u0631\u0627\u06cc\u0634 \u0631\u0645\u0632 \u0639\u0628\u0648\u0631 (`ftp_set:pass`):**\n - \u0628\u0631\u0627\u06cc \u0648\u0627\u0631\u062f \u06a9\u0631\u062f\u0646 \u0631\u0645\u0632 \u0639\u0628\u0648\u0631 (\u067e\u0633 \u0627\u0632 \u062f\u0631\u06cc\u0627\u0641\u062a\u060c \u067e\u06cc\u0627\u0645 \u0628\u0631\u0627\u06cc \u0627\u0645\u0646\u06cc\u062a \u0628\u06cc\u0634\u062a\u0631 \u062d\u0630\u0641 \u0645\u06cc\u200c\u0634\u0648\u062f \u0648 \u062f\u0631 \u0645\u0646\u0648 \u0628\u0647 \u0635\u0648\u0631\u062a \u0645\u0627\u0633\u06a9\u200c\u0634\u062f\u0647 `\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022` \u0646\u0645\u0627\u06cc\u0634 \u062f\u0627\u062f\u0647 \u0645\u06cc\u200c\u0634\u0648\u062f).\n4. **\ud83d\udcc2 \u0648\u06cc\u0631\u0627\u06cc\u0634 \u0645\u0633\u06cc\u0631 \u0631\u06cc\u0645\u0648\u062a \u0631\u0648\u06cc \u0647\u0627\u0633\u062a (`ftp_set:path`):**\n - \u0628\u0631\u0627\u06cc \u0645\u0634\u062e\u0635 \u06a9\u0631\u062f\u0646 \u0645\u0633\u06cc\u0631 \u067e\u0648\u0634\u0647 \u062f\u0631 \u0647\u0627\u0633\u062a (\u0645\u0627\u0646\u0646\u062f `/public_html` \u06cc\u0627 `/domains/mysite.com/public_html`).\n5. **\ud83d\udd12 \u0633\u0648\u06cc\u06cc\u0686 \u067e\u0631\u0648\u062a\u06a9\u0644 \u0627\u0645\u0646 FTPS / TLS (`ftp_toggle_tls`):**\n - \u0628\u0627 \u06cc\u06a9 \u06a9\u0644\u06cc\u06a9 \u0628\u06cc\u0646 FTP \u0645\u0639\u0645\u0648\u0644\u06cc \u0648 TLS \u0627\u0645\u0646 \u062a\u063a\u06cc\u06cc\u0631 \u0648\u0636\u0639\u06cc\u062a \u0645\u06cc\u200c\u062f\u0647\u062f.\n6. **\ud83d\udd0d \u062a\u0633\u062a \u062e\u0648\u062f\u06a9\u0627\u0631 \u0648 \u0622\u0646\u0644\u0627\u06cc\u0646 \u0627\u062a\u0635\u0627\u0644 FTP (`btn_ftp_test`):**\n - \u0628\u0631\u0631\u0633\u06cc \u0632\u0646\u062f\u0647 \u0635\u062d\u062a \u0645\u0634\u062e\u0635\u0627\u062a \u0627\u062a\u0635\u0627\u0644 \u0628\u0627 \u0647\u0627\u0633\u062a \u0648 \u0646\u0645\u0627\u06cc\u0634 \u0648\u0636\u0639\u06cc\u062a \u0627\u0631\u062a\u0628\u0627\u0637.\n7. **\ud83d\uddd1\ufe0f \u067e\u0627\u06a9\u200c\u0633\u0627\u0632\u06cc \u0645\u0634\u062e\u0635\u0627\u062a FTP (`ftp_clear_conf`):**\n - \u0631\u06cc\u0633\u062a \u0648 \u067e\u0627\u06a9 \u06a9\u0631\u062f\u0646 \u06a9\u0627\u0645\u0644 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u0627\u062a\u0635\u0627\u0644 \u062f\u0631 \u0635\u0648\u0631\u062a \u0646\u06cc\u0627\u0632.\n\n---\n\n[[RESTART_BOT]]\n\n[[BUTTONS: layout=[\n [{\"text\": \"\ud83d\ude80 \u0628\u0627\u0632 \u06a9\u0631\u062f\u0646 \u0645\u0646\u0648\u06cc FTP\", \"cmd\": \"/ftp\"}, {\"text\": \"\ud83c\udfe0 \u0645\u0646\u0648\u06cc \u0627\u0635\u0644\u06cc\", \"cmd\": \"/menu\"}]\n]]]\n\n\u2022 \u0646\u0627\u0645 \u067e\u0631\u0648\u0698\u0647: default \n\u2022 \u0622\u062f\u0631\u0633 \u0645\u062e\u0632\u0646: https://git.msa.artacloud.ir/root/default\n", + "last_prompt": "\u062a\u0633\u062a \u0627\u0641 \u062a\u06cc \u067e\u06cc \u0646\u062a\u06cc\u062c\u0647 \u0631\u0648 \u062f\u0631\u0633\u062a \u0646\u0645\u06cc\u06af\u0647", + "last_response": "\u0628\u0631\u0631\u0633\u06cc \u0639\u0645\u06cc\u0642 \u0648 \u0631\u06cc\u0634\u0647\u200c\u06cc\u0627\u0628\u06cc \u0639\u0645\u0644\u06a9\u0631\u062f \u062a\u0633\u062a \u0627\u062a\u0635\u0627\u0644 FTP \u0627\u0646\u062c\u0627\u0645 \u0634\u062f \u0648 \u062f\u0648 \u0645\u0634\u06a9\u0644 \u0627\u0635\u0644\u06cc \u0634\u0646\u0627\u0633\u0627\u06cc\u06cc \u0648 \u0628\u0631\u0637\u0631\u0641 \u06af\u0631\u062f\u06cc\u062f:\n\n---\n\n### \ud83d\udd0d \u0631\u06cc\u0634\u0647\u200c\u06cc\u0627\u0628\u06cc \u0648 \u0627\u0635\u0644\u0627\u062d\u0627\u062a \u0627\u0646\u062c\u0627\u0645\u200c\u0634\u062f\u0647:\n\n1. **\u0630\u062e\u06cc\u0631\u0647\u200c\u0633\u0627\u0632\u06cc \u067e\u0627\u06cc\u062f\u0627\u0631 \u0645\u0634\u062e\u0635\u0627\u062a FTP \u062f\u0631 \u0641\u0627\u06cc\u0644 \u0646\u0634\u0633\u062a\u200c\u0647\u0627 (`sessions.json`):**\n - **\u0639\u0644\u062a:** \u0641\u06cc\u0644\u062f\u0647\u0627\u06cc FTP \u062f\u0631 \u0632\u0645\u0627\u0646 \u0633\u0631\u06cc\u0627\u0644\u200c\u0633\u0627\u0632\u06cc \u0648 \u0630\u062e\u06cc\u0631\u0647 \u0646\u0634\u0633\u062a \u062f\u0631 `SessionManager.save()` \u0644\u062d\u0627\u0638 \u0646\u0634\u062f\u0647 \u0628\u0648\u062f\u0646\u062f\u061b \u062f\u0631 \u0646\u062a\u06cc\u062c\u0647 \u067e\u0633 \u0627\u0632 \u0630\u062e\u06cc\u0631\u0647 \u06cc\u0627 \u0631\u06cc\u200c\u0627\u0633\u062a\u0627\u0631\u062a \u0631\u0628\u0627\u062a\u060c \u0645\u0642\u0627\u062f\u06cc\u0631 \u0641\u06cc\u0644\u062f\u0647\u0627 \u0631\u06cc\u0633\u062a \u0645\u06cc\u200c\u0634\u062f\u0646\u062f \u0648 \u062a\u0633\u062a \u0628\u0627 \u0645\u0642\u0627\u062f\u06cc\u0631 \u062e\u0627\u0644\u06cc \u0627\u0646\u062c\u0627\u0645 \u0645\u06cc\u200c\u06af\u0631\u0641\u062a.\n - **\u0627\u0635\u0644\u0627\u062d:** \u062a\u0645\u0627\u0645 \u0641\u06cc\u0644\u062f\u0647\u0627\u06cc `ftp_host`\u060c `ftp_port`\u060c `ftp_user`\u060c `ftp_password`\u060c `ftp_path` \u0648 `ftp_tls` \u0628\u0647 \u0633\u0631\u06cc\u0627\u0644\u200c\u0633\u0627\u0632\u06cc \u0646\u0634\u0633\u062a\u200c\u0647\u0627 \u0627\u0636\u0627\u0641\u0647 \u0634\u062f\u0646\u062f.\n\n2. **\u0645\u062f\u06cc\u0631\u06cc\u062a \u062d\u0627\u0644\u062a Passive \u0648 \u067e\u0631\u0648\u062a\u06a9\u0644 TLS \u062f\u0631 \u06a9\u062a\u0627\u0628\u062e\u0627\u0646\u0647 `ftplib`:**\n - **\u0639\u0644\u062a:** \u062f\u0631 \u0627\u0631\u062a\u0628\u0627\u0637 \u0628\u0627 \u0628\u0631\u062e\u06cc \u0647\u0627\u0633\u062a\u200c\u0647\u0627 (\u0628\u0647 \u062f\u0644\u06cc\u0644 \u0641\u0627\u06cc\u0631\u0648\u0627\u0644 \u06cc\u0627 NAT \u0633\u0631\u0648\u0631\u0647\u0627)\u060c \u0639\u062f\u0645 \u0641\u0639\u0627\u0644\u200c\u0633\u0627\u0632\u06cc \u0635\u0631\u06cc\u062d \u062d\u0627\u0644\u062a Passive \u0648 \u06a9\u062f\u06af\u0630\u0627\u0631\u06cc UTF-8 \u062f\u0631 \u062f\u0631\u06cc\u0627\u0641\u062a \u0644\u06cc\u0633\u062a \u062f\u0627\u06cc\u0631\u06a9\u062a\u0648\u0631\u06cc\u060c \u0628\u0627\u0639\u062b \u062e\u0637\u0627\u06cc \u06a9\u0627\u0630\u0628 \u062f\u0631 \u0645\u0631\u062d\u0644\u0647 \u0646\u0647\u0627\u06cc\u06cc \u062a\u0633\u062a \u0645\u06cc\u200c\u0634\u062f. \u0647\u0645\u0686\u0646\u06cc\u0646 \u062f\u0631 FTPS \u0647\u0646\u062f\u0634\u06cc\u06a9 `auth()` \u0628\u0647 \u0635\u0648\u0631\u062a \u0627\u0633\u062a\u0627\u0646\u062f\u0627\u0631\u062f \u0627\u0636\u0627\u0641\u0647 \u0634\u062f.\n - **\u0627\u0635\u0644\u0627\u062d:** \u062a\u0646\u0638\u06cc\u0645 \u0635\u0631\u06cc\u062d Passive Mode (`ftp.set_pasv(True)`)\u060c \u0647\u0646\u062f\u0634\u06cc\u06a9 \u0627\u0645\u0646 FTPS\u060c \u0627\u0646\u06a9\u0648\u062f\u06cc\u0646\u06af UTF-8 \u0648 \u0641\u0627\u0644\u200c\u0628\u06a9 \u062f\u0631\u06cc\u0627\u0641\u062a \u0644\u06cc\u0633\u062a \u062f\u0627\u06cc\u0631\u06a9\u062a\u0648\u0631\u06cc \u0627\u0639\u0645\u0627\u0644 \u0634\u062f.\n\n3. **\u0646\u0645\u0627\u06cc\u0634 \u06a9\u0627\u0645\u0644 \u0648 \u062f\u0642\u06cc\u0642 \u06af\u0632\u0627\u0631\u0634 \u062a\u0633\u062a \u062f\u0631 \u0686\u062a:**\n - \u0628\u0647 \u062c\u0627\u06cc \u0647\u0634\u062f\u0627\u0631 \u06a9\u0648\u062a\u0627\u0647 \u062a\u0644\u06af\u0631\u0627\u0645 (Popup Alert) \u06a9\u0647 \u062e\u0637\u0627\u0647\u0627\u06cc \u0637\u0648\u0644\u0627\u0646\u06cc \u0631\u0627 \u06a9\u0648\u062a\u0627\u0647 \u0645\u06cc\u200c\u06a9\u0631\u062f\u060c \u0627\u06a9\u0646\u0648\u0646 \u06cc\u06a9 \u06a9\u0627\u0631\u062a \u06af\u0632\u0627\u0631\u0634 \u062a\u0641\u0635\u06cc\u0644\u06cc \u0628\u0627 \u062a\u0645\u0627\u0645 \u062c\u0632\u0626\u06cc\u0627\u062a \u062e\u0637\u0627 (\u0646\u0627\u0645 \u06a9\u0627\u0631\u0628\u0631\u06cc\u060c \u0631\u0645\u0632 \u0639\u0628\u0648\u0631\u060c \u067e\u0648\u0631\u062a\u060c \u0641\u0627\u06cc\u0631\u0648\u0627\u0644 \u06cc\u0627 \u0645\u0633\u06cc\u0631 \u0646\u0627\u0645\u0639\u062a\u0628\u0631) \u0645\u0633\u062a\u0642\u06cc\u0645\u0627\u064b \u062f\u0631 \u0686\u062a \u0627\u0631\u0633\u0627\u0644 \u0645\u06cc\u200c\u0634\u0648\u062f.\n\n---\n\n[[RESTART_BOT]]\n\n[[BUTTONS: layout=[\n [{\"text\": \"\ud83d\ude80 \u0628\u0627\u0632 \u06a9\u0631\u062f\u0646 \u0645\u0646\u0648\u06cc FTP\", \"cmd\": \"/ftp\"}, {\"text\": \"\ud83d\udd0d \u062a\u0633\u062a \u0627\u062a\u0635\u0627\u0644 FTP\", \"prompt\": \"\u0648\u0636\u0639\u06cc\u062a \u0627\u062a\u0635\u0627\u0644 FTP \u067e\u0631\u0648\u0698\u0647 \u0631\u0648 \u062a\u0633\u062a \u06a9\u0646\"}]\n]]]\n\n\u2022 \u0646\u0627\u0645 \u067e\u0631\u0648\u0698\u0647: default \n\u2022 \u0622\u062f\u0631\u0633 \u0645\u062e\u0632\u0646: https://git.msa.artacloud.ir/root/default\n", "last_status_msg_id": null, "restart_pending": false, "last_delivered": true, - "last_update_time": 1788112105.8170931, + "last_update_time": 1788112414.7699497, "workspace": "/root", "conversation_id": "ce39875a-dec2-41c5-b2fe-54593a48b00c", "model": "gemini-3.7-flash-auto", "effort": "high", "language": "fa", - "last_context_length": 41556, - "last_total_tokens": 332309 + "last_context_length": 78747, + "last_total_tokens": 774548 }, "232801087": { "chat_id": 232801087,