Update main.py
Browse files
main.py
CHANGED
|
@@ -17,7 +17,7 @@ from flask import Flask
|
|
| 17 |
# کتابخانههای ربات تلگرام/بله
|
| 18 |
import telebot
|
| 19 |
from telebot.async_telebot import AsyncTeleBot
|
| 20 |
-
from telebot import asyncio_helper #
|
| 21 |
from telebot.types import ReplyKeyboardMarkup, KeyboardButton
|
| 22 |
|
| 23 |
# ایمپورتهای هوش مصنوعی، کار با فایل صوتی و دیتابیس هاگینگ فیس
|
|
@@ -35,28 +35,6 @@ ADMIN_CODE = "3011"
|
|
| 35 |
# متغیر سراسری برای ذخیره آیدی خود ربات (جلوگیری از جواب دادن ربات به خودش)
|
| 36 |
BOT_GUID = None
|
| 37 |
|
| 38 |
-
# =======================================================
|
| 39 |
-
# 🔥 سیستم کنترل سرعت و ضد رگبار (Burst Controller) 🔥
|
| 40 |
-
# =======================================================
|
| 41 |
-
global_burst_count = 0
|
| 42 |
-
global_burst_time = time.time()
|
| 43 |
-
burst_lock = threading.Lock()
|
| 44 |
-
|
| 45 |
-
def is_backlog_burst():
|
| 46 |
-
"""اگر بیشتر از 5 پیام در 1 ثانیه بیاید، یعنی رگبار از سمت سرور است و رد میشود"""
|
| 47 |
-
global global_burst_count, global_burst_time
|
| 48 |
-
with burst_lock:
|
| 49 |
-
now = time.time()
|
| 50 |
-
if now - global_burst_time > 1.0:
|
| 51 |
-
global_burst_time = now
|
| 52 |
-
global_burst_count = 1
|
| 53 |
-
return False
|
| 54 |
-
else:
|
| 55 |
-
global_burst_count += 1
|
| 56 |
-
if global_burst_count > 5:
|
| 57 |
-
return True
|
| 58 |
-
return False
|
| 59 |
-
|
| 60 |
# --- سیستم دیتابیس حساب کاربری متصل به دیتاست هاگینگ فیس ---
|
| 61 |
DB_FILE = "users_db.json"
|
| 62 |
DATASET_REPO = "Opera8/Karbaran-rayegan-tedad"
|
|
@@ -96,7 +74,7 @@ def load_db():
|
|
| 96 |
print("✅ دیتابیس با موفقیت از دیتاست هاگینگ فیس لود شد.")
|
| 97 |
return json.load(f)
|
| 98 |
except Exception as e:
|
| 99 |
-
print("⚠️ فایل دیتابیس در هاگینگ فیس یافت نشد
|
| 100 |
|
| 101 |
if os.path.exists(DB_FILE):
|
| 102 |
try:
|
|
@@ -191,7 +169,7 @@ app = Flask(__name__)
|
|
| 191 |
|
| 192 |
@app.route('/')
|
| 193 |
def home():
|
| 194 |
-
return "ربات یکپارچه آلفا (متصل به بله + دیتاست +
|
| 195 |
|
| 196 |
def run_flask():
|
| 197 |
app.run(host="0.0.0.0", port=7860)
|
|
@@ -215,19 +193,6 @@ def get_join_keyboard():
|
|
| 215 |
markup.row(KeyboardButton("✅ عضو شدم"))
|
| 216 |
return markup
|
| 217 |
|
| 218 |
-
# --- ⛔️ سیستم بررسی عضویت اجباری کانال (Force Join) ⛔️ ---
|
| 219 |
-
CHANNEL_USERNAME = "aialpha"
|
| 220 |
-
|
| 221 |
-
async def check_channel_membership(client, user_id):
|
| 222 |
-
global BOT_GUID
|
| 223 |
-
if str(user_id) == str(BOT_GUID): return True
|
| 224 |
-
try:
|
| 225 |
-
member = await client.get_chat_member(f"@{CHANNEL_USERNAME}", user_id)
|
| 226 |
-
if member.status in ['member', 'administrator', 'creator']:
|
| 227 |
-
return True
|
| 228 |
-
return False
|
| 229 |
-
except Exception:
|
| 230 |
-
return False
|
| 231 |
|
| 232 |
# --- تابع ارسال منحصراً برای کیبورد پایین صفحه ---
|
| 233 |
async def send_with_keyboard(client, chat_id, text, use_keyboard=True):
|
|
@@ -274,8 +239,6 @@ if GEMINI_KEYS_STR2:
|
|
| 274 |
_raw_keys.extend(GEMINI_KEYS_STR2.split(","))
|
| 275 |
|
| 276 |
GEMINI_KEYS = list(set([k.strip() for k in _raw_keys if k.strip()]))
|
| 277 |
-
print(f"✅ تعداد {len(GEMINI_KEYS)} کلید جیمینای با موفقیت شناسایی شد.")
|
| 278 |
-
|
| 279 |
current_gemini_key_index = 0
|
| 280 |
gemini_key_lock = threading.Lock()
|
| 281 |
|
|
@@ -310,7 +273,7 @@ async def helper_upload_file(client, chat_id, file_name, file_type="Image", capt
|
|
| 310 |
markup = get_main_keyboard()
|
| 311 |
if file_type in["photo", "Image", "image"]:
|
| 312 |
await client.send_photo(chat_id, photo=f, caption=caption, reply_markup=markup)
|
| 313 |
-
elif file_type in
|
| 314 |
if abs_path.lower().endswith('.ogg'):
|
| 315 |
await client.send_voice(chat_id, voice=f, caption=caption, reply_markup=markup)
|
| 316 |
else:
|
|
@@ -342,13 +305,11 @@ SPEAKERS = {
|
|
| 342 |
}
|
| 343 |
|
| 344 |
user_states = {}
|
| 345 |
-
processed_message_ids = set()
|
| 346 |
-
user_last_request_time = {}
|
| 347 |
|
| 348 |
|
| 349 |
# --- ۱. پردازش چت متنی و چندرسانهای ---
|
| 350 |
async def process_gemini(client, chat_id, prompt, file_bytes=None, file_name=None):
|
| 351 |
-
str_chat_id = str(chat_id)
|
| 352 |
creds = get_user_credits(str_chat_id)
|
| 353 |
if creds["chat"] <= 0:
|
| 354 |
return await send_with_keyboard(client, chat_id, "❌ اعتبار پیامهای چت شما تمام شده است. لطفاً از منوی اصلی وار�� بخش «خرید اشتراک 💎» شوید.", False)
|
|
@@ -482,7 +443,7 @@ async def process_gemini(client, chat_id, prompt, file_bytes=None, file_name=Non
|
|
| 482 |
|
| 483 |
# --- ۲. پردازش ساخت عکس ---
|
| 484 |
async def process_image(client, chat_id, prompt):
|
| 485 |
-
str_chat_id = str(chat_id)
|
| 486 |
creds = get_user_credits(str_chat_id)
|
| 487 |
if creds["image"] <= 0:
|
| 488 |
return await send_with_keyboard(client, chat_id, "❌ اعتبار ساخت عکس شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False)
|
|
@@ -608,7 +569,7 @@ async def translate_text_aloha(prompt_text):
|
|
| 608 |
|
| 609 |
# --- ۲.۵. پردازش ویرایش عکس ---
|
| 610 |
async def process_image_edit(client, chat_id, image_bytes, prompt):
|
| 611 |
-
str_chat_id = str(chat_id)
|
| 612 |
creds = get_user_credits(str_chat_id)
|
| 613 |
if creds["edit_image"] <= 0:
|
| 614 |
return await send_with_keyboard(client, chat_id, "❌ اعتبار ویرایش عکس شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False)
|
|
@@ -668,7 +629,7 @@ async def process_image_edit(client, chat_id, image_bytes, prompt):
|
|
| 668 |
|
| 669 |
# --- ۳. پردازش ساخت صدا ---
|
| 670 |
async def process_tts(client, chat_id, user_text, speaker_id, speaker_name):
|
| 671 |
-
str_chat_id = str(chat_id)
|
| 672 |
creds = get_user_credits(str_chat_id)
|
| 673 |
if creds["tts"] <= 0:
|
| 674 |
return await send_with_keyboard(client, chat_id, "❌ اعتبار تبدیل متن به صدای شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False)
|
|
@@ -724,7 +685,7 @@ async def process_tts(client, chat_id, user_text, speaker_id, speaker_name):
|
|
| 724 |
|
| 725 |
# --- ۳.۵. پردازش پادکست ---
|
| 726 |
async def process_podcast(client, chat_id, prompt):
|
| 727 |
-
str_chat_id = str(chat_id)
|
| 728 |
creds = get_user_credits(str_chat_id)
|
| 729 |
if creds["podcast"] <= 0:
|
| 730 |
return await send_with_keyboard(client, chat_id, "❌ اعتبار ساخت پادکست شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False)
|
|
@@ -816,7 +777,7 @@ async def process_podcast(client, chat_id, prompt):
|
|
| 816 |
|
| 817 |
# --- ۴. پردازش تبدیل فایل صوتی/تصویری به متن ---
|
| 818 |
async def process_stt(client, chat_id, audio_bytes, file_name):
|
| 819 |
-
str_chat_id = str(chat_id)
|
| 820 |
creds = get_user_credits(str_chat_id)
|
| 821 |
if creds["stt"] <= 0:
|
| 822 |
return await send_with_keyboard(client, chat_id, "❌ اعتبار تبدیل صدا به متن شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False)
|
|
@@ -861,7 +822,7 @@ async def process_stt(client, chat_id, audio_bytes, file_name):
|
|
| 861 |
|
| 862 |
# --- ۵. پردازش تحلیل فایل مستقل ---
|
| 863 |
async def process_file_analysis(client, chat_id, file_bytes, file_name, prompt):
|
| 864 |
-
str_chat_id = str(chat_id)
|
| 865 |
creds = get_user_credits(str_chat_id)
|
| 866 |
if creds["file"] <= 0:
|
| 867 |
return await send_with_keyboard(client, chat_id, "❌ اعتبار تحلیل فایل شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False)
|
|
@@ -905,7 +866,7 @@ async def process_file_analysis(client, chat_id, file_bytes, file_name, prompt):
|
|
| 905 |
|
| 906 |
# --- ۵.۵. پردازش ساخت مقاله و تبدیل به فایل ---
|
| 907 |
async def process_create_file(client, chat_id, topic):
|
| 908 |
-
str_chat_id = str(chat_id)
|
| 909 |
creds = get_user_credits(str_chat_id)
|
| 910 |
|
| 911 |
if creds["chat"] <= 0:
|
|
@@ -1031,17 +992,12 @@ bot = AsyncTeleBot(bot_token) if bot_token else None
|
|
| 1031 |
if bot:
|
| 1032 |
@bot.message_handler(func=lambda message: True, content_types=['text', 'photo', 'document', 'voice', 'audio', 'video'])
|
| 1033 |
async def main_handler(message):
|
| 1034 |
-
global BOT_GUID
|
| 1035 |
-
|
| 1036 |
-
if is_backlog_burst():
|
| 1037 |
-
return
|
| 1038 |
-
|
| 1039 |
try:
|
|
|
|
| 1040 |
if not BOT_GUID:
|
| 1041 |
try:
|
| 1042 |
me_info = await bot.get_me()
|
| 1043 |
-
if me_info:
|
| 1044 |
-
BOT_GUID = me_info.id
|
| 1045 |
except Exception:
|
| 1046 |
pass
|
| 1047 |
|
|
@@ -1050,19 +1006,6 @@ if bot:
|
|
| 1050 |
return
|
| 1051 |
|
| 1052 |
chat_id = message.chat.id
|
| 1053 |
-
msg_id = message.message_id
|
| 1054 |
-
|
| 1055 |
-
unique_msg_key = f"{chat_id}_{msg_id}" if msg_id else None
|
| 1056 |
-
if unique_msg_key:
|
| 1057 |
-
if unique_msg_key in processed_message_ids: return
|
| 1058 |
-
processed_message_ids.add(unique_msg_key)
|
| 1059 |
-
if len(processed_message_ids) > 5000: processed_message_ids.clear()
|
| 1060 |
-
|
| 1061 |
-
current_time = time.time()
|
| 1062 |
-
last_req_time = user_last_request_time.get(chat_id, 0)
|
| 1063 |
-
if current_time - last_req_time < 1.0:
|
| 1064 |
-
return
|
| 1065 |
-
user_last_request_time[chat_id] = current_time
|
| 1066 |
|
| 1067 |
user_text = message.text or message.caption or ""
|
| 1068 |
user_text_str = str(user_text).strip() if user_text else ""
|
|
@@ -1078,24 +1021,10 @@ if bot:
|
|
| 1078 |
target_id = parts[1].replace("`", "").replace("'", "").replace('"', "").strip()
|
| 1079 |
if target_id:
|
| 1080 |
if target_id not in user_credits_db:
|
| 1081 |
-
user_credits_db[target_id] = {
|
| 1082 |
-
"is_premium": False,
|
| 1083 |
-
"expire_date": None,
|
| 1084 |
-
"last_reset": "",
|
| 1085 |
-
"chat": 10,
|
| 1086 |
-
"image": 5,
|
| 1087 |
-
"edit_image": 1,
|
| 1088 |
-
"podcast": 2,
|
| 1089 |
-
"tts": 5,
|
| 1090 |
-
"file": 1,
|
| 1091 |
-
"stt": 5,
|
| 1092 |
-
"has_joined": True
|
| 1093 |
-
}
|
| 1094 |
-
|
| 1095 |
user_credits_db[target_id]["is_premium"] = True
|
| 1096 |
expire_time = datetime.datetime.now() + datetime.timedelta(days=30)
|
| 1097 |
user_credits_db[target_id]["expire_date"] = expire_time.isoformat()
|
| 1098 |
-
|
| 1099 |
user_credits_db[target_id]["chat"] = 999999
|
| 1100 |
user_credits_db[target_id]["image"] = 20
|
| 1101 |
user_credits_db[target_id]["edit_image"] = 10
|
|
@@ -1103,7 +1032,6 @@ if bot:
|
|
| 1103 |
user_credits_db[target_id]["tts"] = 999999
|
| 1104 |
user_credits_db[target_id]["file"] = 999999
|
| 1105 |
user_credits_db[target_id]["stt"] = 999999
|
| 1106 |
-
|
| 1107 |
save_db(user_credits_db)
|
| 1108 |
await send_with_keyboard(bot, chat_id, f"✅ حساب کاربر `{target_id}` به مدت ۳۰ روز شارژ شد و به پرو ارتقا یافت.", False)
|
| 1109 |
try:
|
|
@@ -1135,7 +1063,6 @@ if bot:
|
|
| 1135 |
if target_id in user_credits_db:
|
| 1136 |
t_creds = user_credits_db[target_id]
|
| 1137 |
is_prem = t_creds.get("is_premium", False)
|
| 1138 |
-
|
| 1139 |
if is_prem:
|
| 1140 |
expire_txt = "نامشخص"
|
| 1141 |
days_left = 0
|
|
@@ -1144,33 +1071,13 @@ if bot:
|
|
| 1144 |
now = datetime.datetime.now()
|
| 1145 |
diff = exp_d - now
|
| 1146 |
days_left = diff.days if diff.days >= 0 else 0
|
| 1147 |
-
|
| 1148 |
jy, jm, jd = gregorian_to_jalali(exp_d.year, exp_d.month, exp_d.day)
|
| 1149 |
expire_txt = f"{jy:04d}/{jm:02d}/{jd:02d}"
|
| 1150 |
status_text = f"🌟 نسخه پرو (ویژه)\n📅 انقضا: {expire_txt}\n⏳ باقیمانده: {days_left} روز"
|
| 1151 |
else:
|
| 1152 |
status_text = "🥉 نسخه رایگان (آزمایشی)\n⏳ سهمیه روزانه"
|
| 1153 |
|
| 1154 |
-
|
| 1155 |
-
podcast_rem = "نامحدود ∞" if is_prem else t_creds.get('podcast', 0)
|
| 1156 |
-
tts_rem = "نامحدود ∞" if is_prem else t_creds.get('tts', 0)
|
| 1157 |
-
file_rem = "نامحدود ∞" if is_prem else t_creds.get('file', 0)
|
| 1158 |
-
stt_rem = "نامحدود ∞" if is_prem else t_creds.get('stt', 0)
|
| 1159 |
-
image_rem = t_creds.get('image', 0)
|
| 1160 |
-
edit_image_rem = t_creds.get('edit_image', 0)
|
| 1161 |
-
|
| 1162 |
-
info_msg = f"""🔍 **اطلاعات کاربر `{target_id}`:**
|
| 1163 |
-
|
| 1164 |
-
🔹 **وضعیت:** {status_text}
|
| 1165 |
-
|
| 1166 |
-
📊 **سهمیه:**
|
| 1167 |
-
- چت: {chat_rem}
|
| 1168 |
-
- تولید عکس: {image_rem}
|
| 1169 |
-
- ویرایش عکس: {edit_image_rem}
|
| 1170 |
-
- پادکست: {podcast_rem}
|
| 1171 |
-
- متن به صدا: {tts_rem}
|
| 1172 |
-
- تحلیل فایل: {file_rem}
|
| 1173 |
-
- صدا به متن: {stt_rem}"""
|
| 1174 |
await send_with_keyboard(bot, chat_id, info_msg, False)
|
| 1175 |
else:
|
| 1176 |
await send_with_keyboard(bot, chat_id, f"❌ کاربری با شناسه `{target_id}` در دیتابیس یافت نشد.", False)
|
|
@@ -1195,7 +1102,7 @@ if bot:
|
|
| 1195 |
is_file = True
|
| 1196 |
file_name = getattr(message.video, 'file_name', f"video_{uuid.uuid4().hex[:6]}.mp4")
|
| 1197 |
|
| 1198 |
-
str_chat_id = str(chat_id)
|
| 1199 |
creds = get_user_credits(str_chat_id)
|
| 1200 |
|
| 1201 |
if user_text_str == "✅ عضو شدم":
|
|
@@ -1220,10 +1127,9 @@ if bot:
|
|
| 1220 |
return
|
| 1221 |
|
| 1222 |
# --- حساب کاربری ---
|
| 1223 |
-
if user_text_str in
|
| 1224 |
creds = get_user_credits(chat_id)
|
| 1225 |
is_prem = creds.get("is_premium", False)
|
| 1226 |
-
|
| 1227 |
if is_prem:
|
| 1228 |
expire_txt = "نامشخص"
|
| 1229 |
days_left = 0
|
|
@@ -1232,10 +1138,8 @@ if bot:
|
|
| 1232 |
now = datetime.datetime.now()
|
| 1233 |
diff = exp_d - now
|
| 1234 |
days_left = diff.days if diff.days >= 0 else 0
|
| 1235 |
-
|
| 1236 |
jy, jm, jd = gregorian_to_jalali(exp_d.year, exp_d.month, exp_d.day)
|
| 1237 |
expire_txt = f"{jy:04d}/{jm:02d}/{jd:02d} (ساعت {exp_d.hour:02d}:{exp_d.minute:02d})"
|
| 1238 |
-
|
| 1239 |
status_text = "🌟 نسخه پرو (ویژه)"
|
| 1240 |
expire_info = f"\n📅 **تاریخ انقضا:** {expire_txt}\n⏳ **زمان باقیمانده:** {days_left} روز"
|
| 1241 |
daily_note = "*نکته: سهمیه پردازشی شما مختص همین دوره یکماهه میباشد.*"
|
|
@@ -1339,10 +1243,10 @@ if bot:
|
|
| 1339 |
|
| 1340 |
if user_text_str in["/podcast", "📻 پادکست", "ساخت پادکست 🎙️"]:
|
| 1341 |
user_states[chat_id]["mode"] = "podcast_waiting_for_topic"
|
| 1342 |
-
await send_with_keyboard(bot, chat_id, "📻 شما وارد بخش **ساخت پادکست** شدید.\n\nلطفاً موضوع پادکست خود را بفرستید.\nمثال: درباره تاریخچه پیدایش قهوه با ۳ گوینده یک پادکست جذاب بساز .
|
| 1343 |
return
|
| 1344 |
|
| 1345 |
-
if user_text_str in["/file", "تحلیل فایل 📁"]:
|
| 1346 |
user_states[chat_id]["mode"] = "file_waiting_for_file"
|
| 1347 |
user_states[chat_id]["file_bytes"] = None
|
| 1348 |
await send_with_keyboard(bot, chat_id, "📁 شما وارد بخش **تحلیل فایل اختصاصی** شدید.\n\nلطفاً فایل خود را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
|
@@ -1355,7 +1259,7 @@ if bot:
|
|
| 1355 |
|
| 1356 |
if user_text_str in["/create_file", "ساخت فایل 📄"]:
|
| 1357 |
user_states[chat_id]["mode"] = "create_file_waiting_for_topic"
|
| 1358 |
-
await send_with_keyboard(bot, chat_id, "📄 شما وارد بخش **ساخت فایل** شدید.\n\nلطفاً موضوع مقالهای که میخواهید را کامل بفرستید.\nمثال: نحوه مدیریت زمان\n\n
|
| 1359 |
return
|
| 1360 |
|
| 1361 |
current_mode = user_states[chat_id].get("mode")
|
|
@@ -1370,13 +1274,13 @@ if bot:
|
|
| 1370 |
await send_with_keyboard(bot, chat_id, "📥 در حال دانلود فایل...", False)
|
| 1371 |
try:
|
| 1372 |
file_bytes = await helper_download_file(bot, message)
|
| 1373 |
-
|
| 1374 |
except Exception as dl_err: await send_with_keyboard(bot, chat_id, f"❌ خطا در دریافت فایل!\n{str(dl_err)}", False)
|
| 1375 |
-
elif user_text_str:
|
| 1376 |
return
|
| 1377 |
|
| 1378 |
elif current_mode == "image_waiting_for_text":
|
| 1379 |
-
if user_text_str:
|
| 1380 |
return
|
| 1381 |
|
| 1382 |
elif current_mode == "image_edit_waiting_for_image":
|
|
@@ -1395,7 +1299,7 @@ if bot:
|
|
| 1395 |
saved_bytes = user_states[chat_id].get("file_bytes")
|
| 1396 |
user_states[chat_id]["mode"] = None
|
| 1397 |
user_states[chat_id]["file_bytes"] = None
|
| 1398 |
-
|
| 1399 |
else: await send_with_keyboard(bot, chat_id, "⚠️ لطفاً درخواست خود را متنی بنویسید.", False)
|
| 1400 |
return
|
| 1401 |
|
|
@@ -1427,13 +1331,13 @@ if bot:
|
|
| 1427 |
spk_name, spk_id = SPEAKERS[normalized_text]
|
| 1428 |
txt = user_states[chat_id]["text"]
|
| 1429 |
user_states[chat_id]["mode"] = "tts_waiting_for_text"
|
| 1430 |
-
|
| 1431 |
else:
|
| 1432 |
await send_with_keyboard(bot, chat_id, "❌ شماره نامعتبر است! لطفاً فقط یک عدد بین 1 تا 30 بفرستید.", False)
|
| 1433 |
return
|
| 1434 |
|
| 1435 |
elif current_mode == "podcast_waiting_for_topic":
|
| 1436 |
-
if user_text_str:
|
| 1437 |
else: await send_with_keyboard(bot, chat_id, "⚠️ لطفاً موضوع پادکست خود را به صورت متنی بفرستید.", False)
|
| 1438 |
return
|
| 1439 |
|
|
@@ -1442,7 +1346,7 @@ if bot:
|
|
| 1442 |
await send_with_keyboard(bot, chat_id, "📥 در حال دانلود فایل...", False)
|
| 1443 |
try:
|
| 1444 |
audio_bytes = await helper_download_file(bot, message)
|
| 1445 |
-
|
| 1446 |
except Exception as dl_err: await send_with_keyboard(bot, chat_id, f"❌ خطا در دانلود فایل!\n{str(dl_err)}", False)
|
| 1447 |
return
|
| 1448 |
|
|
@@ -1463,18 +1367,20 @@ if bot:
|
|
| 1463 |
saved_bytes = user_states[chat_id].get("file_bytes")
|
| 1464 |
saved_name = user_states[chat_id].get("file_name", "file.jpeg")
|
| 1465 |
user_states[chat_id]["mode"] = "file_waiting_for_file"
|
| 1466 |
-
|
| 1467 |
else: await send_with_keyboard(bot, chat_id, "⚠️ لطفاً درخواست خود را متنی بنویسید.", False)
|
| 1468 |
return
|
| 1469 |
|
| 1470 |
elif current_mode == "create_file_waiting_for_topic":
|
| 1471 |
if user_text_str:
|
| 1472 |
-
|
| 1473 |
else:
|
| 1474 |
await send_with_keyboard(bot, chat_id, "⚠️ لطفاً موضوع مقاله خود را به صورت متنی بفرستید.", False)
|
| 1475 |
return
|
| 1476 |
|
| 1477 |
-
except Exception:
|
|
|
|
|
|
|
| 1478 |
|
| 1479 |
if __name__ == "__main__":
|
| 1480 |
threading.Thread(target=run_flask, daemon=True).start()
|
|
@@ -1482,4 +1388,5 @@ if __name__ == "__main__":
|
|
| 1482 |
print("خطا: توکن ربات بله وارد نشده است! لطفا متغیر BALE_TOKEN را تنظیم کنید.")
|
| 1483 |
else:
|
| 1484 |
print("ربات آلفا پرو با سیستم اشتراک نامحدود + سپر امنیتی متصل به پیامرسان «بله» روشن شد... 🚀")
|
| 1485 |
-
|
|
|
|
|
|
| 17 |
# کتابخانههای ربات تلگرام/بله
|
| 18 |
import telebot
|
| 19 |
from telebot.async_telebot import AsyncTeleBot
|
| 20 |
+
from telebot import asyncio_helper # ماژول صحیح برای اتصال به بله در حالت غیرهمزمان
|
| 21 |
from telebot.types import ReplyKeyboardMarkup, KeyboardButton
|
| 22 |
|
| 23 |
# ایمپورتهای هوش مصنوعی، کار با فایل صوتی و دیتابیس هاگینگ فیس
|
|
|
|
| 35 |
# متغیر سراسری برای ذخیره آیدی خود ربات (جلوگیری از جواب دادن ربات به خودش)
|
| 36 |
BOT_GUID = None
|
| 37 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
# --- سیستم دیتابیس حساب کاربری متصل به دیتاست هاگینگ فیس ---
|
| 39 |
DB_FILE = "users_db.json"
|
| 40 |
DATASET_REPO = "Opera8/Karbaran-rayegan-tedad"
|
|
|
|
| 74 |
print("✅ دیتابیس با موفقیت از دیتاست هاگینگ فیس لود شد.")
|
| 75 |
return json.load(f)
|
| 76 |
except Exception as e:
|
| 77 |
+
print("⚠️ فایل دیتابیس در هاگینگ فیس یافت نشد (ساخت دیتابیس جدید).")
|
| 78 |
|
| 79 |
if os.path.exists(DB_FILE):
|
| 80 |
try:
|
|
|
|
| 169 |
|
| 170 |
@app.route('/')
|
| 171 |
def home():
|
| 172 |
+
return "ربات یکپارچه آلفا (متصل به بله + دیتاست + بدون قفلی) روشن است! 🚀"
|
| 173 |
|
| 174 |
def run_flask():
|
| 175 |
app.run(host="0.0.0.0", port=7860)
|
|
|
|
| 193 |
markup.row(KeyboardButton("✅ عضو شدم"))
|
| 194 |
return markup
|
| 195 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 196 |
|
| 197 |
# --- تابع ارسال منحصراً برای کیبورد پایین صفحه ---
|
| 198 |
async def send_with_keyboard(client, chat_id, text, use_keyboard=True):
|
|
|
|
| 239 |
_raw_keys.extend(GEMINI_KEYS_STR2.split(","))
|
| 240 |
|
| 241 |
GEMINI_KEYS = list(set([k.strip() for k in _raw_keys if k.strip()]))
|
|
|
|
|
|
|
| 242 |
current_gemini_key_index = 0
|
| 243 |
gemini_key_lock = threading.Lock()
|
| 244 |
|
|
|
|
| 273 |
markup = get_main_keyboard()
|
| 274 |
if file_type in["photo", "Image", "image"]:
|
| 275 |
await client.send_photo(chat_id, photo=f, caption=caption, reply_markup=markup)
|
| 276 |
+
elif file_type in["voice", "Voice", "audio"]:
|
| 277 |
if abs_path.lower().endswith('.ogg'):
|
| 278 |
await client.send_voice(chat_id, voice=f, caption=caption, reply_markup=markup)
|
| 279 |
else:
|
|
|
|
| 305 |
}
|
| 306 |
|
| 307 |
user_states = {}
|
|
|
|
|
|
|
| 308 |
|
| 309 |
|
| 310 |
# --- ۱. پردازش چت متنی و چندرسانهای ---
|
| 311 |
async def process_gemini(client, chat_id, prompt, file_bytes=None, file_name=None):
|
| 312 |
+
str_chat_id = str(chat_id)
|
| 313 |
creds = get_user_credits(str_chat_id)
|
| 314 |
if creds["chat"] <= 0:
|
| 315 |
return await send_with_keyboard(client, chat_id, "❌ اعتبار پیامهای چت شما تمام شده است. لطفاً از منوی اصلی وار�� بخش «خرید اشتراک 💎» شوید.", False)
|
|
|
|
| 443 |
|
| 444 |
# --- ۲. پردازش ساخت عکس ---
|
| 445 |
async def process_image(client, chat_id, prompt):
|
| 446 |
+
str_chat_id = str(chat_id)
|
| 447 |
creds = get_user_credits(str_chat_id)
|
| 448 |
if creds["image"] <= 0:
|
| 449 |
return await send_with_keyboard(client, chat_id, "❌ اعتبار ساخت عکس شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False)
|
|
|
|
| 569 |
|
| 570 |
# --- ۲.۵. پردازش ویرایش عکس ---
|
| 571 |
async def process_image_edit(client, chat_id, image_bytes, prompt):
|
| 572 |
+
str_chat_id = str(chat_id)
|
| 573 |
creds = get_user_credits(str_chat_id)
|
| 574 |
if creds["edit_image"] <= 0:
|
| 575 |
return await send_with_keyboard(client, chat_id, "❌ اعتبار ویرایش عکس شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False)
|
|
|
|
| 629 |
|
| 630 |
# --- ۳. پردازش ساخت صدا ---
|
| 631 |
async def process_tts(client, chat_id, user_text, speaker_id, speaker_name):
|
| 632 |
+
str_chat_id = str(chat_id)
|
| 633 |
creds = get_user_credits(str_chat_id)
|
| 634 |
if creds["tts"] <= 0:
|
| 635 |
return await send_with_keyboard(client, chat_id, "❌ اعتبار تبدیل متن به صدای شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False)
|
|
|
|
| 685 |
|
| 686 |
# --- ۳.۵. پردازش پادکست ---
|
| 687 |
async def process_podcast(client, chat_id, prompt):
|
| 688 |
+
str_chat_id = str(chat_id)
|
| 689 |
creds = get_user_credits(str_chat_id)
|
| 690 |
if creds["podcast"] <= 0:
|
| 691 |
return await send_with_keyboard(client, chat_id, "❌ اعتبار ساخت پادکست شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False)
|
|
|
|
| 777 |
|
| 778 |
# --- ۴. پردازش تبدیل فایل صوتی/تصویری به متن ---
|
| 779 |
async def process_stt(client, chat_id, audio_bytes, file_name):
|
| 780 |
+
str_chat_id = str(chat_id)
|
| 781 |
creds = get_user_credits(str_chat_id)
|
| 782 |
if creds["stt"] <= 0:
|
| 783 |
return await send_with_keyboard(client, chat_id, "❌ اعتبار تبدیل صدا به متن شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False)
|
|
|
|
| 822 |
|
| 823 |
# --- ۵. پردازش تحلیل فایل مستقل ---
|
| 824 |
async def process_file_analysis(client, chat_id, file_bytes, file_name, prompt):
|
| 825 |
+
str_chat_id = str(chat_id)
|
| 826 |
creds = get_user_credits(str_chat_id)
|
| 827 |
if creds["file"] <= 0:
|
| 828 |
return await send_with_keyboard(client, chat_id, "❌ اعتبار تحلیل فایل شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False)
|
|
|
|
| 866 |
|
| 867 |
# --- ۵.۵. پردازش ساخت مقاله و تبدیل به فایل ---
|
| 868 |
async def process_create_file(client, chat_id, topic):
|
| 869 |
+
str_chat_id = str(chat_id)
|
| 870 |
creds = get_user_credits(str_chat_id)
|
| 871 |
|
| 872 |
if creds["chat"] <= 0:
|
|
|
|
| 992 |
if bot:
|
| 993 |
@bot.message_handler(func=lambda message: True, content_types=['text', 'photo', 'document', 'voice', 'audio', 'video'])
|
| 994 |
async def main_handler(message):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 995 |
try:
|
| 996 |
+
global BOT_GUID
|
| 997 |
if not BOT_GUID:
|
| 998 |
try:
|
| 999 |
me_info = await bot.get_me()
|
| 1000 |
+
if me_info: BOT_GUID = me_info.id
|
|
|
|
| 1001 |
except Exception:
|
| 1002 |
pass
|
| 1003 |
|
|
|
|
| 1006 |
return
|
| 1007 |
|
| 1008 |
chat_id = message.chat.id
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1009 |
|
| 1010 |
user_text = message.text or message.caption or ""
|
| 1011 |
user_text_str = str(user_text).strip() if user_text else ""
|
|
|
|
| 1021 |
target_id = parts[1].replace("`", "").replace("'", "").replace('"', "").strip()
|
| 1022 |
if target_id:
|
| 1023 |
if target_id not in user_credits_db:
|
| 1024 |
+
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}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1025 |
user_credits_db[target_id]["is_premium"] = True
|
| 1026 |
expire_time = datetime.datetime.now() + datetime.timedelta(days=30)
|
| 1027 |
user_credits_db[target_id]["expire_date"] = expire_time.isoformat()
|
|
|
|
| 1028 |
user_credits_db[target_id]["chat"] = 999999
|
| 1029 |
user_credits_db[target_id]["image"] = 20
|
| 1030 |
user_credits_db[target_id]["edit_image"] = 10
|
|
|
|
| 1032 |
user_credits_db[target_id]["tts"] = 999999
|
| 1033 |
user_credits_db[target_id]["file"] = 999999
|
| 1034 |
user_credits_db[target_id]["stt"] = 999999
|
|
|
|
| 1035 |
save_db(user_credits_db)
|
| 1036 |
await send_with_keyboard(bot, chat_id, f"✅ حساب کاربر `{target_id}` به مدت ۳۰ روز شارژ شد و به پرو ارتقا یافت.", False)
|
| 1037 |
try:
|
|
|
|
| 1063 |
if target_id in user_credits_db:
|
| 1064 |
t_creds = user_credits_db[target_id]
|
| 1065 |
is_prem = t_creds.get("is_premium", False)
|
|
|
|
| 1066 |
if is_prem:
|
| 1067 |
expire_txt = "نامشخص"
|
| 1068 |
days_left = 0
|
|
|
|
| 1071 |
now = datetime.datetime.now()
|
| 1072 |
diff = exp_d - now
|
| 1073 |
days_left = diff.days if diff.days >= 0 else 0
|
|
|
|
| 1074 |
jy, jm, jd = gregorian_to_jalali(exp_d.year, exp_d.month, exp_d.day)
|
| 1075 |
expire_txt = f"{jy:04d}/{jm:02d}/{jd:02d}"
|
| 1076 |
status_text = f"🌟 نسخه پرو (ویژه)\n📅 انقضا: {expire_txt}\n⏳ باقیمانده: {days_left} روز"
|
| 1077 |
else:
|
| 1078 |
status_text = "🥉 نسخه رایگان (آزمایشی)\n⏳ سهمیه روزانه"
|
| 1079 |
|
| 1080 |
+
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)}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1081 |
await send_with_keyboard(bot, chat_id, info_msg, False)
|
| 1082 |
else:
|
| 1083 |
await send_with_keyboard(bot, chat_id, f"❌ کاربری با شناسه `{target_id}` در دیتابیس یافت نشد.", False)
|
|
|
|
| 1102 |
is_file = True
|
| 1103 |
file_name = getattr(message.video, 'file_name', f"video_{uuid.uuid4().hex[:6]}.mp4")
|
| 1104 |
|
| 1105 |
+
str_chat_id = str(chat_id)
|
| 1106 |
creds = get_user_credits(str_chat_id)
|
| 1107 |
|
| 1108 |
if user_text_str == "✅ عضو شدم":
|
|
|
|
| 1127 |
return
|
| 1128 |
|
| 1129 |
# --- حساب کاربری ---
|
| 1130 |
+
if user_text_str in["/account", "حساب کاربری 👤"]:
|
| 1131 |
creds = get_user_credits(chat_id)
|
| 1132 |
is_prem = creds.get("is_premium", False)
|
|
|
|
| 1133 |
if is_prem:
|
| 1134 |
expire_txt = "نامشخص"
|
| 1135 |
days_left = 0
|
|
|
|
| 1138 |
now = datetime.datetime.now()
|
| 1139 |
diff = exp_d - now
|
| 1140 |
days_left = diff.days if diff.days >= 0 else 0
|
|
|
|
| 1141 |
jy, jm, jd = gregorian_to_jalali(exp_d.year, exp_d.month, exp_d.day)
|
| 1142 |
expire_txt = f"{jy:04d}/{jm:02d}/{jd:02d} (ساعت {exp_d.hour:02d}:{exp_d.minute:02d})"
|
|
|
|
| 1143 |
status_text = "🌟 نسخه پرو (ویژه)"
|
| 1144 |
expire_info = f"\n📅 **تاریخ انقضا:** {expire_txt}\n⏳ **زمان باقیمانده:** {days_left} روز"
|
| 1145 |
daily_note = "*نکته: سهمیه پردازشی شما مختص همین دوره یکماهه میباشد.*"
|
|
|
|
| 1243 |
|
| 1244 |
if user_text_str in["/podcast", "📻 پادکست", "ساخت پادکست 🎙️"]:
|
| 1245 |
user_states[chat_id]["mode"] = "podcast_waiting_for_topic"
|
| 1246 |
+
await send_with_keyboard(bot, chat_id, "📻 شما وارد بخش **ساخت پادکست** شدید.\n\nلطفاً موضوع پادکست خود را بفرستید.\nمثال: درباره تاریخچه پیدایش قهوه با ۳ گوینده یک پادکست جذاب بساز .\n\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1247 |
return
|
| 1248 |
|
| 1249 |
+
if user_text_str in ["/file", "تحلیل فایل 📁"]:
|
| 1250 |
user_states[chat_id]["mode"] = "file_waiting_for_file"
|
| 1251 |
user_states[chat_id]["file_bytes"] = None
|
| 1252 |
await send_with_keyboard(bot, chat_id, "📁 شما وارد بخش **تحلیل فایل اختصاصی** شدید.\n\nلطفاً فایل خود را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
|
|
|
| 1259 |
|
| 1260 |
if user_text_str in["/create_file", "ساخت فایل 📄"]:
|
| 1261 |
user_states[chat_id]["mode"] = "create_file_waiting_for_topic"
|
| 1262 |
+
await send_with_keyboard(bot, chat_id, "📄 شما وارد بخش **ساخت فایل** شدید.\n\nلطفاً موضوع مقالهای که میخواهید را کامل بفرستید.\nمثال: نحوه مدیریت زمان\n\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1263 |
return
|
| 1264 |
|
| 1265 |
current_mode = user_states[chat_id].get("mode")
|
|
|
|
| 1274 |
await send_with_keyboard(bot, chat_id, "📥 در حال دانلود فایل...", False)
|
| 1275 |
try:
|
| 1276 |
file_bytes = await helper_download_file(bot, message)
|
| 1277 |
+
await process_gemini(bot, chat_id, user_text_str, file_bytes=file_bytes, file_name=file_name)
|
| 1278 |
except Exception as dl_err: await send_with_keyboard(bot, chat_id, f"❌ خطا در دریافت فایل!\n{str(dl_err)}", False)
|
| 1279 |
+
elif user_text_str: await process_gemini(bot, chat_id, user_text_str)
|
| 1280 |
return
|
| 1281 |
|
| 1282 |
elif current_mode == "image_waiting_for_text":
|
| 1283 |
+
if user_text_str: await process_image(bot, chat_id, user_text_str)
|
| 1284 |
return
|
| 1285 |
|
| 1286 |
elif current_mode == "image_edit_waiting_for_image":
|
|
|
|
| 1299 |
saved_bytes = user_states[chat_id].get("file_bytes")
|
| 1300 |
user_states[chat_id]["mode"] = None
|
| 1301 |
user_states[chat_id]["file_bytes"] = None
|
| 1302 |
+
await process_image_edit(bot, chat_id, saved_bytes, user_text_str)
|
| 1303 |
else: await send_with_keyboard(bot, chat_id, "⚠️ لطفاً درخواست خود را متنی بنویسید.", False)
|
| 1304 |
return
|
| 1305 |
|
|
|
|
| 1331 |
spk_name, spk_id = SPEAKERS[normalized_text]
|
| 1332 |
txt = user_states[chat_id]["text"]
|
| 1333 |
user_states[chat_id]["mode"] = "tts_waiting_for_text"
|
| 1334 |
+
await process_tts(bot, chat_id, txt, spk_id, spk_name)
|
| 1335 |
else:
|
| 1336 |
await send_with_keyboard(bot, chat_id, "❌ شماره نامعتبر است! لطفاً فقط یک عدد بین 1 تا 30 بفرستید.", False)
|
| 1337 |
return
|
| 1338 |
|
| 1339 |
elif current_mode == "podcast_waiting_for_topic":
|
| 1340 |
+
if user_text_str: await process_podcast(bot, chat_id, user_text_str)
|
| 1341 |
else: await send_with_keyboard(bot, chat_id, "⚠️ لطفاً موضوع پادکست خود را به صورت متنی بفرستید.", False)
|
| 1342 |
return
|
| 1343 |
|
|
|
|
| 1346 |
await send_with_keyboard(bot, chat_id, "📥 در حال دانلود فایل...", False)
|
| 1347 |
try:
|
| 1348 |
audio_bytes = await helper_download_file(bot, message)
|
| 1349 |
+
await process_stt(bot, chat_id, audio_bytes, file_name)
|
| 1350 |
except Exception as dl_err: await send_with_keyboard(bot, chat_id, f"❌ خطا در دانلود فایل!\n{str(dl_err)}", False)
|
| 1351 |
return
|
| 1352 |
|
|
|
|
| 1367 |
saved_bytes = user_states[chat_id].get("file_bytes")
|
| 1368 |
saved_name = user_states[chat_id].get("file_name", "file.jpeg")
|
| 1369 |
user_states[chat_id]["mode"] = "file_waiting_for_file"
|
| 1370 |
+
await process_file_analysis(bot, chat_id, saved_bytes, saved_name, user_text_str)
|
| 1371 |
else: await send_with_keyboard(bot, chat_id, "⚠️ لطفاً درخواست خود را متنی بنویسید.", False)
|
| 1372 |
return
|
| 1373 |
|
| 1374 |
elif current_mode == "create_file_waiting_for_topic":
|
| 1375 |
if user_text_str:
|
| 1376 |
+
await process_create_file(bot, chat_id, user_text_str)
|
| 1377 |
else:
|
| 1378 |
await send_with_keyboard(bot, chat_id, "⚠️ لطفاً موضوع مقاله خود را به صورت متنی بفرستید.", False)
|
| 1379 |
return
|
| 1380 |
|
| 1381 |
+
except Exception as e:
|
| 1382 |
+
print("خطا در پردازش:", e)
|
| 1383 |
+
traceback.print_exc()
|
| 1384 |
|
| 1385 |
if __name__ == "__main__":
|
| 1386 |
threading.Thread(target=run_flask, daemon=True).start()
|
|
|
|
| 1388 |
print("خطا: توکن ربات بله وارد نشده است! لطفا متغیر BALE_TOKEN را تنظیم کنید.")
|
| 1389 |
else:
|
| 1390 |
print("ربات آلفا پرو با سیستم اشتراک نامحدود + سپر امنیتی متصل به پیامرسان «بله» روشن شد... 🚀")
|
| 1391 |
+
# تنظیم زمان تایماوت معقول برای جلوگیری از بسته شدن کانکشن بله
|
| 1392 |
+
asyncio.run(bot.polling(non_stop=True, timeout=20, request_timeout=30))
|