AI Update: تسک ها را آماده کن این ساختار عالیه

This commit is contained in:
Antigravity Bot
2026-08-30 18:36:58 +03:30
parent d5c225ebf6
commit bf4df87e86
7 changed files with 930 additions and 28 deletions
+204
View File
@@ -49,6 +49,7 @@ from formatters import (
format_git_info,
format_git_commits_page,
format_commit_detail_view,
format_ftp_info,
split_message,
escape_html,
)
@@ -67,6 +68,7 @@ from invite_manager import (
)
from backup_manager import backup_manager
from git_manager import git_manager
from ftp_manager import ftp_manager
from sys_monitor import render_server_hardware_report
from usage_monitor import fetch_and_render_usage_report
from bot_actions import process_all_ai_actions
@@ -319,6 +321,10 @@ async def build_git_menu(chat_id: int) -> tuple[str, InlineKeyboardMarkup]:
[
InlineKeyboardButton("🌐 مشاهده در مرورگر (Gitea)", url=urls["web_url"]),
],
[
InlineKeyboardButton("🚀 انتشار به پروداکشن (Publish)", callback_data="btn_git_publish"),
InlineKeyboardButton("🚀 دیپلوی FTP", callback_data="btn_ftp_menu"),
],
[
InlineKeyboardButton("📜 تاریخچه ۲۰ کامیت اخیر", callback_data="git_hist:1"),
InlineKeyboardButton("↩️ لغو آخرین تغییر (Undo)", callback_data="git_ask_undo_head"),
@@ -341,6 +347,10 @@ async def build_git_menu(chat_id: int) -> tuple[str, InlineKeyboardMarkup]:
[
InlineKeyboardButton("🌐 Open in Browser (Gitea)", url=urls["web_url"]),
],
[
InlineKeyboardButton("🚀 Publish to Production", callback_data="btn_git_publish"),
InlineKeyboardButton("🚀 Deploy via FTP", callback_data="btn_ftp_menu"),
],
[
InlineKeyboardButton("📜 Recent Commits (History)", callback_data="git_hist:1"),
InlineKeyboardButton("↩️ Undo Last Change", callback_data="git_ask_undo_head"),
@@ -362,6 +372,59 @@ async def build_git_menu(chat_id: int) -> tuple[str, InlineKeyboardMarkup]:
return text, InlineKeyboardMarkup(keyboard)
async def build_ftp_menu(chat_id: int) -> tuple[str, InlineKeyboardMarkup]:
"""Generates the interactive FTP Deployer and configuration view."""
session = session_manager.get_or_create(chat_id)
curr_proj = session_manager.get_current_project(chat_id)
is_fa = (session.language or "").lower() in ("fa", "farsi", "persian", "🇮🇷 persian / farsi (فارسی)")
if not curr_proj:
msg = "⚠️ شما هنوز هیچ پروژه‌ای ایجاد نکرده‌اید." if is_fa else "⚠️ No active project found."
return msg, InlineKeyboardMarkup([[InlineKeyboardButton("🏠 منوی اصلی" if is_fa else "🏠 Main Dashboard", callback_data="btn_dashboard")]])
text = format_ftp_info(
project_name=curr_proj.name,
host=curr_proj.ftp_host,
port=curr_proj.ftp_port,
user=curr_proj.ftp_user,
path=curr_proj.ftp_path,
tls=curr_proj.ftp_tls,
lang=session.language,
)
if is_fa:
keyboard = [
[
InlineKeyboardButton("🚀 دیپلوی روی FTP (Clean Deploy)", callback_data="btn_ftp_deploy"),
InlineKeyboardButton("🔍 تست اتصال FTP", callback_data="btn_ftp_test"),
],
[
InlineKeyboardButton("🐙 منوی گیت و برنچ‌ها", callback_data="btn_git_menu"),
InlineKeyboardButton("📁 مدیریت پروژه‌ها", callback_data="proj_menu"),
],
[
InlineKeyboardButton("🏠 منوی اصلی", callback_data="btn_dashboard"),
],
]
else:
keyboard = [
[
InlineKeyboardButton("🚀 Deploy via FTP (Clean)", callback_data="btn_ftp_deploy"),
InlineKeyboardButton("🔍 Test FTP Connection", callback_data="btn_ftp_test"),
],
[
InlineKeyboardButton("🐙 Git & Branches Menu", callback_data="btn_git_menu"),
InlineKeyboardButton("📁 Projects Menu", callback_data="proj_menu"),
],
[
InlineKeyboardButton("🏠 Main Dashboard", callback_data="btn_dashboard"),
],
]
return text, InlineKeyboardMarkup(keyboard)
async def build_git_history_menu(chat_id: int, page: int = 1) -> tuple[str, InlineKeyboardMarkup]:
"""Generates paginated commit history view."""
session = session_manager.get_or_create(chat_id)
@@ -3360,6 +3423,55 @@ async def git_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
text, markup = await build_git_menu(chat_id)
await update.message.reply_html(text, reply_markup=markup, disable_web_page_preview=True)
# Command: /publish
@check_auth
async def publish_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
chat_id = update.effective_chat.id
session = session_manager.get_or_create(chat_id)
curr_proj = session_manager.get_current_project(chat_id)
is_fa = (session.language or "").lower() in ("fa", "farsi", "persian", "🇮🇷 persian / farsi (فارسی)")
if not curr_proj:
msg = "⚠️ شما هنوز هیچ پروژه‌ای ایجاد نکرده‌اید." if is_fa else "⚠️ No active project found."
await update.message.reply_html(msg)
return
pub_msg = " ".join(context.args).strip() if context.args else f"Manual release published via /publish"
status_msg = await update.message.reply_html("🚀 <i>در حال انتشار تغییرات شاخه dev به شاخه production...</i>" if is_fa else "🚀 <i>Publishing dev branch to production...</i>")
ok, res_msg, p_info = await git_manager.git_publish(curr_proj.workspace, message=pub_msg, repo_name=curr_proj.name)
urls = git_manager.get_repo_urls(curr_proj.name)
buttons = [
[
InlineKeyboardButton("🚀 دیپلوی روی FTP" if is_fa else "🚀 Deploy to FTP", callback_data="btn_ftp_deploy"),
InlineKeyboardButton("🐙 منوی گیت" if is_fa else "🐙 Git Menu", callback_data="btn_git_menu"),
]
]
if ok:
out = (
f"🚀 <b>عملیات انتشار به پروداکشن (Publish to Production) با موفقیت انجام شد:</b>\n\n"
f"• 📁 <b>پروژه:</b> <code>{escape_html(curr_proj.name)}</code>\n"
f"• 🌐 <b>مخزن:</b> <a href=\"{urls['web_url']}\">{urls['web_url']}</a>\n\n"
f"{res_msg}"
) if is_fa else (
f"🚀 <b>Published to Production Successfully:</b>\n\n"
f"• 📁 <b>Project:</b> <code>{escape_html(curr_proj.name)}</code>\n"
f"• 🌐 <b>Repository:</b> <a href=\"{urls['web_url']}\">{urls['web_url']}</a>\n\n"
f"{res_msg}"
)
else:
out = f"⚠️ <b>خطا در انتشار:</b>\n{res_msg}"
await status_msg.edit_text(out, parse_mode=constants.ParseMode.HTML, reply_markup=InlineKeyboardMarkup(buttons), disable_web_page_preview=True)
# Command: /ftp
@check_auth
async def ftp_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
chat_id = update.effective_chat.id
text, markup = await build_ftp_menu(chat_id)
await update.message.reply_html(text, reply_markup=markup, disable_web_page_preview=True)
# Command: /sync
@check_auth
async def sync_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
@@ -4574,6 +4686,96 @@ async def callback_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
except Exception:
await query.message.reply_html(text, reply_markup=markup, disable_web_page_preview=True)
elif data == "btn_git_publish":
await query.answer("🚀 در حال انتشار به پروداکشن..." if is_fa else "🚀 Publishing to production...")
if curr_proj:
ok, res_msg, _ = await git_manager.git_publish(curr_proj.workspace, message="Publish via bot button", repo_name=curr_proj.name)
try:
await query.answer("✅ انتشار به پروداکشن با موفقیت انجام شد!" if ok else "⚠️ خطا در انتشار", show_alert=not ok)
except Exception:
pass
text, markup = await build_git_menu(chat_id)
try:
await query.edit_message_text(text, parse_mode=constants.ParseMode.HTML, reply_markup=markup, disable_web_page_preview=True)
except Exception:
await query.message.reply_html(text, reply_markup=markup, disable_web_page_preview=True)
elif data == "btn_ftp_menu":
text, markup = await build_ftp_menu(chat_id)
try:
await query.edit_message_text(text, parse_mode=constants.ParseMode.HTML, reply_markup=markup, disable_web_page_preview=True)
except Exception:
await query.message.reply_html(text, reply_markup=markup, disable_web_page_preview=True)
elif data == "btn_ftp_test":
await query.answer("🔍 در حال بررسی اتصال FTP..." if is_fa else "🔍 Testing FTP connection...")
if curr_proj and curr_proj.ftp_host:
test_ok, test_msg = await ftp_manager.test_connection(
host=curr_proj.ftp_host,
port=curr_proj.ftp_port,
user=curr_proj.ftp_user or "",
password=curr_proj.ftp_password or "",
path=curr_proj.ftp_path or "/",
tls=curr_proj.ftp_tls,
)
try:
alert_text = ("✅ اتصال FTP برقرار است" if test_ok else "❌ خطا در اتصال FTP") + f"\n{test_msg}"
await query.answer(alert_text[:200], show_alert=True)
except Exception:
pass
else:
try:
await query.answer("⚠️ اطلاعات FTP هنوز برای این پروژه تنظیم نشده است.", show_alert=True)
except Exception:
pass
text, markup = await build_ftp_menu(chat_id)
try:
await query.edit_message_text(text, parse_mode=constants.ParseMode.HTML, reply_markup=markup, disable_web_page_preview=True)
except Exception:
await query.message.reply_html(text, reply_markup=markup, disable_web_page_preview=True)
elif data == "btn_ftp_deploy":
await query.answer("🚀 در حال استقرار هوشمند روی FTP..." if is_fa else "🚀 Deploying to FTP...")
if curr_proj and curr_proj.ftp_host:
# Auto publish before deploy
try:
await git_manager.git_publish(curr_proj.workspace, message="Auto-publish before UI FTP deploy", repo_name=curr_proj.name)
except Exception:
pass
res = await ftp_manager.deploy_project(
workspace_path=curr_proj.workspace,
host=curr_proj.ftp_host,
port=curr_proj.ftp_port,
user=curr_proj.ftp_user or "",
password=curr_proj.ftp_password or "",
remote_path=curr_proj.ftp_path or "/",
tls=curr_proj.ftp_tls,
)
if res.get("success"):
files_up = res.get("files_uploaded", 0)
dur = res.get("duration", 0)
try:
await query.answer(f"✅ دیپلوی با موفقیت انجام شد ({files_up} فایل در {dur} ثانیه)", show_alert=True)
except Exception:
pass
else:
err = res.get("error", "Error")
try:
await query.answer(f"❌ خطا در دیپلوی: {err}"[:200], show_alert=True)
except Exception:
pass
else:
try:
await query.answer("⚠️ اطلاعات FTP تنظیم نشده است. ابتدا اطلاعات FTP را ثبت کنید.", show_alert=True)
except Exception:
pass
text, markup = await build_ftp_menu(chat_id)
try:
await query.edit_message_text(text, parse_mode=constants.ParseMode.HTML, reply_markup=markup, disable_web_page_preview=True)
except Exception:
await query.message.reply_html(text, reply_markup=markup, disable_web_page_preview=True)
elif data == "btn_git_sync":
await query.answer("🔄 در حال همگام‌سازی با Gitea..." if is_fa else "🔄 Syncing with Gitea...")
if curr_proj:
@@ -7034,6 +7236,8 @@ def main():
# Git & Gitea Version Control Handlers
application.add_handler(CommandHandler(["git", "repo", "repository", "gitea"], git_command))
application.add_handler(CommandHandler(["publish", "gitpublish", "release"], publish_command))
application.add_handler(CommandHandler(["ftp", "ftpdeploy", "deploy"], ftp_command))
application.add_handler(CommandHandler(["sync", "gitsync", "pull"], sync_command))
application.add_handler(CommandHandler(["commit", "gitcommit"], commit_command))
application.add_handler(CommandHandler(["undo", "revert", "gitundo", "gitrevert", "laghv"], undo_command))