| import os |
| import time |
| import threading |
| import random |
| import aiohttp |
| import traceback |
| import asyncio |
| import base64 |
| import mimetypes |
| import io |
| import json |
| import datetime |
| import string |
| import uuid |
| from flask import Flask |
|
|
| |
| import telebot |
| from telebot.async_telebot import AsyncTeleBot |
| from telebot import asyncio_helper |
| from telebot.types import ReplyKeyboardMarkup, KeyboardButton |
|
|
| |
| from huggingface_hub import AsyncInferenceClient, HfApi, hf_hub_download |
| from PIL import Image |
| from pydub import AudioSegment |
|
|
| |
| asyncio_helper.API_URL = "https://tapi.bale.ai/bot{0}/{1}" |
| asyncio_helper.FILE_URL = "https://tapi.bale.ai/file/bot{0}/{1}" |
|
|
| |
| ADMIN_CODE = "3011" |
| BOT_GUID = None |
|
|
| |
| DB_FILE = "users_db.json" |
| DATASET_REPO = "Opera8/Karbaran-rayegan-tedad" |
| HF_TOKEN_DB = os.environ.get("HF_TOKEN") |
| db_lock = threading.Lock() |
|
|
| def gregorian_to_jalali(gy, gm, gd): |
| g_d_m =[0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334] |
| gy2 = (gy + 1) if (gm > 2) else gy |
| days = 355666 + (365 * gy) + ((gy2 + 3) // 4) - ((gy2 + 99) // 100) + ((gy2 + 399) // 400) + gd + g_d_m[gm - 1] |
| jy = -1595 + (33 * (days // 12053)) |
| days %= 12053 |
| jy += 4 * (days // 1461) |
| days %= 1461 |
| if days > 365: |
| jy += (days - 1) // 365 |
| days = (days - 1) % 365 |
| if days < 186: |
| jm = 1 + (days // 31) |
| jd = 1 + (days % 31) |
| else: |
| jm = 7 + ((days - 186) // 30) |
| jd = 1 + ((days - 186) % 30) |
| return jy, jm, jd |
|
|
| def load_db(): |
| print("در حال تلاش برای خواندن دیتابیس کاربران از دیتاست هاگینگ فیس...") |
| if HF_TOKEN_DB: |
| try: |
| file_path = hf_hub_download( |
| repo_id=DATASET_REPO, |
| filename=DB_FILE, |
| repo_type="dataset", |
| token=HF_TOKEN_DB |
| ) |
| with open(file_path, "r", encoding="utf-8") as f: |
| print("✅ دیتابیس با موفقیت از دیتاست هاگینگ فیس لود شد.") |
| return json.load(f) |
| except Exception as e: |
| print("⚠️ فایل دیتابیس در هاگینگ فیس یافت نشد (ساخت دیتابیس جدید).") |
| |
| if os.path.exists(DB_FILE): |
| try: |
| with open(DB_FILE, "r", encoding="utf-8") as f: |
| return json.load(f) |
| except Exception: |
| pass |
| return {} |
|
|
| def _upload_db_background(): |
| if HF_TOKEN_DB: |
| api = HfApi(token=HF_TOKEN_DB) |
| try: |
| api.upload_file( |
| path_or_fileobj=DB_FILE, |
| path_in_repo=DB_FILE, |
| repo_id=DATASET_REPO, |
| repo_type="dataset" |
| ) |
| except Exception as e: |
| print("❌ خطا در آپلود دیتابیس به هاگینگ فیس:", str(e)[:100]) |
|
|
| def save_db(db_data): |
| with db_lock: |
| try: |
| with open(DB_FILE, "w", encoding="utf-8") as f: |
| json.dump(db_data, f, ensure_ascii=False, indent=4) |
| threading.Thread(target=_upload_db_background, daemon=True).start() |
| except Exception as e: |
| print("خطا در ذخیره دیتابیس:", e) |
|
|
| user_credits_db = load_db() |
|
|
| def get_user_credits(chat_id): |
| str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip() |
| today_str = datetime.date.today().isoformat() |
| |
| if str_chat_id not in user_credits_db: |
| user_credits_db[str_chat_id] = { |
| "is_premium": False, |
| "expire_date": None, |
| "last_reset": "", |
| "chat": 10, |
| "image": 5, |
| "edit_image": 1, |
| "podcast": 2, |
| "tts": 5, |
| "file": 1, |
| "stt": 5, |
| "has_joined": False |
| } |
| save_db(user_credits_db) |
| |
| user_data = user_credits_db[str_chat_id] |
| is_premium = user_data.get("is_premium", False) |
| |
| if is_premium and user_data.get("expire_date"): |
| try: |
| expire_date = datetime.datetime.fromisoformat(user_data["expire_date"]) |
| if datetime.datetime.now() > expire_date: |
| user_data["is_premium"] = False |
| user_data["expire_date"] = None |
| is_premium = False |
| except Exception: |
| pass |
|
|
| if not is_premium: |
| if user_data.get("last_reset") != today_str: |
| user_data["last_reset"] = today_str |
| user_data["chat"] = 10 |
| user_data["image"] = 5 |
| user_data["edit_image"] = 1 |
| user_data["podcast"] = 2 |
| user_data["tts"] = 5 |
| user_data["file"] = 1 |
| user_data["stt"] = 5 |
| save_db(user_credits_db) |
| |
| return user_data |
|
|
| def to_english_digits(text): |
| if not text: |
| return text |
| persian_digits = '۰۱۲۳۴۵۶۷۸۹' |
| arabic_digits = '٠١٢٣٤٥٦٧٨٩' |
| english_digits = '0123456789' |
| translation_table = str.maketrans(persian_digits + arabic_digits, english_digits * 2) |
| return str(text).translate(translation_table) |
|
|
| |
| app = Flask(__name__) |
|
|
| @app.route('/') |
| def home(): |
| return "ربات یکپارچه آلفا (متصل به بله + دیتاست + بدون قفلی) روشن است! 🚀" |
|
|
| def run_flask(): |
| app.run(host="0.0.0.0", port=7860) |
|
|
|
|
| |
| def get_main_keyboard(): |
| markup = ReplyKeyboardMarkup(resize_keyboard=True) |
| markup.row(KeyboardButton("چت با هوش مصنوعی 🤖")) |
| markup.row(KeyboardButton("ساخت تصاویر🎨"), KeyboardButton("ویرایش تصاویر 🪄")) |
| markup.row(KeyboardButton("ساخت پادکست 🎙️"), KeyboardButton("تبدیل متن به صدا🗣️")) |
| markup.row(KeyboardButton("فایل صوتی به متن 📝"), KeyboardButton("تحلیل فایل 📁")) |
| markup.row(KeyboardButton("ساخت فایل 📄")) |
| markup.row(KeyboardButton("حساب کاربری 👤"), KeyboardButton("خرید اشتراک 💎")) |
| markup.row(KeyboardButton("انتقال اکانت از برنامه به ربات")) |
| markup.row(KeyboardButton("برگشت♻️")) |
| return markup |
|
|
| def get_join_keyboard(): |
| markup = ReplyKeyboardMarkup(resize_keyboard=True) |
| markup.row(KeyboardButton("✅ عضو شدم")) |
| return markup |
|
|
|
|
| |
| async def send_with_keyboard(client, chat_id, text, use_keyboard=True): |
| try: |
| markup = get_main_keyboard() if use_keyboard else None |
| return await client.send_message(chat_id, text, reply_markup=markup) |
| except Exception: |
| try: |
| return await client.send_message(chat_id, text) |
| except Exception: |
| return None |
|
|
|
|
| |
| async def helper_download_file(client, message): |
| file_id = None |
| if message.document: |
| file_id = message.document.file_id |
| elif message.photo: |
| file_id = message.photo[-1].file_id |
| elif message.voice: |
| file_id = message.voice.file_id |
| elif message.audio: |
| file_id = message.audio.file_id |
| elif message.video: |
| file_id = message.video.file_id |
| |
| if not file_id: |
| raise Exception("هیچ فایلی برای دانلود یافت نشد.") |
| |
| file_info = await client.get_file(file_id) |
| downloaded_bytes = await client.download_file(file_info.file_path) |
| return downloaded_bytes |
|
|
|
|
| |
| GEMINI_KEYS_STR1 = os.environ.get("GEMINI_API_KEYS1", "") |
| GEMINI_KEYS_STR2 = os.environ.get("GEMINI_API_KEYS2", "") |
|
|
| _raw_keys =[] |
| if GEMINI_KEYS_STR1: |
| _raw_keys.extend(GEMINI_KEYS_STR1.split(",")) |
| if GEMINI_KEYS_STR2: |
| _raw_keys.extend(GEMINI_KEYS_STR2.split(",")) |
|
|
| GEMINI_KEYS = list(set([k.strip() for k in _raw_keys if k.strip()])) |
| current_gemini_key_index = 0 |
| gemini_key_lock = threading.Lock() |
|
|
| def get_next_gemini_keys(count=100): |
| global current_gemini_key_index |
| with gemini_key_lock: |
| total_keys = len(GEMINI_KEYS) |
| if total_keys == 0: |
| return[] |
| |
| actual_count = min(count, total_keys) |
| selected_keys =[] |
| |
| for _ in range(actual_count): |
| selected_keys.append(GEMINI_KEYS[current_gemini_key_index]) |
| current_gemini_key_index = (current_gemini_key_index + 1) % total_keys |
| |
| return selected_keys |
|
|
| HF_TOKENS_STR = os.environ.get("HF_TOKENS", "") |
| HF_TOKENS =[k.strip() for k in HF_TOKENS_STR.split(",") if k.strip()] |
|
|
| |
| bot_token = os.environ.get("BALE_TOKEN", "").strip() |
|
|
|
|
| |
| async def helper_upload_file(client, chat_id, file_name, file_type="Image", caption=""): |
| abs_path = os.path.abspath(file_name) |
| try: |
| with open(abs_path, "rb") as f: |
| markup = get_main_keyboard() |
| if file_type in["photo", "Image", "image"]: |
| await client.send_photo(chat_id, photo=f, caption=caption, reply_markup=markup) |
| elif file_type in["voice", "Voice", "audio"]: |
| if abs_path.lower().endswith('.ogg'): |
| await client.send_voice(chat_id, voice=f, caption=caption, reply_markup=markup) |
| else: |
| await client.send_audio(chat_id, audio=f, caption=caption, reply_markup=markup) |
| elif file_type == "Music": |
| await client.send_audio(chat_id, audio=f, caption=caption, reply_markup=markup) |
| else: |
| await client.send_document(chat_id, document=f, caption=caption, reply_markup=markup) |
| return True |
| except Exception as e: |
| return f"Bale Send Error: {str(e)[:100]}" |
|
|
|
|
| WORKER_URLS = ["https://opera8-ttspro.hf.space/generate"] |
|
|
| SPEAKERS = { |
| "1": ("شهاب (مرد)", "Charon"), "2": ("آوا (زن)", "Zephyr"), "3": ("نوید (مرد)", "Achird"), |
| "4": ("آرمان (مرد)", "Zubenelgenubi"), "5": ("مهسا (زن)", "Vindemiatrix"), "6": ("دانا (مرد)", "Rasalgethi"), |
| "7": ("سامان (مرد)", "Sadachbia"), "8": ("آرش (مرد)", "Sadaltager"), "9": ("شبنم (زن)", "Sulafat"), |
| "10": ("سحر (زن)", "Laomedeia"), "11": ("مریم (زن)", "Achernar"), "12": ("بهرام (مرد)", "Alnilam"), |
| "13": ("نیکان (مرد)", "Schedar"), "14": ("فرناز (زن)", "Gacrux"), "15": ("سارا (زن)", "Pulcherrima"), |
| "16": ("مانی (مرد)", "Umbriel"), "17": ("آرتین (مرد)", "Algieba"), "18": ("دلنواز (زن)", "Despina"), |
| "19": ("روژان (زن)", "Erinome"), "20": ("امید (مرد)", "Algenib"), "21": ("بردیا (مرد)", "Orus"), |
| "22": ("ترانه (زن)", "Aoede"), "23": ("نیکو (زن)", "Callirrhoe"), "24": ("هستی (زن)", "Autonoe"), |
| "25": ("کامیار (مرد)", "Enceladus"), "26": ("کیانوش (مرد)", "Iapetus"), "27": ("پویا (مرد)", "Puck"), |
| "28": ("مهتاب (زن)", "Kore"), "29": ("سام (مرد)", "Fenrir"), "30": ("لیدا (زن)", "Leda") |
| } |
|
|
| user_states = {} |
| processed_message_ids = set() |
|
|
| |
| async def process_gemini(client, chat_id, prompt, file_bytes=None, file_name=None): |
| str_chat_id = str(chat_id) |
| creds = get_user_credits(str_chat_id) |
| if creds["chat"] <= 0: |
| return await send_with_keyboard(client, chat_id, "❌ اعتبار پیامهای چت شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False) |
|
|
| if not GEMINI_KEYS: return await send_with_keyboard(client, chat_id, "❌ کلیدهای API جیمینای تنظیم نشدهاند.", False) |
| |
| proc_msg = await send_with_keyboard(client, chat_id, "🧠 در حال پردازش...", False) |
| history = user_states[chat_id].get("history",[]) |
| new_parts =[] |
| |
| if prompt: new_parts.append({"text": prompt}) |
| elif file_bytes: new_parts.append({"text": "لطفاً این فایل را به دقت بررسی کن."}) |
| |
| if file_bytes and file_name: |
| base64_data = base64.b64encode(file_bytes).decode('utf-8') |
| mime_type, _ = mimetypes.guess_type(file_name) |
| if not mime_type: |
| mime_type = "image/jpeg" |
| new_parts.append({"inlineData": {"mimeType": mime_type, "data": base64_data}}) |
|
|
| if history and history[-1]["role"] == "user": history[-1]["parts"].extend(new_parts) |
| else: history.append({"role": "user", "parts": new_parts}) |
|
|
| if len(history) > 40: |
| history = history[-40:] |
| if history[0]["role"] == "model": history = history[1:] |
|
|
| keys_to_try = get_next_gemini_keys(100) |
| final_answer = None |
| |
| async with aiohttp.ClientSession() as session: |
| for key in keys_to_try: |
| url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}" |
| payload = {"contents": history, "generationConfig": {"temperature": 0.7, "maxOutputTokens": 8192}} |
| try: |
| async with session.post(url, json=payload, timeout=60) as response: |
| if response.status == 200: |
| data = await response.json() |
| try: |
| final_answer = data["candidates"][0]["content"]["parts"][0]["text"] |
| break |
| except (KeyError, IndexError): continue |
| except Exception: continue |
|
|
| if not final_answer and HF_TOKENS: |
| hf_messages =[] |
| for msg in history: |
| role = "assistant" if msg["role"] == "model" else "user" |
| content_parts =[] |
| for part in msg["parts"]: |
| if "text" in part: |
| content_parts.append({"type": "text", "text": part["text"]}) |
| elif "inlineData" in part: |
| mime_t = part["inlineData"]["mimeType"] |
| b64_d = part["inlineData"]["data"] |
| content_parts.append({ |
| "type": "image_url", |
| "image_url": {"url": f"data:{mime_t};base64,{b64_d}"} |
| }) |
| hf_messages.append({"role": role, "content": content_parts}) |
|
|
| keys_to_try_hf = HF_TOKENS.copy() |
| random.shuffle(keys_to_try_hf) |
| |
| async with aiohttp.ClientSession() as session: |
| for hf_key in keys_to_try_hf: |
| url = "https://router.huggingface.co/v1/chat/completions" |
| headers = {"Authorization": f"Bearer {hf_key}", "Content-Type": "application/json"} |
| payload = {"model": "google/gemma-4-31B-it:novita", "messages": hf_messages, "max_tokens": 4096} |
| try: |
| async with session.post(url, headers=headers, json=payload, timeout=60) as response: |
| if response.status == 200: |
| data = await response.json() |
| final_answer = data["choices"][0]["message"]["content"] |
| break |
| except Exception: |
| continue |
|
|
| try: |
| if proc_msg: |
| msg_id = getattr(proc_msg, 'message_id', None) |
| if msg_id: await client.delete_message(chat_id, msg_id) |
| except Exception: pass |
|
|
| if not final_answer: |
| if history and history[-1]["role"] == "user": history.pop() |
| await send_with_keyboard(client, chat_id, "❌ سرور شلوغ است فعلا بعدا امتحان کنید.", False) |
| return |
|
|
| if not creds.get("is_premium"): |
| user_credits_db[str_chat_id]["chat"] -= 1 |
| save_db(user_credits_db) |
|
|
| history.append({"role": "model", "parts":[{"text": final_answer}]}) |
| user_states[chat_id]["history"] = history |
|
|
| try: |
| max_len = 1000 |
| chunks =[] |
| temp_text = final_answer |
| while len(temp_text) > max_len: |
| split_idx = temp_text.rfind('\n', 0, max_len) |
| if split_idx == -1: split_idx = temp_text.rfind(' ', 0, max_len) |
| if split_idx == -1: split_idx = max_len |
| chunks.append(temp_text[:split_idx]) |
| temp_text = temp_text[split_idx:].strip() |
| if temp_text: chunks.append(temp_text) |
| |
| for idx, chunk in enumerate(chunks): |
| if idx != len(chunks) - 1: chunk += "\n\n⏳ *(ادامه در پیام بعدی)...* 👇" |
| try: |
| await send_with_keyboard(client, chat_id, chunk, False) |
| await asyncio.sleep(2.5) |
| except Exception: await asyncio.sleep(2.5) |
| |
| except Exception: |
| await send_with_keyboard(client, chat_id, "❌ خطایی در ارسال پیام رخ داد.", False) |
|
|
|
|
| |
| async def process_image(client, chat_id, prompt): |
| str_chat_id = str(chat_id) |
| creds = get_user_credits(str_chat_id) |
| if creds["image"] <= 0: |
| return await send_with_keyboard(client, chat_id, "❌ اعتبار ساخت عکس شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False) |
|
|
| if not HF_TOKENS: return await send_with_keyboard(client, chat_id, "❌ توکنهای هاگینگ فیس تنظیم نشدهاند.", False) |
| |
| proc_msg = await send_with_keyboard(client, chat_id, "✨ در حال ترجمه و بهینهسازی پرامپت شما...\n(تبدیل به پرامپت حرفهای)", False) |
| enhanced_prompt = prompt |
| gemini_sys_prompt = f"You are an expert AI image generation prompt engineer. Translate the following user input to English, and enhance it with high-quality, highly detailed, 4k resolution, cinematic lighting, and visually striking descriptive keywords. Return ONLY the final English prompt string.\nUser input: {prompt}" |
| |
| if GEMINI_KEYS: |
| keys_to_try_gemini = get_next_gemini_keys(100) |
| async with aiohttp.ClientSession() as session: |
| for key in keys_to_try_gemini: |
| url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}" |
| payload = {"contents": [{"parts":[{"text": gemini_sys_prompt}]}], "generationConfig": {"temperature": 0.7}} |
| try: |
| async with session.post(url, json=payload, timeout=20) as response: |
| if response.status == 200: |
| data = await response.json() |
| enhanced_prompt = data["candidates"][0]["content"]["parts"][0]["text"].strip() |
| break |
| except Exception: continue |
|
|
| if enhanced_prompt == prompt and HF_TOKENS: |
| keys_to_try_hf = HF_TOKENS.copy() |
| random.shuffle(keys_to_try_hf) |
| async with aiohttp.ClientSession() as session: |
| for hf_key in keys_to_try_hf: |
| url = "https://router.huggingface.co/v1/chat/completions" |
| headers = {"Authorization": f"Bearer {hf_key}", "Content-Type": "application/json"} |
| payload = {"model": "google/gemma-4-31B-it:novita", "messages":[{"role": "user", "content":[{"type": "text", "text": gemini_sys_prompt}]}], "max_tokens": 1024} |
| try: |
| async with session.post(url, headers=headers, json=payload, timeout=20) as response: |
| if response.status == 200: |
| data = await response.json() |
| enhanced_prompt = data["choices"][0]["message"]["content"].strip() |
| break |
| except Exception: |
| continue |
|
|
| try: |
| if proc_msg: |
| msg_id = getattr(proc_msg, 'message_id', None) |
| if msg_id: await client.delete_message(chat_id, msg_id) |
| except Exception: pass |
| |
| short_preview = enhanced_prompt[:150] + "..." if len(enhanced_prompt) > 150 else enhanced_prompt |
| proc_msg = await send_with_keyboard(client, chat_id, f"🎨 در حال طراحی عکس...\n\n📝 پرامپت ساخته شده:\n`{short_preview}`\n\n(ممکن است چند ثانیه زمان ببرد)", False) |
|
|
| keys_to_try = HF_TOKENS.copy() |
| random.shuffle(keys_to_try) |
| generated_image = None |
| last_error_log = "هیچ اتصالی برقرار نشد." |
| |
| for token in keys_to_try: |
| try: |
| hf_client = AsyncInferenceClient(provider="fal-ai", api_key=token) |
| generated_image = await hf_client.text_to_image(enhanced_prompt, model="Tongyi-MAI/Z-Image-Turbo") |
| break |
| except Exception as e: |
| last_error_log = str(e) |
| continue |
| |
| try: |
| if proc_msg: |
| msg_id = getattr(proc_msg, 'message_id', None) |
| if msg_id: await client.delete_message(chat_id, msg_id) |
| except Exception: pass |
|
|
| if not generated_image: return await send_with_keyboard(client, chat_id, f"❌ عکس ساخته نشد.\n\n⚠️ خطا:\n{last_error_log[:200]}", True) |
|
|
| user_credits_db[str_chat_id]["image"] -= 1 |
| save_db(user_credits_db) |
|
|
| try: |
| file_name = f"image_{uuid.uuid4().hex}.jpg" |
| rgb_im = generated_image.convert('RGB') |
| rgb_im.save(file_name, format="JPEG", quality=100) |
| await asyncio.sleep(1) |
| caption_text = f"🎨 تصویر شما با پرامپت هوشمند آماده شد!\n\n✨ ایده اولیه: {prompt}" |
| upload_result = await helper_upload_file(client, chat_id, file_name, "Image", caption_text) |
| if upload_result is not True: await send_with_keyboard(client, chat_id, f"❌ خطا در آپلود بله:\n`{str(upload_result)[:800]}`", True) |
| if os.path.exists(file_name): os.remove(file_name) |
| except Exception as e: await send_with_keyboard(client, chat_id, f"❌ خطا در ذخیره عکس:\n{str(e)[:150]}", True) |
|
|
| async def translate_text_aloha(prompt_text): |
| session_hash = ''.join(random.choices(string.ascii_lowercase + string.digits, k=11)) |
| join_url = "https://hamed744-translate-tts-aloha.hf.space/gradio_api/queue/join" |
| payload = { |
| "data":[prompt_text, "انگلیسی (آمریکا) - جنی (زن)", 0, 0, 0], |
| "fn_index": 1, |
| "session_hash": session_hash |
| } |
| |
| try: |
| async with aiohttp.ClientSession() as session: |
| async with session.post(join_url, json=payload, timeout=20) as resp: |
| if resp.status != 200: |
| return prompt_text |
| |
| data_url = f"https://hamed744-translate-tts-aloha.hf.space/gradio_api/queue/data?session_hash={session_hash}" |
| async with session.get(data_url, timeout=60) as resp: |
| async for line_bytes in resp.content: |
| line = line_bytes.decode('utf-8').strip() |
| if line.startswith("data: "): |
| try: |
| json_data = json.loads(line[6:]) |
| if json_data.get("msg") == "process_completed": |
| if json_data.get("success"): |
| return json_data["output"]["data"][0] |
| break |
| except Exception: |
| pass |
| except Exception: |
| pass |
| |
| return prompt_text |
|
|
| |
| async def process_image_edit(client, chat_id, image_bytes, prompt): |
| str_chat_id = str(chat_id) |
| creds = get_user_credits(str_chat_id) |
| if creds["edit_image"] <= 0: |
| return await send_with_keyboard(client, chat_id, "❌ اعتبار ویرایش عکس شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False) |
|
|
| if not HF_TOKENS: |
| return await send_with_keyboard(client, chat_id, "❌ توکنهای هاگینگ فیس تنظیم نشدهاند.", False) |
|
|
| proc_msg = await send_with_keyboard(client, chat_id, "🪄 در حال ترجمه دستور شما توسط اسپیس و اعمال جادوی FLUX.2...\n(این فرآیند ممکن است کمی طول بکشد)", False) |
| |
| translated_prompt = await translate_text_aloha(prompt) |
| if not translated_prompt or translated_prompt.strip() == "": |
| translated_prompt = prompt |
|
|
| keys_to_try = HF_TOKENS.copy() |
| random.shuffle(keys_to_try) |
| generated_image = None |
| last_error_log = "سرور پاسخ نداد." |
| |
| for token in keys_to_try: |
| try: |
| hf_client = AsyncInferenceClient(provider="fal-ai", api_key=token) |
| generated_image = await hf_client.image_to_image( |
| image_bytes, |
| prompt=translated_prompt, |
| model="black-forest-labs/FLUX.2-dev" |
| ) |
| break |
| except Exception as e: |
| last_error_log = str(e) |
| continue |
| |
| try: |
| if proc_msg: |
| msg_id = getattr(proc_msg, 'message_id', None) |
| if msg_id: await client.delete_message(chat_id, msg_id) |
| except Exception: pass |
|
|
| if not generated_image: |
| return await send_with_keyboard(client, chat_id, f"❌ متأسفانه ویرایش عکس انجام نشد.\n\n⚠️ علت:\n{last_error_log[:200]}", True) |
|
|
| user_credits_db[str_chat_id]["edit_image"] -= 1 |
| save_db(user_credits_db) |
|
|
| try: |
| file_name = f"edited_flux_{uuid.uuid4().hex}.jpg" |
| rgb_im = generated_image.convert('RGB') |
| rgb_im.save(file_name, format="JPEG", quality=100) |
| await asyncio.sleep(1) |
| caption_text = f"🪄 ویرایش عکس با هوش مصنوعی Flux.2 انجام شد!\n\n✨ تغییرات خواسته شده: {prompt}\n🔤 متن ارسال شده به هوش: {translated_prompt}" |
| upload_result = await helper_upload_file(client, chat_id, file_name, "Image", caption_text) |
| if upload_result is not True: |
| await send_with_keyboard(client, chat_id, f"❌ عکس ساخته شد اما خطا در ارسال به بله رخ داد:\n`{str(upload_result)[:800]}`", True) |
| if os.path.exists(file_name): os.remove(file_name) |
| except Exception as e: |
| await send_with_keyboard(client, chat_id, f"❌ خطا در ذخیره عکس ویرایش شده:\n{str(e)[:150]}", True) |
|
|
|
|
| |
| async def process_tts(client, chat_id, user_text, speaker_id, speaker_name): |
| str_chat_id = str(chat_id) |
| creds = get_user_credits(str_chat_id) |
| if creds["tts"] <= 0: |
| return await send_with_keyboard(client, chat_id, "❌ اعتبار تبدیل متن به صدای شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False) |
|
|
| try: |
| proc_msg = await send_with_keyboard(client, chat_id, f"⏳ در حال ساخت صدا با «{speaker_name}»...\n(لطفاً صبور باشید)", False) |
| payload = {"text": user_text, "speaker": speaker_id, "temperature": 1.5, "prompt": "", "use_live_model": True} |
| headers = {"User-Agent": "Mozilla/5.0", "Content-Type": "application/json"} |
| audio_bytes = None |
| last_error = "پاسخی دریافت نشد" |
| workers = WORKER_URLS.copy() |
| random.shuffle(workers) |
| |
| async with aiohttp.ClientSession(headers=headers, timeout=aiohttp.ClientTimeout(total=600)) as session: |
| for worker_url in workers[:3]: |
| try: |
| async with session.post(worker_url, json=payload) as response: |
| if response.status == 200: |
| content_type = response.headers.get('Content-Type', '') |
| if 'audio' in content_type or response.content_length > 1000: |
| audio_bytes = await response.read() |
| break |
| else: last_error = "فایل نامعتبر" |
| else: last_error = f"ارور ({response.status})" |
| except Exception as e: last_error = f"خطا: {str(e)}"; continue |
|
|
| try: |
| if proc_msg: |
| msg_id = getattr(proc_msg, 'message_id', None) |
| if msg_id: await client.delete_message(chat_id, msg_id) |
| except Exception: pass |
|
|
| if audio_bytes: |
| if not creds.get("is_premium"): |
| user_credits_db[str_chat_id]["tts"] -= 1 |
| save_db(user_credits_db) |
| |
| file_name_mp3 = f"audio_{uuid.uuid4().hex}.mp3" |
| |
| with open(file_name_mp3, "wb") as f: f.write(audio_bytes) |
| |
| await asyncio.sleep(1) |
| |
| upload_result_file = await helper_upload_file(client, chat_id, file_name_mp3, "File", "✅ صدای شما با موفقیت آماده شد (فایل MP3):") |
| |
| if upload_result_file is not True: |
| await send_with_keyboard(client, chat_id, f"❌ ارور آپلود فایل:\n`{str(upload_result_file)[:800]}`", True) |
| |
| if os.path.exists(file_name_mp3): os.remove(file_name_mp3) |
| else: await send_with_keyboard(client, chat_id, f"❌ سرورها درگیر هستند.\nدلیل: {last_error}", True) |
| except Exception: traceback.print_exc() |
|
|
|
|
| |
| async def process_podcast(client, chat_id, prompt): |
| str_chat_id = str(chat_id) |
| creds = get_user_credits(str_chat_id) |
| if creds["podcast"] <= 0: |
| return await send_with_keyboard(client, chat_id, "❌ اعتبار ساخت پادکست شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False) |
|
|
| proc_msg = await send_with_keyboard(client, chat_id, "📻 در حال بررسی موضوع و نگارش سناریوی پادکست توسط هوش مصنوعی...\n(لطفاً صبور باشید)", False) |
| available_speakers =[] |
| for num_key, (spk_name, spk_id) in SPEAKERS.items(): |
| gender = "male" if "مرد" in spk_name else "female" |
| available_speakers.append({"id": spk_id, "name": spk_name.split(' (')[0], "gender": gender}) |
|
|
| url_create = "https://opera8-podgen.hf.space/api/create-full-podcast" |
| payload_create = {"prompt": prompt, "available_speakers": available_speakers} |
| |
| async with aiohttp.ClientSession() as session: |
| try: |
| async with session.post(url_create, json=payload_create, timeout=60) as resp: |
| if resp.status != 202: return await send_with_keyboard(client, chat_id, f"❌ خطا در سرور پادکست: وضعیت {resp.status}", True) |
| task_id = (await resp.json()).get("task_id") |
| except Exception as e: return await send_with_keyboard(client, chat_id, f"❌ خطا در اتصال به سرور پادکست:\n{str(e)}", True) |
|
|
| url_status = f"https://opera8-podgen.hf.space/api/podcast-status/{task_id}" |
| script_data = None |
| for _ in range(500): |
| await asyncio.sleep(3) |
| try: |
| async with session.get(url_status) as resp: |
| if resp.status == 200: |
| status_data = await resp.json() |
| if status_data.get("status") == "completed": |
| script_data = status_data.get("data", {}).get("script",[]) |
| break |
| elif status_data.get("status") == "failed": |
| return await send_with_keyboard(client, chat_id, "❌ متأسفانه هوش مصنوعی نتوانست برای این موضوع سناریو بنویسد.", True) |
| except Exception: pass |
| |
| if not script_data: return await send_with_keyboard(client, chat_id, "❌ زمان انتظار برای نوشتن سناریو به پایان رسید.", True) |
|
|
| try: |
| if proc_msg: |
| msg_id = getattr(proc_msg, 'message_id', None) |
| if msg_id: await client.delete_message(chat_id, msg_id) |
| except: pass |
| |
| proc_msg = await send_with_keyboard(client, chat_id, f"🎙 سناریو نوشته شد! در حال ریکورد و میکس دیالوگهای گویندگان (شامل {len(script_data)} نوبت صحبت)...\nاین مرحله زمانبر است...", False) |
|
|
| combined_audio = AudioSegment.empty() |
| url_generate = "https://opera8-podgen.hf.space/api/generate" |
| |
| for index, turn in enumerate(script_data): |
| payload_gen = {"text": turn["dialogue"], "speaker": turn["speaker_id"], "temperature": 0.9} |
| chunk_audio_bytes = None |
| for attempt in range(3): |
| try: |
| async with session.post(url_generate, json=payload_gen, timeout=120) as resp: |
| if resp.status == 200: |
| chunk_audio_bytes = await resp.read() |
| break |
| except Exception: await asyncio.sleep(2) |
| |
| if not chunk_audio_bytes: return await send_with_keyboard(client, chat_id, f"❌ خطا در تولید صدای بخش {index+1} از سرور. عملیات متوقف شد.", True) |
| |
| try: |
| audio_segment = AudioSegment.from_file(io.BytesIO(chunk_audio_bytes)) |
| combined_audio += audio_segment |
| except Exception as e: return await send_with_keyboard(client, chat_id, f"❌ خطا در پردازش صدا:\n{str(e)}", True) |
|
|
| if not creds.get("is_premium"): |
| user_credits_db[str_chat_id]["podcast"] -= 1 |
| save_db(user_credits_db) |
|
|
| file_name_mp3 = f"final_podcast_{uuid.uuid4().hex}.mp3" |
| combined_audio.export(file_name_mp3, format="mp3") |
| |
| try: |
| if proc_msg: |
| msg_id = getattr(proc_msg, 'message_id', None) |
| if msg_id: await client.delete_message(chat_id, msg_id) |
| except: pass |
|
|
| caption_file = f"🎧 فایل پادکست شما با فرمت MP3:\n\n💡 موضوع شما: {prompt}" |
| |
| upload_result_file = await helper_upload_file(client, chat_id, file_name_mp3, "File", caption_file) |
| |
| if upload_result_file is not True: |
| await send_with_keyboard(client, chat_id, f"❌ پادکست ساخته شد اما بله خطای آپلود داد.\n\n`{str(upload_result_file)[:800]}`", True) |
| |
| if os.path.exists(file_name_mp3): os.remove(file_name_mp3) |
|
|
|
|
| |
| async def process_stt(client, chat_id, audio_bytes, file_name): |
| str_chat_id = str(chat_id) |
| creds = get_user_credits(str_chat_id) |
| if creds["stt"] <= 0: |
| return await send_with_keyboard(client, chat_id, "❌ اعتبار تبدیل صدا به متن شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False) |
|
|
| if not GEMINI_KEYS: return await send_with_keyboard(client, chat_id, "❌ کلیدهای جیمینای تنظیم نشدهاند.", False) |
| |
| proc_msg = await send_with_keyboard(client, chat_id, "📝 در حال گوش دادن و پیادهسازی متن...", False) |
| base64_data = base64.b64encode(audio_bytes).decode('utf-8') |
| mime_type, _ = mimetypes.guess_type(file_name) |
| if not mime_type: mime_type = "audio/ogg" |
| |
| keys_to_try = get_next_gemini_keys(100) |
| transcribed_text = None |
| prompt = "لطفاً این فایل صوتی/تصویری را با دقت کامل گوش بده و صحبتهای داخل آن را کلمه به کلمه به متن تبدیل کن. هیچ توضیح اضافهای نده." |
| |
| async with aiohttp.ClientSession() as session: |
| for key in keys_to_try: |
| url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}" |
| payload = {"contents": [{"parts":[{"text": prompt}, {"inlineData": {"mimeType": mime_type, "data": base64_data}}]}], "generationConfig": {"temperature": 0.2}} |
| try: |
| async with session.post(url, json=payload, timeout=60) as response: |
| if response.status == 200: |
| data = await response.json() |
| transcribed_text = data["candidates"][0]["content"]["parts"][0]["text"] |
| break |
| except Exception: continue |
|
|
| try: |
| if proc_msg: |
| msg_id = getattr(proc_msg, 'message_id', None) |
| if msg_id: await client.delete_message(chat_id, msg_id) |
| except Exception: pass |
|
|
| if transcribed_text: |
| if not creds.get("is_premium"): |
| user_credits_db[str_chat_id]["stt"] -= 1 |
| save_db(user_credits_db) |
| await send_with_keyboard(client, chat_id, f"📝 **متن استخراج شده:**\n\n{transcribed_text}", True) |
| else: |
| await send_with_keyboard(client, chat_id, "❌ سرور شلوغ است فعلا بعدا امتحان کنید.", True) |
|
|
|
|
| |
| async def process_file_analysis(client, chat_id, file_bytes, file_name, prompt): |
| str_chat_id = str(chat_id) |
| creds = get_user_credits(str_chat_id) |
| if creds["file"] <= 0: |
| return await send_with_keyboard(client, chat_id, "❌ اعتبار تحلیل فایل شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False) |
|
|
| if not GEMINI_KEYS: return await send_with_keyboard(client, chat_id, "❌ کلید جیمینای تنظیم نیست.", False) |
| |
| proc_msg = await send_with_keyboard(client, chat_id, "👁️ در حال تحلیل فایل...", False) |
| base64_data = base64.b64encode(file_bytes).decode('utf-8') |
| mime_type, _ = mimetypes.guess_type(file_name) |
| if not mime_type: mime_type = "image/jpeg" |
| |
| keys_to_try = get_next_gemini_keys(100) |
| final_answer = None |
| |
| async with aiohttp.ClientSession() as session: |
| for key in keys_to_try: |
| url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}" |
| payload = {"contents":[{"parts":[{"text": prompt}, {"inlineData": {"mimeType": mime_type, "data": base64_data}}]}], "generationConfig": {"temperature": 0.6}} |
| try: |
| async with session.post(url, json=payload, timeout=45) as response: |
| if response.status == 200: |
| data = await response.json() |
| final_answer = data["candidates"][0]["content"]["parts"][0]["text"] |
| break |
| except Exception: continue |
|
|
| try: |
| if proc_msg: |
| msg_id = getattr(proc_msg, 'message_id', None) |
| if msg_id: await client.delete_message(chat_id, msg_id) |
| except Exception: pass |
|
|
| if final_answer: |
| if not creds.get("is_premium"): |
| user_credits_db[str_chat_id]["file"] -= 1 |
| save_db(user_credits_db) |
| await send_with_keyboard(client, chat_id, f"💡 **نتیجه تحلیل:**\n\n{final_answer}", True) |
| else: |
| await send_with_keyboard(client, chat_id, "❌ سرور شلوغ است فعلا بعدا امتحان کنید.", True) |
|
|
|
|
| |
| async def process_create_file(client, chat_id, topic): |
| str_chat_id = str(chat_id) |
| creds = get_user_credits(str_chat_id) |
| |
| if creds["chat"] <= 0: |
| return await send_with_keyboard(client, chat_id, "❌ اعتبار چت شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False) |
|
|
| if not GEMINI_KEYS: return await send_with_keyboard(client, chat_id, "❌ کلیدهای جیمینای تنظیم نشدهاند.", False) |
| |
| proc_msg = await send_with_keyboard(client, chat_id, "✍️ در حال تحقیق و نگارش مقاله جامع و حرفهای...\n(این عملیات با توجه به طولانی بودن متن ممکن است کمی طول بکشد)", False) |
|
|
| ai_prompt = f"یک مقاله بسیار جامع، کاملا حرفهای، بسیار طولانی و با جزئیات کامل درباره موضوع زیر به زبان فارسی بنویس. فقط متن مقاله را بده و هیچ توضیح اضافهای نده:\n\nموضوع: {topic}" |
| article_text = None |
|
|
| keys_to_try = get_next_gemini_keys(100) |
| async with aiohttp.ClientSession() as session: |
| for key in keys_to_try: |
| url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}" |
| payload = {"contents": [{"parts":[{"text": ai_prompt}]}], "generationConfig": {"temperature": 0.7, "maxOutputTokens": 8192}} |
| try: |
| async with session.post(url, json=payload, timeout=60) as response: |
| if response.status == 200: |
| data = await response.json() |
| article_text = data["candidates"][0]["content"]["parts"][0]["text"] |
| break |
| except Exception: continue |
|
|
| if not article_text and HF_TOKENS: |
| keys_to_try_hf = HF_TOKENS.copy() |
| random.shuffle(keys_to_try_hf) |
| async with aiohttp.ClientSession() as session: |
| for hf_key in keys_to_try_hf: |
| url = "https://router.huggingface.co/v1/chat/completions" |
| headers = {"Authorization": f"Bearer {hf_key}", "Content-Type": "application/json"} |
| payload = {"model": "google/gemma-4-31B-it:novita", "messages":[{"role": "user", "content":[{"type": "text", "text": ai_prompt}]}], "max_tokens": 4096} |
| try: |
| async with session.post(url, headers=headers, json=payload, timeout=60) as response: |
| if response.status == 200: |
| data = await response.json() |
| article_text = data["choices"][0]["message"]["content"] |
| break |
| except Exception: continue |
|
|
| if not article_text: |
| return await send_with_keyboard(client, chat_id, "❌ سرور تولید متن شلوغ است، لطفاً بعداً تلاش کنید.", True) |
|
|
| try: |
| if proc_msg: |
| msg_id = getattr(proc_msg, 'message_id', None) |
| if msg_id: await client.delete_message(chat_id, msg_id) |
| except Exception: pass |
|
|
| proc_msg = await send_with_keyboard(client, chat_id, "📄 مقاله با موفقیت نوشته شد! در حال ارتباط با سرور و تبدیل به فایلهای PDF و Word...\n(لطفا صبور باشید)", False) |
|
|
| pdf_bytes = None |
| docx_bytes = None |
| converter_url = "https://opera8-texttopdf.hf.space/" |
|
|
| async with aiohttp.ClientSession() as session: |
| try: |
| form_data_pdf = aiohttp.FormData() |
| form_data_pdf.add_field('content', article_text) |
| form_data_pdf.add_field('format', 'pdf') |
| async with session.post(converter_url, data=form_data_pdf, timeout=60) as resp: |
| if resp.status == 200: |
| pdf_bytes = await resp.read() |
| except Exception as e: print("PDF creation error:", e) |
|
|
| try: |
| form_data_docx = aiohttp.FormData() |
| form_data_docx.add_field('content', article_text) |
| form_data_docx.add_field('format', 'docx') |
| async with session.post(converter_url, data=form_data_docx, timeout=60) as resp: |
| if resp.status == 200: |
| docx_bytes = await resp.read() |
| except Exception as e: print("DOCX creation error:", e) |
|
|
| try: |
| if proc_msg: |
| msg_id = getattr(proc_msg, 'message_id', None) |
| if msg_id: await client.delete_message(chat_id, msg_id) |
| except Exception: pass |
|
|
| if not pdf_bytes and not docx_bytes: |
| return await send_with_keyboard(client, chat_id, "❌ متاسفانه در تبدیل متن به فایل خطایی رخ داد.", True) |
|
|
| if not creds.get("is_premium"): |
| user_credits_db[str_chat_id]["chat"] -= 1 |
| save_db(user_credits_db) |
|
|
| uid = uuid.uuid4().hex |
| pdf_filename = f"Article_{uid}.pdf" |
| docx_filename = f"Article_{uid}.docx" |
|
|
| uploaded_any = False |
| |
| if pdf_bytes: |
| with open(pdf_filename, "wb") as f: |
| f.write(pdf_bytes) |
| res = await helper_upload_file(client, chat_id, pdf_filename, "File", f"📄 فایل PDF مقاله شما:\n\n💡 موضوع: {topic}") |
| if res is True: uploaded_any = True |
| if os.path.exists(pdf_filename): os.remove(pdf_filename) |
| await asyncio.sleep(1.5) |
|
|
| if docx_bytes: |
| with open(docx_filename, "wb") as f: |
| f.write(docx_bytes) |
| res = await helper_upload_file(client, chat_id, docx_filename, "File", f"📝 فایل Word (DOCX) مقاله شما:\n\n💡 موضوع: {topic}") |
| if res is True: uploaded_any = True |
| if os.path.exists(docx_filename): os.remove(docx_filename) |
|
|
| if uploaded_any: |
| await send_with_keyboard(client, chat_id, "✅ مقاله شما با موفقیت به صورت فایل تحویل داده شد!", True) |
| else: |
| await send_with_keyboard(client, chat_id, "❌ فایلها ساخته شدند اما بله در ارسال آنها دچار مشکل شد.", True) |
|
|
| |
| async def task_chat_file(client, chat_id, text, message, file_name): |
| try: |
| file_bytes = await helper_download_file(client, message) |
| await process_gemini(client, chat_id, text, file_bytes=file_bytes, file_name=file_name) |
| except Exception as e: await send_with_keyboard(client, chat_id, f"❌ خطا در دریافت فایل!\n{str(e)}", False) |
|
|
| async def task_image_edit(client, chat_id, message): |
| await send_with_keyboard(client, chat_id, "📥 در حال دانلود عکس...", False) |
| try: |
| file_bytes = await helper_download_file(client, message) |
| user_states[chat_id]["file_bytes"] = file_bytes |
| user_states[chat_id]["mode"] = "image_edit_waiting_for_prompt" |
| await send_with_keyboard(client, chat_id, "✅ عکس با موفقیت دریافت شد.\n\nحالا دستور خود را به صورت متنی تایپ کنید.\nمثال: یک کلاه قرمز روی سر این گربه بگذار.", False) |
| except Exception as e: await send_with_keyboard(client, chat_id, f"❌ خطا در دریافت عکس!\n{str(e)}", False) |
|
|
| async def task_stt(client, chat_id, message, file_name): |
| await send_with_keyboard(client, chat_id, "📥 در حال دانلود فایل...", False) |
| try: |
| audio_bytes = await helper_download_file(client, message) |
| await process_stt(client, chat_id, audio_bytes, file_name) |
| except Exception as e: await send_with_keyboard(client, chat_id, f"❌ خطا در دانلود فایل!\n{str(e)}", False) |
|
|
| async def task_file_analysis(client, chat_id, message, file_name): |
| await send_with_keyboard(client, chat_id, "📥 در حال دریافت فایل...", False) |
| try: |
| file_bytes = await helper_download_file(client, message) |
| user_states[chat_id]["file_bytes"] = file_bytes |
| user_states[chat_id]["file_name"] = file_name |
| user_states[chat_id]["mode"] = "file_waiting_for_prompt" |
| await send_with_keyboard(client, chat_id, "✅ فایل با موفقیت دریافت شد.\n\nحالا لطفاً متنی بگویید **چگونه تحلیل شود؟**", False) |
| except Exception as e: await send_with_keyboard(client, chat_id, f"❌ خطا در دریافت فایل!\n{str(e)}", False) |
|
|
|
|
| |
| bot = AsyncTeleBot(bot_token) if bot_token else None |
|
|
| if bot: |
| @bot.message_handler(func=lambda message: True, content_types=['text', 'photo', 'document', 'voice', 'audio', 'video']) |
| async def main_handler(message): |
| try: |
| chat_id = message.chat.id |
| msg_id = message.message_id |
| |
| |
| unique_msg_key = f"{chat_id}_{msg_id}" |
| if unique_msg_key in processed_message_ids: |
| return |
| processed_message_ids.add(unique_msg_key) |
| if len(processed_message_ids) > 10000: |
| processed_message_ids.clear() |
| |
| global BOT_GUID |
| if not BOT_GUID: |
| try: |
| me_info = await bot.get_me() |
| if me_info: BOT_GUID = me_info.id |
| except Exception: pass |
|
|
| author_id = message.from_user.id |
| if BOT_GUID and author_id == BOT_GUID: |
| return |
|
|
| user_text = message.text or message.caption or "" |
| user_text_str = str(user_text).strip() if user_text else "" |
| user_text_lower = user_text_str.lower() |
|
|
| if chat_id not in user_states: |
| user_states[chat_id] = {"mode": None, "text": "", "history":[], "file_bytes": None, "file_name": None} |
|
|
| |
| if user_text_lower.startswith(f"{ADMIN_CODE} pro=") or user_text_lower.startswith(f"{ADMIN_CODE}pro="): |
| parts = user_text_str.split("=", 1) |
| if len(parts) >= 2: |
| target_id = parts[1].replace("`", "").replace("'", "").replace('"', "").strip() |
| if target_id: |
| if target_id not in user_credits_db: |
| user_credits_db[target_id] = {"is_premium": False, "expire_date": None, "last_reset": "", "chat": 10, "image": 5, "edit_image": 1, "podcast": 2, "tts": 5, "file": 1, "stt": 5, "has_joined": True} |
| user_credits_db[target_id]["is_premium"] = True |
| expire_time = datetime.datetime.now() + datetime.timedelta(days=30) |
| user_credits_db[target_id]["expire_date"] = expire_time.isoformat() |
| user_credits_db[target_id]["chat"] = 999999 |
| user_credits_db[target_id]["image"] = 20 |
| user_credits_db[target_id]["edit_image"] = 10 |
| user_credits_db[target_id]["podcast"] = 999999 |
| user_credits_db[target_id]["tts"] = 999999 |
| user_credits_db[target_id]["file"] = 999999 |
| user_credits_db[target_id]["stt"] = 999999 |
| save_db(user_credits_db) |
| asyncio.create_task(send_with_keyboard(bot, chat_id, f"✅ حساب کاربر `{target_id}` به مدت ۳۰ روز شارژ شد و به پرو ارتقا یافت.", False)) |
| return |
| |
| if user_text_lower.startswith(f"{ADMIN_CODE} free=") or user_text_lower.startswith(f"{ADMIN_CODE}free="): |
| parts = user_text_str.split("=", 1) |
| if len(parts) >= 2: |
| target_id = parts[1].replace("`", "").replace("'", "").replace('"', "").strip() |
| if target_id: |
| if target_id in user_credits_db: |
| user_credits_db[target_id]["is_premium"] = False |
| user_credits_db[target_id]["expire_date"] = None |
| user_credits_db[target_id]["last_reset"] = "" |
| save_db(user_credits_db) |
| asyncio.create_task(send_with_keyboard(bot, chat_id, f"✅ اشتراک کاربر `{target_id}` لغو شد و به رایگان تبدیل گشت.", False)) |
| return |
|
|
| if user_text_lower.startswith(f"{ADMIN_CODE} =") or user_text_lower.startswith(f"{ADMIN_CODE}="): |
| parts = user_text_str.split("=", 1) |
| if len(parts) >= 2: |
| target_id = parts[1].replace("`", "").replace("'", "").replace('"', "").strip() |
| if target_id: |
| if target_id in user_credits_db: |
| t_creds = user_credits_db[target_id] |
| is_prem = t_creds.get("is_premium", False) |
| if is_prem: |
| expire_txt = "نامشخص" |
| days_left = 0 |
| if t_creds.get("expire_date"): |
| exp_d = datetime.datetime.fromisoformat(t_creds["expire_date"]) |
| now = datetime.datetime.now() |
| diff = exp_d - now |
| days_left = diff.days if diff.days >= 0 else 0 |
| jy, jm, jd = gregorian_to_jalali(exp_d.year, exp_d.month, exp_d.day) |
| expire_txt = f"{jy:04d}/{jm:02d}/{jd:02d}" |
| status_text = f"🌟 نسخه پرو (ویژه)\n📅 انقضا: {expire_txt}\n⏳ باقیمانده: {days_left} روز" |
| else: |
| status_text = "🥉 نسخه رایگان (آزمایشی)\n⏳ سهمیه روزانه" |
|
|
| info_msg = f"🔍 **اطلاعات کاربر `{target_id}`:**\n\n🔹 **وضعیت:** {status_text}\n\n📊 **سهمیه:**\n- چت: {t_creds.get('chat',0)}\n- تولید عکس: {t_creds.get('image',0)}\n- ویرایش عکس: {t_creds.get('edit_image',0)}\n- پادکست: {t_creds.get('podcast',0)}\n- متن به صدا: {t_creds.get('tts',0)}\n- تحلیل فایل: {t_creds.get('file',0)}\n- صدا به متن: {t_creds.get('stt',0)}" |
| asyncio.create_task(send_with_keyboard(bot, chat_id, info_msg, False)) |
| else: |
| asyncio.create_task(send_with_keyboard(bot, chat_id, f"❌ کاربری با شناسه `{target_id}` در دیتابیس یافت نشد.", False)) |
| return |
|
|
| is_file = False |
| file_name = f"unknown_file_{uuid.uuid4().hex[:6]}.jpg" |
| |
| if message.document: |
| is_file = True |
| file_name = message.document.file_name or file_name |
| elif message.photo: |
| is_file = True |
| file_name = f"image_{uuid.uuid4().hex[:6]}.jpg" |
| elif message.voice: |
| is_file = True |
| file_name = f"voice_{uuid.uuid4().hex[:6]}.ogg" |
| elif message.audio: |
| is_file = True |
| file_name = message.audio.file_name or f"audio_{uuid.uuid4().hex[:6]}.mp3" |
| elif message.video: |
| is_file = True |
| file_name = getattr(message.video, 'file_name', f"video_{uuid.uuid4().hex[:6]}.mp4") |
|
|
| str_chat_id = str(chat_id) |
| creds = get_user_credits(str_chat_id) |
|
|
| if user_text_str == "✅ عضو شدم": |
| if not creds.get("has_joined", False): |
| user_credits_db[str_chat_id]["has_joined"] = True |
| save_db(user_credits_db) |
| asyncio.create_task(send_with_keyboard(bot, chat_id, "🎉 **عضویت شما با موفقیت تایید شد! خیلی خوش آمدید.**\n\nحالا میتوانید از تمامی امکانات ربات استفاده کنید.\nلطفاً یکی از گزینههای منو را انتخاب کنید:", True)) |
| return |
| else: |
| asyncio.create_task(send_with_keyboard(bot, chat_id, "✅ شما قبلاً عضو شدهاید! لطفا از منوی اصلی استفاده کنید.", True)) |
| return |
|
|
| if not creds.get("has_joined", False): |
| join_msg = "👋 **سلام کاربر گرامی!**\n\nجهت استفاده از خدمات ربات هوش مصنوعی آلفا و مطلع شدن از آخرین آپدیتها، لطفا ابتدا در کانال رسمی ما عضو شوید:\n\n📢 **آیدی کانال:** @aialpha\n\n👇 پس از عضویت در کانال، بر روی دکمه **«✅ عضو شدم»** کلیک کنید تا ربات برای شما فعال شود." |
| asyncio.create_task(bot.send_message(chat_id, join_msg, reply_markup=get_join_keyboard())) |
| return |
|
|
| if user_text_str in["/start", "سلام", "لغو", "/cancel", "❌ لغو", "برگشت♻️"]: |
| user_states[chat_id]["mode"] = None |
| user_states[chat_id]["file_bytes"] = None |
| asyncio.create_task(send_with_keyboard(bot, chat_id, "سلام! به ربات هوش مصنوعی آلفا خوش آمدید 🤖\n\nلطفاً برای شروع، از کیبورد پایین یکی از بخشها را انتخاب کنید:", True)) |
| return |
|
|
| if user_text_str in["/account", "حساب کاربری 👤"]: |
| creds = get_user_credits(chat_id) |
| is_prem = creds.get("is_premium", False) |
| if is_prem: |
| expire_txt = "نامشخص" |
| days_left = 0 |
| if creds.get("expire_date"): |
| exp_d = datetime.datetime.fromisoformat(creds["expire_date"]) |
| now = datetime.datetime.now() |
| diff = exp_d - now |
| days_left = diff.days if diff.days >= 0 else 0 |
| jy, jm, jd = gregorian_to_jalali(exp_d.year, exp_d.month, exp_d.day) |
| expire_txt = f"{jy:04d}/{jm:02d}/{jd:02d} (ساعت {exp_d.hour:02d}:{exp_d.minute:02d})" |
| status_text = "🌟 نسخه پرو (ویژه)" |
| expire_info = f"\n📅 **تاریخ انقضا:** {expire_txt}\n⏳ **زمان باقیمانده:** {days_left} روز" |
| daily_note = "*نکته: سهمیه پردازشی شما مختص همین دوره یکماهه میباشد.*" |
| else: |
| status_text = "🥉 نسخه رایگان (آزمایشی)" |
| expire_info = "" |
| daily_note = "*نکته: سهمیه شما هر روز ساعت ۰۰:۰۰ بامداد به صورت خودکار مجدداً شارژ میگردد.*" |
|
|
| chat_rem = "نامحدود ∞" if is_prem else creds['chat'] |
| podcast_rem = "نامحدود ∞" if is_prem else creds['podcast'] |
| tts_rem = "نامحدود ∞" if is_prem else creds['tts'] |
| file_rem = "نامحدود ∞" if is_prem else creds['file'] |
| stt_rem = "نامحدود ∞" if is_prem else creds['stt'] |
| image_rem = creds['image'] |
| edit_image_rem = creds['edit_image'] |
|
|
| account_profile = f"👤 **اطلاعات حساب کاربری شما**\n\n🔹 **شناسه یکتا:** `{chat_id}`\n🔹 **وضعیت اشتراک:** {status_text}{expire_info}\n\n📊 **سهمیه باقیمانده شما:**\n- 💬 چت هوشمند: {chat_rem}\n- 🎨 تولید تصویر: {image_rem} عدد\n- 🪄 ویرایش تصویر: {edit_image_rem} عدد\n- 🎙 ساخت پادکست: {podcast_rem}\n- 🗣 تبدیل متن به صدا: {tts_rem}\n- 📁 تحلیل فایل و سند: {file_rem}\n- 📝 تبدیل صدا به متن: {stt_rem}\n\n{daily_note}" |
| asyncio.create_task(send_with_keyboard(bot, chat_id, account_profile, True)) |
| return |
|
|
| if user_text_str in["/buy", "خرید اشتراک 💎"]: |
| buy_text = f"💎 **خرید اشتراک ویژه آلفا پرو (یک ماهه)**\n\nبا تهیه اشتراک ویژه، محدودیتها را کنار بزنید و از نهایت قدرت هوش مصنوعی لذت ببرید! 🚀\n\n🎁 **بسته طلایی یکماهه شامل:**\n🤖 چت با هوش مصنوعی بصورت نامحدود\n🗣 تبدیل متن به صدا بصورت نامحدود با ۳۰ گوینده\n🎙 ساخت پادکست بصورت نامحدود \n\n🪄 ۱۰ ویرایش تصویر\n🎨 ۲۰ تولید تصویر \n📁 تحلیل نامحدود فایل و سند\n📝 تبدیل فایل صوتی به متن نامحدود\n\n💳 **هزینه اشتراک یک ماهه:** 250 هزار تومان\n\n💳 **شماره کارت جهت واریز:**\n`6219861411958035`\n👤 **به نام:** کوهی\n\n✅ **نحوه فعالسازی:**\nپس از واریز مبلغ، لطفاً رسید پرداختی را به همراه **شناسه یکتای خود** (که در پایین آمده) به آیدی پشتیبانی زیر ارسال کنید تا اشتراک شما فعال گردد:\n\n🔑 **شناسه یکتای شما:** `{chat_id}`\n\n👨💻 **ارتباط با پشتیبانی:**\n🆔 @H_a_m_e_d100" |
| asyncio.create_task(send_with_keyboard(bot, chat_id, buy_text, True)) |
| return |
|
|
| if user_text_str in["/transfer", "انتقال اکانت از برنامه به ربات"]: |
| transfer_text = f"🔄 **انتقال اکانت از برنامه به ربات**\n\nکاربر گرامی، در صورتی که داخل برنامه «هوش مصنوعی آلفا» پیشتر اشتراک تهیه کردهاید، نیازی به خرید مجدد اشتراک داخل ربات نیست! 🎉\n\nکافیست **شناسه یکتای** ربات خود را کپی کرده و برای پشتیبانی ما ارسال کنید تا اکانت اشتراکی شما به سرعت انتقال داده شود.\n\n🔑 **شناسه یکتای ربات شما:** `{chat_id}`\n\n👨💻 **پشتیبانی:**\n🆔 @H_a_m_e_d100" |
| asyncio.create_task(send_with_keyboard(bot, chat_id, transfer_text, True)) |
| return |
|
|
| if user_text_str in["/chat", "💬 چت", "چت با هوش مصنوعی 🤖"]: |
| user_states[chat_id]["mode"] = "chat" |
| user_states[chat_id]["history"] =[] |
| asyncio.create_task(send_with_keyboard(bot, chat_id, "💬 شما وارد بخش **چت با هوش مصنوعی** شدید.\n\nهر سوالی دارید بفرستید تا جواب بدم:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)) |
| return |
|
|
| if user_text_str in ["/image", "🎨 عکس", "ساخت تصاویر🎨"]: |
| user_states[chat_id]["mode"] = "image_waiting_for_text" |
| asyncio.create_task(send_with_keyboard(bot, chat_id, "🎨 شما وارد بخش **ساخت عکس پیشرفته** شدید.\n\nمتن خود را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)) |
| return |
|
|
| if user_text_str in["/edit_image", "ویرایش تصاویر 🪄"]: |
| user_states[chat_id]["mode"] = "image_edit_waiting_for_image" |
| user_states[chat_id]["file_bytes"] = None |
| asyncio.create_task(send_with_keyboard(bot, chat_id, "🪄 به بخش **ویرایش عکس (Flux.2)** خوش آمدید.\n\nلطفاً ابتدا عکسی که میخواهید ویرایش کنید را بفرستید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)) |
| return |
|
|
| if user_text_str in["/tts", "🎙️ صدا", "تبدیل متن به صدا🗣️"]: |
| user_states[chat_id]["mode"] = "tts_waiting_for_text" |
| asyncio.create_task(send_with_keyboard(bot, chat_id, "🎙️ شما وارد بخش **تبدیل متن به صدا** شدید.\n\nلطفاً متنی که میخواهید به صدا تبدیل شود را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)) |
| return |
| |
| if user_text_str in["/podcast", "📻 پادکست", "ساخت پادکست 🎙️"]: |
| user_states[chat_id]["mode"] = "podcast_waiting_for_topic" |
| asyncio.create_task(send_with_keyboard(bot, chat_id, "📻 شما وارد بخش **ساخت پادکست** شدید.\n\nلطفاً موضوع پادکست خود را بفرستید.\nمثال: درباره تاریخچه پیدایش قهوه با ۳ گوینده یک پادکست جذاب بساز .\n\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)) |
| return |
|
|
| if user_text_str in["/file", "تحلیل فایل 📁"]: |
| user_states[chat_id]["mode"] = "file_waiting_for_file" |
| user_states[chat_id]["file_bytes"] = None |
| asyncio.create_task(send_with_keyboard(bot, chat_id, "📁 شما وارد بخش **تحلیل فایل اختصاصی** شدید.\n\nلطفاً فایل خود را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)) |
| return |
|
|
| if user_text_str in["/stt", "فایل صوتی به متن 📝"]: |
| user_states[chat_id]["mode"] = "stt_waiting_for_audio" |
| asyncio.create_task(send_with_keyboard(bot, chat_id, "📝 شما وارد بخش **تبدیل صدا به متن** شدید.\n\nلطفاً فایل خود (ویس، آهنگ، ویدیو و...) را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)) |
| return |
|
|
| if user_text_str in["/create_file", "ساخت فایل 📄"]: |
| user_states[chat_id]["mode"] = "create_file_waiting_for_topic" |
| asyncio.create_task(send_with_keyboard(bot, chat_id, "📄 شما وارد بخش **ساخت فایل** شدید.\n\nلطفاً موضوع مقالهای که میخواهید را کامل بفرستید.\nمثال: نحوه مدیریت زمان\n\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)) |
| return |
|
|
| current_mode = user_states[chat_id].get("mode") |
|
|
| if current_mode is None: |
| if is_file: pass |
| elif user_text_str: asyncio.create_task(send_with_keyboard(bot, chat_id, "⚠️ لطفاً ابتدا از کیبورد پایین، بخش مورد نظرتان را انتخاب کنید:", True)) |
| return |
|
|
| elif current_mode == "chat": |
| if is_file: asyncio.create_task(task_chat_file(bot, chat_id, user_text_str, message, file_name)) |
| elif user_text_str: asyncio.create_task(process_gemini(bot, chat_id, user_text_str)) |
| return |
|
|
| elif current_mode == "image_waiting_for_text": |
| if user_text_str: asyncio.create_task(process_image(bot, chat_id, user_text_str)) |
| return |
|
|
| elif current_mode == "image_edit_waiting_for_image": |
| if not is_file: |
| asyncio.create_task(send_with_keyboard(bot, chat_id, "⚠️ لطفاً ابتدا یک عکس ارسال کنید.", False)) |
| return |
| asyncio.create_task(task_image_edit(bot, chat_id, message)) |
| return |
|
|
| elif current_mode == "image_edit_waiting_for_prompt": |
| if user_text_str: |
| saved_bytes = user_states[chat_id].get("file_bytes") |
| user_states[chat_id]["mode"] = None |
| user_states[chat_id]["file_bytes"] = None |
| asyncio.create_task(process_image_edit(bot, chat_id, saved_bytes, user_text_str)) |
| else: asyncio.create_task(send_with_keyboard(bot, chat_id, "⚠️ لطفاً درخواست خود را متنی بنویسید.", False)) |
| return |
|
|
| elif current_mode == "tts_waiting_for_text": |
| if user_text_str: |
| if len(user_text_str) > 2500: |
| asyncio.create_task(send_with_keyboard(bot, chat_id, "⚠️ لطفاً متنی کوتاهتر از 2500 کاراکتر بفرستید.", False)) |
| return |
| user_states[chat_id]["text"] = user_text_str |
| user_states[chat_id]["mode"] = "tts_waiting_for_speaker" |
| speakers_menu = "✅ متن شما ذخیره شد.\nلطفاً **شماره** گوینده مورد نظر خود را بفرستید:\n1. شهاب | 2. آوا | 3. نوید\n4. آرمان | 5. مهسا | 6. دانا\n7. سامان | 8. آرش | 9. شبنم\n10. سحر | 11. مریم | 12. بهرام\n13. نیکان| 14. فرناز | 15. سارا\n16. مانی | 17. آرتین | 18. دلنواز\n19. روژان | 20. امید | 21. بردیا\n22. ترانه | 23. نیکو | 24. هستی\n25. کامیار| 26. کیانوش| 27. پویا\n28. مهتاب | 29. سام | 30. لیدا" |
| asyncio.create_task(send_with_keyboard(bot, chat_id, speakers_menu, False)) |
| return |
|
|
| elif current_mode == "tts_waiting_for_speaker": |
| normalized_text = to_english_digits(user_text_str) |
| if normalized_text.isdigit() and normalized_text in SPEAKERS: |
| spk_name, spk_id = SPEAKERS[normalized_text] |
| txt = user_states[chat_id]["text"] |
| user_states[chat_id]["mode"] = "tts_waiting_for_text" |
| asyncio.create_task(process_tts(bot, chat_id, txt, spk_id, spk_name)) |
| else: |
| asyncio.create_task(send_with_keyboard(bot, chat_id, "❌ شماره نامعتبر است! لطفاً فقط یک عدد بین 1 تا 30 بفرستید.", False)) |
| return |
|
|
| elif current_mode == "podcast_waiting_for_topic": |
| if user_text_str: asyncio.create_task(process_podcast(bot, chat_id, user_text_str)) |
| else: asyncio.create_task(send_with_keyboard(bot, chat_id, "⚠️ لطفاً موضوع پادکست خود را به صورت متنی بفرستید.", False)) |
| return |
|
|
| elif current_mode == "stt_waiting_for_audio": |
| if not is_file: |
| asyncio.create_task(send_with_keyboard(bot, chat_id, "⚠️ لطفاً یک فایل ارسال کنید.", False)) |
| return |
| asyncio.create_task(task_stt(bot, chat_id, message, file_name)) |
| return |
|
|
| elif current_mode == "file_waiting_for_file": |
| if not is_file: |
| asyncio.create_task(send_with_keyboard(bot, chat_id, "⚠️ لطفاً ابتدا یک فایل ارسال کنید.", False)) |
| return |
| asyncio.create_task(task_file_analysis(bot, chat_id, message, file_name)) |
| return |
|
|
| elif current_mode == "file_waiting_for_prompt": |
| if user_text_str: |
| saved_bytes = user_states[chat_id].get("file_bytes") |
| saved_name = user_states[chat_id].get("file_name", "file.jpeg") |
| user_states[chat_id]["mode"] = "file_waiting_for_file" |
| asyncio.create_task(process_file_analysis(bot, chat_id, saved_bytes, saved_name, user_text_str)) |
| else: asyncio.create_task(send_with_keyboard(bot, chat_id, "⚠️ لطفاً درخواست خود را متنی بنویسید.", False)) |
| return |
|
|
| elif current_mode == "create_file_waiting_for_topic": |
| if user_text_str: asyncio.create_task(process_create_file(bot, chat_id, user_text_str)) |
| else: asyncio.create_task(send_with_keyboard(bot, chat_id, "⚠️ لطفاً موضوع مقاله خود را به صورت متنی بفرستید.", False)) |
| return |
|
|
| except Exception as e: |
| traceback.print_exc() |
|
|
| if __name__ == "__main__": |
| threading.Thread(target=run_flask, daemon=True).start() |
| if not bot_token: |
| print("خطا: توکن ربات بله وارد نشده است! لطفا متغیر BALE_TOKEN را تنظیم کنید.") |
| else: |
| print("ربات آلفا پرو با سیستم اشتراک نامحدود + سپر امنیتی متصل به پیامرسان «بله» روشن شد... 🚀") |
| |
| asyncio.run(bot.polling(non_stop=True, skip_pending=True, timeout=20, request_timeout=30)) |