pmrony commited on
Commit
7663da4
·
verified ·
1 Parent(s): 491e87c

Upload main.py

Browse files
Files changed (1) hide show
  1. main.py +81 -30
main.py CHANGED
@@ -2,6 +2,7 @@ import logging
2
  import os
3
  import asyncio
4
  import threading
 
5
  from fastapi import FastAPI
6
  import uvicorn
7
  import redis.asyncio as redis
@@ -23,10 +24,12 @@ from telegram.ext import (
23
 
24
  # আপনার প্রজেক্টের ফাইলগুলো থেকে ইম্পোর্ট
25
  from credentials import BOT_TOKEN, BOT_OWNER_ID, REPORT_CHANNEL_ID, REDIS_URL_1, REDIS_URL_2
 
26
  from config import logger, BOT_VERSION, TELEGRAM_API_CONCURRENCY_LIMIT
27
  from db import create_db_pool_with_retry, setup_database
28
  import db
29
  from bot_handlers.batch import BatchDeleter
 
30
 
31
  # --- ১. Hugging Face Health Check Server (Port 7860) ---
32
  app_web = FastAPI()
@@ -44,6 +47,7 @@ async def global_error_handler(update: object, context: ContextTypes.DEFAULT_TYP
44
  logger.error("Exception while handling an update:", exc_info=context.error)
45
 
46
  # --- ৩. ব্যাকগ্রাউন্ড টাস্কসমূহ ---
 
47
  async def user_stats_flush_loop(app):
48
  while True:
49
  await asyncio.sleep(300) # প্রতি ৫ মিনিট পর DB-তে ডাটা ফ্লাশ হবে
@@ -68,31 +72,92 @@ async def check_expired_trials_loop(app):
68
  await conn.execute("DELETE FROM vip_trials WHERE expiry_date < $1", now_utc)
69
  except Exception as e:
70
  logger.error(f"❌ VIP Monitor Error: {e}")
71
-
72
 
73
  async def recovery_traffic_locks(app):
74
  """বট স্টার্ট হওয়ার সময় চেক করবে কোনো গ্রুপ লক হয়ে আছে কি না"""
75
  pool = app.bot_data.get('db_pool')
76
  if not pool: return
77
-
78
- # সব গ্রুপ আইডি আনা (db.py থেকে)
79
  group_ids = await db.get_all_group_ids(pool)
80
  for chat_id in group_ids:
81
  from bot_handlers.redis_manager import get_redis_client_for_chat
82
- redis = get_redis_client_for_chat(app, chat_id)
83
- if redis:
84
- backup = await redis.get(f"backup_perms:{chat_id}")
85
  if backup:
86
  from bot_handlers.utils import restore_group_permissions
87
  await restore_group_permissions(app, chat_id, backup)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
 
89
- # --- ৪. জয়েন রিকোয়েস্ট হ্যান্ডেলার (সাইলেন্ট মোড) ---
 
 
 
 
90
  async def handle_join_request(update: Update, context: ContextTypes.DEFAULT_TYPE):
91
  req = update.chat_join_request
92
  user, chat = req.from_user, req.chat
93
  pool = context.bot_data.get('db_pool')
94
 
95
- # ব্যাকগ্রাউন্ডে রেডিস আপডেট (যাতে /grant কমান্ড ইউজ করা যায়)
96
  if user.username:
97
  clean_username = user.username.lower().replace("@", "")
98
  clients = context.bot_data.get('redis_clients')
@@ -100,7 +165,6 @@ async def handle_join_request(update: Update, context: ContextTypes.DEFAULT_TYPE
100
  try: await clients[0].set(f"join_cache:{clean_username}", user.id, ex=2592000)
101
  except: pass
102
 
103
- # ডাটাবেসে টেম্পোরারি সেভ করা
104
  if pool:
105
  try:
106
  temp_expiry = datetime.now(timezone.utc) + timedelta(minutes=10)
@@ -120,12 +184,9 @@ async def w_msg(u, c): from bot_handlers.core import handle_message; await handl
120
  async def w_edit_msg(u, c): from bot_handlers.core import handle_edited_message; await handle_edited_message(u, c)
121
  async def w_callback(u, c): from bot_handlers import callbacks; await callbacks.w_callback(u, c)
122
 
123
- # main.py এর safe_start_command অংশটি রিপ্লেস করুন
124
- async def safe_start_command(update, context):
125
  user = update.effective_user
126
  if update.effective_chat.type != 'private': return
127
-
128
- # ইউজার ডাটাবেসে সেভ (ট্র্যাকিংয়ের জন্য)
129
  pool = context.bot_data.get('db_pool')
130
  if pool:
131
  asyncio.create_task(pool.execute("""
@@ -139,11 +200,7 @@ async def safe_start_command(update, context):
139
  InlineKeyboardButton("বাংলা 🇧🇩", callback_data='lang_bn')],
140
  [InlineKeyboardButton("हिन्दी 🇮🇳", callback_data='lang_hi')]
141
  ])
142
-
143
- await update.message.reply_html(
144
- f"👋 <b>Hello {user.first_name}!</b>\n\nWelcome to Management Bot. Please choose your language to continue:",
145
- reply_markup=keyboard
146
- )
147
 
148
  # --- ৬. POST INIT & STOP ---
149
  async def post_init(app: Application):
@@ -167,9 +224,13 @@ async def post_init(app: Application):
167
  app.bot_data['BOT_OWNER_ID'] = int(BOT_OWNER_ID) if BOT_OWNER_ID else None
168
  app.bot_data['REPORT_CHANNEL_ID'] = int(REPORT_CHANNEL_ID) if REPORT_CHANNEL_ID else None
169
 
 
 
 
 
 
170
  asyncio.create_task(check_expired_trials_loop(app))
171
  asyncio.create_task(user_stats_flush_loop(app))
172
- # ট্রাফিক লক রিকভারি টাস্ক শুরু করা
173
  asyncio.create_task(recovery_traffic_locks(app))
174
 
175
  async def post_stop(app: Application):
@@ -177,18 +238,16 @@ async def post_stop(app: Application):
177
  if p := app.bot_data.get('db_pool'): await p.close()
178
  for r in app.bot_data.get('redis_clients', []): await r.close()
179
 
180
- # --- ৭. প্রধান ফাংশন (All Handlers Registred) ---
181
  def main():
182
  if not BOT_TOKEN: return
183
  app = Application.builder().token(BOT_TOKEN).post_init(post_init).post_stop(post_stop).build()
184
  app.add_error_handler(global_error_handler)
185
 
186
- # মডিউল ইম্পোর্ট
187
  from bot_handlers import admin_commands as ac
188
  from bot_handlers import extra_commands as ec
189
  from bot_handlers import owner_commands as oc
190
 
191
- # --- ১. সাধারণ ও অ্যাডমিন কমান্ড ---
192
  app.add_handler(CommandHandler("start", safe_start_command))
193
  app.add_handler(CommandHandler("grant", ac.vip_trial_command))
194
  app.add_handler(CommandHandler("whois", ac.whois_command))
@@ -198,8 +257,6 @@ def main():
198
  app.add_handler(CommandHandler("delword", ac.del_word_command))
199
  app.add_handler(CommandHandler("wordlist", ac.wordlist_command))
200
  app.add_handler(CommandHandler("resetsettings", ac.reset_settings_command))
201
-
202
- # --- ২. এক্সট্রা ও সেটিংস কমান্ড ---
203
  app.add_handler(CommandHandler("filter", ec.filter_command))
204
  app.add_handler(CommandHandler("stop", ec.stop_filter_command))
205
  app.add_handler(CommandHandler("save", ec.save_note_command))
@@ -222,8 +279,6 @@ def main():
222
  app.add_handler(CommandHandler("ticket", ec.ticket_command))
223
  app.add_handler(CommandHandler("trustscore", ec.trustscore_command))
224
  app.add_handler(CommandHandler("fixdb", ec.fix_database_command))
225
-
226
- # --- ৩. ওনার ও টুলস কমান্ড ---
227
  app.add_handler(CommandHandler("broadcast", oc.broadcast_command))
228
  app.add_handler(CommandHandler("bc", oc.broadcast_groups_command))
229
  app.add_handler(CommandHandler("stats", oc.stats_command))
@@ -235,7 +290,6 @@ def main():
235
  app.add_handler(CommandHandler("sdel", oc.sdel_command))
236
  app.add_handler(CommandHandler("smute", oc.smute_command))
237
 
238
- # --- ৪. কোর মেসেজ ও কলব্যাক হ্যান্ডেলার ---
239
  app.add_handler(CallbackQueryHandler(w_callback))
240
  app.add_handler(ChatJoinRequestHandler(handle_join_request))
241
  app.add_handler(MessageHandler(filters.ALL & ~filters.COMMAND, w_msg))
@@ -243,10 +297,7 @@ def main():
243
  app.add_handler(ChatMemberHandler(w_bot_status, ChatMemberHandler.MY_CHAT_MEMBER))
244
  app.add_handler(ChatMemberHandler(w_member_status, ChatMemberHandler.CHAT_MEMBER))
245
 
246
- # ওয়েব সার্ভার চালু করা (Hugging Face Health Check-এর জন্য)
247
  threading.Thread(target=run_web_server, daemon=True).start()
248
-
249
- # পোলিং মোডে বট চালু করা
250
  logger.info("Bot is polling silently...")
251
  app.run_polling(allowed_updates=["message", "callback_query", "chat_member", "my_chat_member", "chat_join_request", "edited_message"])
252
 
 
2
  import os
3
  import asyncio
4
  import threading
5
+ import re
6
  from fastapi import FastAPI
7
  import uvicorn
8
  import redis.asyncio as redis
 
24
 
25
  # আপনার প্রজেক্টের ফাইলগুলো থেকে ইম্পোর্ট
26
  from credentials import BOT_TOKEN, BOT_OWNER_ID, REPORT_CHANNEL_ID, REDIS_URL_1, REDIS_URL_2
27
+ import config
28
  from config import logger, BOT_VERSION, TELEGRAM_API_CONCURRENCY_LIMIT
29
  from db import create_db_pool_with_retry, setup_database
30
  import db
31
  from bot_handlers.batch import BatchDeleter
32
+ from bot_handlers import utils
33
 
34
  # --- ১. Hugging Face Health Check Server (Port 7860) ---
35
  app_web = FastAPI()
 
47
  logger.error("Exception while handling an update:", exc_info=context.error)
48
 
49
  # --- ৩. ব্যাকগ্রাউন্ড টাস্কসমূহ ---
50
+
51
  async def user_stats_flush_loop(app):
52
  while True:
53
  await asyncio.sleep(300) # প্রতি ৫ মিনিট পর DB-তে ডাটা ফ্লাশ হবে
 
72
  await conn.execute("DELETE FROM vip_trials WHERE expiry_date < $1", now_utc)
73
  except Exception as e:
74
  logger.error(f"❌ VIP Monitor Error: {e}")
 
75
 
76
  async def recovery_traffic_locks(app):
77
  """বট স্টার্ট হওয়ার সময় চেক করবে কোনো গ্রুপ লক হয়ে আছে কি না"""
78
  pool = app.bot_data.get('db_pool')
79
  if not pool: return
 
 
80
  group_ids = await db.get_all_group_ids(pool)
81
  for chat_id in group_ids:
82
  from bot_handlers.redis_manager import get_redis_client_for_chat
83
+ redis_client = get_redis_client_for_chat(app, chat_id)
84
+ if redis_client:
85
+ backup = await redis_client.get(f"backup_perms:{chat_id}")
86
  if backup:
87
  from bot_handlers.utils import restore_group_permissions
88
  await restore_group_permissions(app, chat_id, backup)
89
+
90
+ # 🔥 নতুন: ব্যাকগ্রাউন্ড বায়ো চেকার টাস্ক (একই প্রসেসের ভেতরে চলবে)
91
+ async def background_bio_task(app):
92
+ """এটি মেইন বটের ভেতরেই কিউ থেকে আইডি নিয়ে এক এক করে প্রোফাইল চেক করবে"""
93
+ while True:
94
+ try:
95
+ # লাইন (Queue) থেকে ডাটা নিবে
96
+ data = await app.bot_data['bio_queue'].get()
97
+ chat_id, user_id, msg_id, settings, user_obj = data
98
+
99
+ # রেট লিমিট এড়াতে ০.১ সেকেন্ড বিরতি
100
+ await asyncio.sleep(0.1)
101
+
102
+ try:
103
+ full_user = await app.bot.get_chat(user_id)
104
+ bio_text = getattr(full_user, 'bio', "") or ""
105
+ first_name = full_user.first_name or ""
106
+ last_name = full_user.last_name or ""
107
+ personal_chat = getattr(full_user, 'personal_chat', None)
108
+
109
+ full_profile_text = f"{first_name} {last_name} {bio_text}".strip()
110
+ is_bad = False
111
+ reason_text = "Bad Profile (Auto-detected)"
112
+
113
+ if personal_chat:
114
+ is_bad = True
115
+ reason_text = "Personal Channel Linked"
116
+ elif full_profile_text:
117
+ if utils.has_link_in_text(full_profile_text) or config.SPAM_PHRASES_COMPILED.search(full_profile_text):
118
+ is_bad = True
119
+ reason_text = "Link or Spam words in Bio/Name"
120
+
121
+ redis_client = app.bot_data.get('redis_clients')[0] if app.bot_data.get('redis_clients') else None
122
+
123
+ if is_bad:
124
+ if redis_client: await redis_client.set(f"bio_status:{user_id}", "bad", ex=1800)
125
+
126
+ # মেসেজ ডিলিট
127
+ try: await app.bot.delete_message(chat_id, msg_id)
128
+ except: pass
129
+
130
+ # ডিলেশন রিপোর্ট পাঠানো (Optional)
131
+ try:
132
+ from bot_handlers.core import _background_processing
133
+ class DummyContext:
134
+ def __init__(self, bot, bot_data):
135
+ self.bot = bot
136
+ self.bot_data = bot_data
137
+ dummy_ctx = DummyContext(app.bot, app.bot_data)
138
+ chat_obj = await app.bot.get_chat(chat_id)
139
+ asyncio.create_task(_background_processing(dummy_ctx, user_obj, chat_obj, settings, ['censor_reason_bio_link'], reason_text))
140
+ except: pass
141
+ else:
142
+ if redis_client: await redis_client.set(f"bio_status:{user_id}", "safe", ex=1600)
143
+
144
+ except Exception:
145
+ pass
146
+ finally:
147
+ # কাজ শেষ হলে ইউজার লক রিলিজ করা
148
+ redis_client = app.bot_data.get('redis_clients')[0] if app.bot_data.get('redis_clients') else None
149
+ if redis_client: await redis_client.delete(f"bio_lock:{user_id}")
150
 
151
+ app.bot_data['bio_queue'].task_done()
152
+ except Exception as e:
153
+ logger.error(f"Bio Task Error: {e}")
154
+
155
+ # --- ৪. জয়েন রিকোয়েস্ট হ্যান্ডেলার ---
156
  async def handle_join_request(update: Update, context: ContextTypes.DEFAULT_TYPE):
157
  req = update.chat_join_request
158
  user, chat = req.from_user, req.chat
159
  pool = context.bot_data.get('db_pool')
160
 
 
161
  if user.username:
162
  clean_username = user.username.lower().replace("@", "")
163
  clients = context.bot_data.get('redis_clients')
 
165
  try: await clients[0].set(f"join_cache:{clean_username}", user.id, ex=2592000)
166
  except: pass
167
 
 
168
  if pool:
169
  try:
170
  temp_expiry = datetime.now(timezone.utc) + timedelta(minutes=10)
 
184
  async def w_edit_msg(u, c): from bot_handlers.core import handle_edited_message; await handle_edited_message(u, c)
185
  async def w_callback(u, c): from bot_handlers import callbacks; await callbacks.w_callback(u, c)
186
 
187
+ async def safe_start_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
 
188
  user = update.effective_user
189
  if update.effective_chat.type != 'private': return
 
 
190
  pool = context.bot_data.get('db_pool')
191
  if pool:
192
  asyncio.create_task(pool.execute("""
 
200
  InlineKeyboardButton("বাংলা 🇧🇩", callback_data='lang_bn')],
201
  [InlineKeyboardButton("हिन्दी 🇮🇳", callback_data='lang_hi')]
202
  ])
203
+ await update.message.reply_html(f"👋 <b>Hello {user.first_name}!</b>\n\nPlease choose language:", reply_markup=keyboard)
 
 
 
 
204
 
205
  # --- ৬. POST INIT & STOP ---
206
  async def post_init(app: Application):
 
224
  app.bot_data['BOT_OWNER_ID'] = int(BOT_OWNER_ID) if BOT_OWNER_ID else None
225
  app.bot_data['REPORT_CHANNEL_ID'] = int(REPORT_CHANNEL_ID) if REPORT_CHANNEL_ID else None
226
 
227
+ # 🔥 কিউ তৈরি এবং ব্যাকগ্রাউন্ড টাস্ক চালু করা
228
+ app.bot_data['bio_queue'] = asyncio.Queue()
229
+ asyncio.create_task(background_bio_task(app))
230
+
231
+ # বাকি লুপগুলো শুরু
232
  asyncio.create_task(check_expired_trials_loop(app))
233
  asyncio.create_task(user_stats_flush_loop(app))
 
234
  asyncio.create_task(recovery_traffic_locks(app))
235
 
236
  async def post_stop(app: Application):
 
238
  if p := app.bot_data.get('db_pool'): await p.close()
239
  for r in app.bot_data.get('redis_clients', []): await r.close()
240
 
241
+ # --- ৭. প্রধান ফাংশন ---
242
  def main():
243
  if not BOT_TOKEN: return
244
  app = Application.builder().token(BOT_TOKEN).post_init(post_init).post_stop(post_stop).build()
245
  app.add_error_handler(global_error_handler)
246
 
 
247
  from bot_handlers import admin_commands as ac
248
  from bot_handlers import extra_commands as ec
249
  from bot_handlers import owner_commands as oc
250
 
 
251
  app.add_handler(CommandHandler("start", safe_start_command))
252
  app.add_handler(CommandHandler("grant", ac.vip_trial_command))
253
  app.add_handler(CommandHandler("whois", ac.whois_command))
 
257
  app.add_handler(CommandHandler("delword", ac.del_word_command))
258
  app.add_handler(CommandHandler("wordlist", ac.wordlist_command))
259
  app.add_handler(CommandHandler("resetsettings", ac.reset_settings_command))
 
 
260
  app.add_handler(CommandHandler("filter", ec.filter_command))
261
  app.add_handler(CommandHandler("stop", ec.stop_filter_command))
262
  app.add_handler(CommandHandler("save", ec.save_note_command))
 
279
  app.add_handler(CommandHandler("ticket", ec.ticket_command))
280
  app.add_handler(CommandHandler("trustscore", ec.trustscore_command))
281
  app.add_handler(CommandHandler("fixdb", ec.fix_database_command))
 
 
282
  app.add_handler(CommandHandler("broadcast", oc.broadcast_command))
283
  app.add_handler(CommandHandler("bc", oc.broadcast_groups_command))
284
  app.add_handler(CommandHandler("stats", oc.stats_command))
 
290
  app.add_handler(CommandHandler("sdel", oc.sdel_command))
291
  app.add_handler(CommandHandler("smute", oc.smute_command))
292
 
 
293
  app.add_handler(CallbackQueryHandler(w_callback))
294
  app.add_handler(ChatJoinRequestHandler(handle_join_request))
295
  app.add_handler(MessageHandler(filters.ALL & ~filters.COMMAND, w_msg))
 
297
  app.add_handler(ChatMemberHandler(w_bot_status, ChatMemberHandler.MY_CHAT_MEMBER))
298
  app.add_handler(ChatMemberHandler(w_member_status, ChatMemberHandler.CHAT_MEMBER))
299
 
 
300
  threading.Thread(target=run_web_server, daemon=True).start()
 
 
301
  logger.info("Bot is polling silently...")
302
  app.run_polling(allowed_updates=["message", "callback_query", "chat_member", "my_chat_member", "chat_join_request", "edited_message"])
303