הראה קוד מקור ל github_upload_fix

# ============================================
# תיקון העלאה ישירה מהמכשיר לגיטהאב
# ============================================

from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup, BotCommand, BotCommandScopeChat
from telegram.ext import ContextTypes, Application
from github import Github, GithubException
from datetime import datetime
import logging
from html import escape as html_escape

logger = logging.getLogger(__name__)

# ============================================
# פונקציה מתוקנת לבקשת העלאת קובץ
# ============================================

[תיעוד] async def github_upload_new_file(update, context): """בקשה להעלאת קובץ חדש לגיטהאב""" query = update.callback_query await query.answer() # אל תשתמש בברירת מחדל קשיחה. קרא מהריפו שנבחר בסשן GitHub, אם קיים. repo_name = None try: if hasattr(context, 'bot_data') and hasattr(context.bot_data, 'github_handler'): session = context.bot_data.github_handler.get_user_session(update.effective_user.id) repo_name = session.get('selected_repo') except Exception: repo_name = None # נפילה אחורה: אם לא הוגדר, עדיף לעצור ולא להעלות לריפו שגוי if not repo_name: await update.message.reply_text("❌ קודם בחר ריפו עם /github") return folder = context.user_data.get('github_folder', 'root') # סמן במפורש שאנחנו במצב העלאה לגיטהאב context.user_data['waiting_for'] = 'github_upload' context.user_data['upload_mode'] = 'github' context.user_data['target_repo'] = repo_name context.user_data['target_folder'] = folder # הודעה עם הוראות ברורות message = ( "📤 <b>העלאת קובץ לגיטהאב</b>\n\n" f"🔗 ריפו: <code>{repo_name}</code>\n" f"📂 תיקייה: <code>{folder}</code>\n\n" "<b>כדי להעלות קובץ מהמכשיר:</b>\n" "1) לחץ על 📎 בשורת ההודעה\n" "2) בחר 'Document' או 'File'\n" "3) בחר את הקובץ מהמכשיר\n" "4) שלח אותו\n\n" "⏳ ממתין לקובץ..." ) keyboard = [ [InlineKeyboardButton("📱 בחר מקבצים שמורים", callback_data="select_from_saved")], [InlineKeyboardButton("❌ ביטול", callback_data="github_menu")] ] await query.edit_message_text( message, parse_mode='HTML', reply_markup=InlineKeyboardMarkup(keyboard) )
# ============================================ # פונקציה מתוקנת לטיפול בקובץ שהתקבל # ============================================
[תיעוד] async def handle_document_fixed(update: Update, context: ContextTypes.DEFAULT_TYPE): """טיפול בקובץ שהתקבל""" # דיבאג logger.info(f"DEBUG: upload_mode = {context.user_data.get('upload_mode')}") logger.info(f"DEBUG: Document received: {update.message.document.file_name}") # בדוק אם אנחנו במצב העלאה לגיטהאב if context.user_data.get('upload_mode') == 'github': # הצג הודעת עיבוד processing_msg = await update.message.reply_text("⏳ מעבד את הקובץ...") try: # העלה לגיטהאב await upload_to_github_fixed(update, context, processing_msg) except Exception as e: await processing_msg.edit_text(f"❌ שגיאה: {str(e)}") finally: # נקה את מצב ההעלאה context.user_data['upload_mode'] = None else: # העבר לטיפול הרגיל return None # תן ל-handler הבא לטפל
# ============================================ # פונקציה מתוקנת להעלאה לגיטהאב # ============================================
[תיעוד] async def upload_to_github_fixed(update, context, status_message): """העלאה מתוקנת לגיטהאב""" # קבל את פרטי הקובץ document = update.message.document if not document: await status_message.edit_text("❌ לא התקבל קובץ תקין") return file_name = document.file_name await status_message.edit_text(f"📥 מוריד את {file_name}...") # הורד את הקובץ file = await document.get_file() file_bytes = await file.download_as_bytearray() # קבל פרטי יעד # אל תשתמש בברירת מחדל קשיחה שמובילה לריפו ישן repo_name = context.user_data.get('target_repo') if not repo_name and hasattr(context, 'bot_data') and hasattr(context.bot_data, 'github_handler'): session = context.bot_data.github_handler.get_user_session(update.effective_user.id) repo_name = session.get('selected_repo') if not repo_name: await status_message.edit_text("❌ לא נבחר ריפו. שלח /github ובחר ריפו") return folder = context.user_data.get('target_folder', '') # בנה נתיב מלא if folder and folder != 'root' and folder != '': file_path = f"{folder}/{file_name}" else: file_path = file_name # דיבאג logger.info(f"DEBUG: Repo = {repo_name}, Path = {file_path}") await status_message.edit_text(f"🔄 מתחבר לגיטהאב...") # קבל טוקן github_token = context.user_data.get('github_token') if not github_token: # נסה מהסשן של GitHub handler if hasattr(context.bot_data, 'github_handler'): user_session = context.bot_data.github_handler.get_user_session(update.effective_user.id) github_token = user_session.get('github_token') if not github_token: await status_message.edit_text( "❌ אין חיבור לגיטהאב.\n" "השתמש ב-/github להתחברות או הגדר טוקן." ) return logger.info(f"DEBUG: Token exists = {bool(github_token)}") try: # התחבר g = Github(github_token) user = g.get_user() await status_message.edit_text(f"📦 ניגש לריפו {repo_name}...") # קבל את הריפו repo = g.get_repo(repo_name) await status_message.edit_text(f"📤 מעלה את {file_name}...") # נסה להעלות/לעדכן try: # בדוק אם הקובץ כבר קיים existing_file = repo.get_contents(file_path) # עדכן קובץ קיים result = repo.update_file( path=file_path, message=f"Update {file_name} via Telegram bot", content=file_bytes, sha=existing_file.sha ) action = "עודכן" except: # צור קובץ חדש result = repo.create_file( path=file_path, message=f"Upload {file_name} via Telegram bot", content=file_bytes ) action = "הועלה" # הצלחה! צור לינק commit_sha = result['commit'].sha[:7] file_url = f"https://github.com/{repo_name}/blob/main/{file_path}" success_message = ( f"✅ **הקובץ {action} בהצלחה!**\n\n" f"📄 קובץ: `{file_name}`\n" f"📁 נתיב: `{file_path}`\n" f"🔗 ריפו: `{repo_name}`\n" f"🔖 Commit: `{commit_sha}`\n" ) keyboard = [ [InlineKeyboardButton("👁 צפה בקובץ", url=file_url)], [InlineKeyboardButton("📤 העלה עוד", callback_data="github_upload_new")], [InlineKeyboardButton("🔙 תפריט GitHub", callback_data="github_menu")] ] await status_message.edit_text( success_message, parse_mode='Markdown', reply_markup=InlineKeyboardMarkup(keyboard) ) except GithubException as e: error_msg = f"❌ שגיאת GitHub:\n`{str(e)}`\n\n" if "404" in str(e): error_msg += "• הריפו לא נמצא או אין הרשאות\n" elif "401" in str(e): error_msg += "• בעיית אימות - בדוק את הטוקן\n" elif "403" in str(e): error_msg += "• אין הרשאות כתיבה לריפו\n" await status_message.edit_text(error_msg, parse_mode='Markdown') except Exception as e: await status_message.edit_text( f"❌ שגיאה כללית:\n`{str(e)}`", parse_mode='Markdown' )
# ============================================ # הגדרת פקודות מינימליות - רק stats למנהל # ============================================
[תיעוד] async def setup_minimal_commands(application: Application) -> None: """מחיקת כל הפקודות והשארת רק stats למנהל""" # 1. מחק את כל הפקודות לכל המשתמשים await application.bot.delete_my_commands() print("✅ All public commands removed") # 2. הגדר רק stats למנהל (אמיר בירון) AMIR_ID = 6865105071 # ה-ID של אמיר בירון try: # הגדר את פקודת stats רק לאמיר await application.bot.set_my_commands( commands=[ BotCommand("stats", "📊 סטטיסטיקות שימוש") ], scope=BotCommandScopeChat(chat_id=AMIR_ID) ) print(f"✅ Stats command set for Amir (ID: {AMIR_ID})") except Exception as e: print(f"⚠️ Error setting admin commands: {e}")
# ============================================ # פונקציית stats מעודכנת עם בדיקת הרשאות # ============================================
[תיעוד] async def stats_command_secured(update: Update, context: ContextTypes.DEFAULT_TYPE): """הצג סטטיסטיקות - רק לאמיר בירון""" user_id = update.effective_user.id username = update.effective_user.username # רק אמיר יכול להשתמש AMIR_ID = 6865105071 if user_id != AMIR_ID: await update.message.reply_text( "⛔ הפקודה הזו זמינה רק למנהל המערכת." ) logger.warning(f"❌ Unauthorized stats attempt by @{username} (ID: {user_id})") return # כאן תצטרך להעתיק את הקוד הקיים של stats logger.info(f"✅ Stats shown to Amir")
# ... המשך הקוד של הסטטיסטיקות # ============================================ # פונקציה לבדיקת הפקודות (אופציונלי) # ============================================
[תיעוד] async def check_commands(update: Update, context: ContextTypes.DEFAULT_TYPE): """בדיקת הפקודות הזמינות (רק לאמיר)""" if update.effective_user.id != 6865105071: return # בדוק פקודות ציבוריות public_cmds = await context.bot.get_my_commands() # בדוק פקודות אישיות personal_cmds = await context.bot.get_my_commands( scope=BotCommandScopeChat(chat_id=6865105071) ) message = "📋 <b>סטטוס פקודות</b>\n\n" message += f"סיכום: ציבוריות {len(public_cmds)} | אישיות {len(personal_cmds)}\n\n" if public_cmds: public_list = "\n".join(f"/{cmd.command}" for cmd in public_cmds) message += "<b>ציבוריות:</b>\n" + f"<pre>{html_escape(public_list)}</pre>\n" if personal_cmds: personal_list = "\n".join(f"/{cmd.command}{cmd.description}" for cmd in personal_cmds) message += "<b>אישיות:</b>\n" + f"<pre>{html_escape(personal_list)}</pre>" await update.message.reply_text(message, parse_mode='HTML')