File size: 9,326 Bytes
c9c5e42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
import os
import threading
import time
import telebot
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
import fitz  # PyMuPDF
import subprocess
import shutil
import gradio as gr
from concurrent.futures import ThreadPoolExecutor

TOKEN = os.environ.get("BOT_TOKEN")
GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY")

if not TOKEN:
    raise ValueError("لطفاً BOT_TOKEN را در بخش Secrets تنظیم کنید.")

bot = telebot.TeleBot(TOKEN)
user_target_langs = {}

# استفاده از ThreadPool برای اینکه بات بتواند همزمان پاسخگوی چند کاربر باشد
executor = ThreadPoolExecutor(max_workers=3)

LANGUAGES = {
    "فارسی 🇮🇷": "fa",
    "انگلیسی 🇬🇧": "eng",
    "اسپانیایی 🇪🇸": "spa",
    "عربی 🇸🇦": "ara",
    "فرانسوی 🇫🇷": "fra",
    "روسی 🇷🇺": "rus"
}

def process_manga_page(image_bytes, page_num, target_lang, chat_id):
    input_filename = f"temp_in_{chat_id}_{page_num}.png"
    output_dir = f"temp_out_{chat_id}_{page_num}"
    
    with open(input_filename, "wb") as f:
        f.write(image_bytes)
        
    try:
        custom_env = os.environ.copy()
        
        command = [
            "manga_translator",
            "--mode", "batch",
            "--use-cpu",
            "-i", input_filename,
            "-d", output_dir,
            "--target-lang", target_lang
        ]
        
        if GEMINI_API_KEY:
            custom_env["OPENAI_API_KEY"] = GEMINI_API_KEY
            custom_env["OPENAI_API_BASE"] = "https://generativelanguage.googleapis.com/v1beta/openai/"
            command.extend(["--translator", "chatgpt"])
        else:
            command.extend(["--translator", "google"])
            
        subprocess.run(command, env=custom_env, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        
        translated_file_path = os.path.join(output_dir, input_filename)
        with open(translated_file_path, "rb") as f:
            translated_bytes = f.read()
            
        return translated_bytes
        
    except Exception as e:
        print(f"Error on page {page_num}: {e}")
        return image_bytes # در صورت خطا عکس اورجینال را حفظ کن
        
    finally:
        if os.path.exists(input_filename):
            os.remove(input_filename)
        if os.path.exists(output_dir):
            shutil.rmtree(output_dir)

def translate_task(input_path, output_path, chat_id, target_lang, message_id_to_edit):
    try:
        doc = fitz.open(input_path)
        new_doc = fitz.open()
        total_pages = len(doc)
        
        for page_num in range(total_pages):
            # آپدیت کردن پیام وضعیت به جای ارسال پیام جدید
            bot.edit_message_text(
                chat_id=chat_id,
                message_id=message_id_to_edit,
                text=f"🔄 **در حال پردازش مانگا...**\n\n"
                     f"📄 صفحه: {page_num + 1} از {total_pages}\n"
                     f"⚙️ عملیات: تشخیص زبان، ترجمه مفهومی با AI و جایگذاری متن...",
                parse_mode="Markdown"
            )
            
            page = doc[page_num]
            image_list = page.get_images(full=True)
            
            if image_list:
                xref = image_list[0][0]
                base_image = doc.extract_image(xref)
                image_bytes = base_image["image"]
                
                processed_bytes = process_manga_page(image_bytes, page_num, target_lang, chat_id)
                
                rect = page.rect
                new_page = new_doc.new_page(width=rect.width, height=rect.height)
                new_page.insert_image(rect, stream=processed_bytes)
            else:
                new_page = new_doc.new_page(width=page.rect.width, height=page.rect.height)
                new_page.show_pdf_page(new_page.rect, doc, page_num)

        # بهینه‌سازی و فشرده‌سازی PDF نهایی
        new_doc.save(output_path, garbage=4, deflate=True)
        new_doc.close()
        doc.close()
        
        bot.edit_message_text(
            chat_id=chat_id,
            message_id=message_id_to_edit,
            text="✅ **پردازش تمام شد! در حال آپلود فایل...**",
            parse_mode="Markdown"
        )
        
        with open(output_path, 'rb') as final_doc:
            bot.send_document(chat_id, final_doc, caption="🎉 این هم از مانگای ترجمه‌شده شما!\nامیدوارم از خواندنش لذت ببرید.")
            
    except Exception as e:
        bot.send_message(chat_id, f"❌ متأسفانه در حین پردازش خطایی رخ داد: {str(e)}")
        
    finally:
        if os.path.exists(input_path):
            os.remove(input_path)
        if os.path.exists(output_path):
            os.remove(output_path)

def language_keyboard():
    markup = InlineKeyboardMarkup()
    markup.row_width = 2
    buttons = [InlineKeyboardButton(text, callback_data=f"lang_{code}") for text, code in LANGUAGES.items()]
    markup.add(*buttons)
    return markup

@bot.message_handler(commands=['start', 'help', 'language'])
def send_welcome(message):
    user_target_langs[message.chat.id] = "fa" 
    bot.reply_to(
        message, 
        "به ربات فوق‌پیشرفته مترجم مانگا خوش آمدید! 📚✨\n\n"
        "فرقی نمی‌کند یک داستان عاشقانه لطیف باشد یا یک ایسکای تاریک و روان‌شناختی با اصطلاحات پیچیده؛ من زبان اصلی را کاملاً خودکار تشخیص داده و با هوش مصنوعی (Gemini/ChatGPT) به بهترین شکل ترجمه و تایپ می‌کنم.\n\n"
        "👇 ابتدا از منوی زیر زبان مقصد را انتخاب کنید و سپس فایل PDF را بفرستید:",
        reply_markup=language_keyboard()
    )

@bot.callback_query_handler(func=lambda call: call.data.startswith('lang_'))
def handle_language_selection(call):
    lang_code = call.data.split('_')[1]
    user_target_langs[call.message.chat.id] = lang_code
    bot.answer_callback_query(call.id, "زبان با موفقیت تغییر کرد!")
    bot.edit_message_text(
        chat_id=call.message.chat.id, 
        message_id=call.message.message_id, 
        text=f"✅ زبان مقصد روی **{lang_code}** تنظیم شد.\n\nاکنون منتظر دریافت فایل PDF شما هستم.",
        parse_mode="Markdown"
    )

@bot.message_handler(content_types=['document'])
def handle_docs(message):
    chat_id = message.chat.id
    target_lang = user_target_langs.get(chat_id, "fa") 
    
    if message.document.mime_type != 'application/pdf':
        bot.reply_to(message, "لطفاً فقط فایل با فرمت PDF ارسال کنید. 🚫")
        return
        
    # بررسی حجم فایل (تلگرام محدودیت ۲۰ مگابایتی برای ربات‌ها دارد)
    if message.document.file_size > 20 * 1024 * 1024:
        bot.reply_to(message, "⚠️ حجم فایل شما بیشتر از ۲۰ مگابایت است. ربات‌های تلگرام به صورت پیش‌فرض نمی‌توانند فایل‌های بزرگتر را دانلود کنند. لطفاً فایل را به بخش‌های کوچکتر تقسیم کنید.")
        return

    status_message = bot.reply_to(message, "📥 در حال دانلود فایل از سرورهای تلگرام...")
    
    try:
        file_info = bot.get_file(message.document.file_id)
        downloaded_file = bot.download_file(file_info.file_path)
        
        input_pdf = f"input_{chat_id}_{message.message_id}.pdf"
        output_pdf = f"output_{chat_id}_{message.message_id}.pdf"
        
        with open(input_pdf, 'wb') as new_file:
            new_file.write(downloaded_file)
            
        bot.edit_message_text(
            chat_id=chat_id,
            message_id=status_message.message_id,
            text="✅ فایل دریافت شد. فایل به صف پردازش اضافه شد..."
        )
        
        # ارسال کار به پس‌زمینه تا ربات هنگ نکند
        executor.submit(translate_task, input_pdf, output_pdf, chat_id, target_lang, status_message.message_id)
        
    except Exception as e:
        bot.edit_message_text(
            chat_id=chat_id,
            message_id=status_message.message_id,
            text=f"❌ خطایی در دریافت فایل رخ داد: {str(e)}"
        )

def run_bot():
    bot.infinity_polling(timeout=60, long_polling_timeout=60)

thread = threading.Thread(target=run_bot)
thread.start()

with gr.Blocks() as demo:
    gr.Markdown("# 🚀 نسخه نهایی و بهینه‌شده مترجم مانگا در حال اجراست!")
    gr.Markdown("این نسخه مجهز به **Threading**، **فشرده‌سازی PDF** و **سیستم ویرایش پیام زنده** است.")
    if GEMINI_API_KEY:
        gr.Markdown("✅ موتور هوش مصنوعی Gemini به عنوان مترجم مفهومی **متصل است**.")
        
demo.launch()