AI Update: تسک ها را آماده کن این ساختار عالیه
This commit is contained in:
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user