forked from VJBots/VJ-FILTER-BOT
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathadmin_commands.py
More file actions
377 lines (321 loc) · 14 KB
/
admin_commands.py
File metadata and controls
377 lines (321 loc) · 14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
import os
import asyncio
from pyrogram import Client, filters
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, Message, CallbackQuery
from info import ADMINS, REQUEST_CHANNELS, LOG_CHANNEL
from database.users_chats_db import db
from datetime import datetime
# ==================== ADMIN PANEL ====================
@Client.on_message(filters.command("admin") & filters.user(ADMINS))
async def admin_panel(client, message):
keyboard = InlineKeyboardMarkup([
[InlineKeyboardButton("📊 Stats", callback_data="admin_stats"),
InlineKeyboardButton("👥 Users", callback_data="admin_users")],
[InlineKeyboardButton("📢 Broadcast", callback_data="admin_broadcast"),
InlineKeyboardButton("🚫 Ban/Unban", callback_data="admin_ban")],
[InlineKeyboardButton("📁 Channels", callback_data="admin_channels"),
InlineKeyboardButton("🖼️ Images", callback_data="admin_images")],
[InlineKeyboardButton("⚙️ Settings", callback_data="admin_settings"),
InlineKeyboardButton("📝 Logs", callback_data="admin_logs")]
])
await message.reply_photo(
photo="https://graph.org/file/ce1723991756e48c35aa1.jpg",
caption="**🤖 ADMIN CONTROL PANEL**\n\n"
"Select an option to manage your bot:",
reply_markup=keyboard
)
# ==================== STATS ====================
@Client.on_callback_query(filters.regex("admin_stats"))
async def admin_stats(client, callback_query):
try:
total_users = await db.total_users_count()
total_chats = await db.total_chat_count()
b_users, b_chats = await db.get_banned()
stats_text = f"""
📊 **BOT STATISTICS**
👥 **Total Users:** `{total_users}`
💬 **Total Chats:** `{total_chats}`
🚫 **Banned Users:** `{len(b_users)}`
🚫 **Banned Chats:** `{len(b_chats)}`
📅 **Last Updated:** `{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}`
🤖 **Bot Info:**
├ ID: `{client.me.id}`
├ Name: {client.me.first_name}
└ Username: @{client.me.username}
"""
await callback_query.message.edit_caption(
caption=stats_text,
reply_markup=InlineKeyboardMarkup([
[InlineKeyboardButton("🔄 Refresh", callback_data="admin_stats"),
InlineKeyboardButton("📤 Export", callback_data="export_stats")],
[InlineKeyboardButton("🔙 Back", callback_data="admin_back")]
])
)
except Exception as e:
await callback_query.message.edit_caption(f"Error: {str(e)}")
# ==================== BROADCAST WITH IMAGE ====================
@Client.on_callback_query(filters.regex("admin_broadcast"))
async def admin_broadcast_menu(client, callback_query):
keyboard = InlineKeyboardMarkup([
[InlineKeyboardButton("📝 Text Only", callback_data="broadcast_text"),
InlineKeyboardButton("🖼️ With Image", callback_data="broadcast_image")],
[InlineKeyboardButton("🔙 Back", callback_data="admin_back")]
])
await callback_query.message.edit_caption(
caption="**📢 BROADCAST MESSAGE**\n\n"
"Choose broadcast type:\n"
"• **Text Only** - Send text message\n"
"• **With Image** - Send image with caption\n\n"
"⚠️ This will send to ALL users.",
reply_markup=keyboard
)
@Client.on_callback_query(filters.regex("broadcast_image"))
async def broadcast_image_start(client, callback_query):
await callback_query.message.edit_caption(
caption="**🖼️ BROADCAST WITH IMAGE**\n\n"
"Send me the image first, then send the caption.\n\n"
"Format:\n"
"1. Send image (as photo)\n"
"2. Send caption text\n\n"
"Type /cancel to stop.",
reply_markup=InlineKeyboardMarkup([
[InlineKeyboardButton("❌ Cancel", callback_data="admin_broadcast")]
])
)
# Store state
user_id = callback_query.from_user.id
broadcast_data[user_id] = {"type": "image", "step": 1}
# Global dictionary to store broadcast data
broadcast_data = {}
@Client.on_message(filters.photo & filters.user(ADMINS))
async def receive_broadcast_image(client, message):
user_id = message.from_user.id
if user_id in broadcast_data and broadcast_data[user_id]["type"] == "image" and broadcast_data[user_id]["step"] == 1:
# Store image
broadcast_data[user_id]["photo"] = message.photo.file_id
broadcast_data[user_id]["step"] = 2
await message.reply_text(
"✅ Image received!\n\n"
"Now send me the caption/text for this image.\n"
"Type /cancel to stop."
)
@Client.on_message(filters.text & filters.user(ADMINS))
async def receive_broadcast_caption(client, message):
user_id = message.from_user.id
if message.text == "/cancel":
if user_id in broadcast_data:
del broadcast_data[user_id]
await message.reply_text("❌ Broadcast cancelled.")
return
if user_id in broadcast_data and broadcast_data[user_id]["type"] == "image" and broadcast_data[user_id]["step"] == 2:
caption = message.text
photo = broadcast_data[user_id].get("photo")
if not photo:
await message.reply_text("❌ No image found. Please start again.")
return
# Confirm broadcast
keyboard = InlineKeyboardMarkup([
[InlineKeyboardButton("✅ Yes, Send", callback_data=f"confirm_broadcast_image_{user_id}"),
InlineKeyboardButton("❌ Cancel", callback_data="cancel_broadcast")]
])
# Preview
await message.reply_photo(
photo=photo,
caption=f"📢 **BROADCAST PREVIEW**\n\n{caption}\n\n"
f"**Send this to all users?**\n"
f"Estimated users: {await db.total_users_count()}",
reply_markup=keyboard
)
# Store final data
broadcast_data[user_id]["caption"] = caption
@Client.on_callback_query(filters.regex(r"^confirm_broadcast_image_"))
async def confirm_broadcast_image(client, callback_query):
user_id = int(callback_query.data.split("_")[-1])
if user_id not in broadcast_data:
await callback_query.message.edit_caption("❌ Broadcast data not found.")
return
data = broadcast_data[user_id]
photo = data.get("photo")
caption = data.get("caption")
if not photo or not caption:
await callback_query.message.edit_caption("❌ Missing image or caption.")
return
# Start broadcasting
users = await db.get_all_users()
total = len(users)
success = 0
failed = 0
progress_msg = await callback_query.message.edit_caption(
f"📤 **Broadcasting Started...**\n\n"
f"Progress: 0/{total}\n"
f"✅ Success: 0\n"
f"❌ Failed: 0"
)
for i, user in enumerate(users):
try:
await client.send_photo(
chat_id=int(user['id']),
photo=photo,
caption=caption
)
success += 1
except Exception as e:
failed += 1
# Update progress every 10 users
if (i + 1) % 10 == 0 or (i + 1) == total:
await progress_msg.edit_caption(
f"📤 **Broadcasting...**\n\n"
f"Progress: {i+1}/{total}\n"
f"✅ Success: {success}\n"
f"❌ Failed: {failed}"
)
# Final result
await progress_msg.edit_caption(
f"✅ **BROADCAST COMPLETE!**\n\n"
f"📊 **Results:**\n"
f"• Total Users: {total}\n"
f"• ✅ Success: {success}\n"
f"• ❌ Failed: {failed}\n\n"
f"📅 {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
)
# Cleanup
if user_id in broadcast_data:
del broadcast_data[user_id]
# Log to LOG_CHANNEL
try:
await client.send_message(
LOG_CHANNEL,
f"📢 **Broadcast Sent**\n\n"
f"👤 Admin: {callback_query.from_user.mention}\n"
f"👥 Total: {total}\n"
f"✅ Success: {success}\n"
f"❌ Failed: {failed}\n"
f"🕐 Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
)
except:
pass
# ==================== MANAGE CHANNELS ====================
@Client.on_callback_query(filters.regex("admin_channels"))
async def admin_channels(client, callback_query):
from info import CHANNELS, REQUEST_CHANNELS
channels_text = "**📁 MANAGED CHANNELS**\n\n"
channels_text += "**📢 File Channels:**\n"
for i, ch in enumerate(CHANNELS, 1):
try:
chat = await client.get_chat(ch)
channels_text += f"{i}. {chat.title} (ID: `{ch}`)\n"
except:
channels_text += f"{i}. Channel ID: `{ch}`\n"
channels_text += "\n**🔐 Request-to-Join Channels:**\n"
if REQUEST_CHANNELS:
for i, ch in enumerate(REQUEST_CHANNELS, 1):
try:
chat = await client.get_chat(ch)
channels_text += f"{i}. {chat.title} (ID: `{ch}`)\n"
except:
channels_text += f"{i}. Channel ID: `{ch}`\n"
else:
channels_text += "No channels set\n"
keyboard = InlineKeyboardMarkup([
[InlineKeyboardButton("➕ Add Channel", callback_data="add_channel"),
InlineKeyboardButton("➖ Remove Channel", callback_data="remove_channel")],
[InlineKeyboardButton("🔄 Refresh", callback_data="admin_channels"),
InlineKeyboardButton("🔙 Back", callback_data="admin_back")]
])
await callback_query.message.edit_caption(
caption=channels_text,
reply_markup=keyboard
)
# ==================== MANAGE IMAGES ====================
@Client.on_callback_query(filters.regex("admin_images"))
async def admin_images(client, callback_query):
keyboard = InlineKeyboardMarkup([
[InlineKeyboardButton("👋 Welcome Image", callback_data="set_welcome_image"),
InlineKeyboardButton("📢 Broadcast Image", callback_data="set_broadcast_image")],
[InlineKeyboardButton("🔗 Link Image", callback_data="set_link_image"),
InlineKeyboardButton("📸 View Images", callback_data="view_images")],
[InlineKeyboardButton("🔙 Back", callback_data="admin_back")]
])
await callback_query.message.edit_caption(
caption="**🖼️ MANAGE IMAGES**\n\n"
"Set custom images for:\n"
"• **Welcome Image** - Shown on /start command\n"
"• **Broadcast Image** - Default for broadcasts\n"
"• **Link Image** - For link messages\n\n"
"Current default: [Graph Image]",
reply_markup=keyboard
)
@Client.on_callback_query(filters.regex("set_welcome_image"))
async def set_welcome_image(client, callback_query):
await callback_query.message.edit_caption(
caption="**👋 SET WELCOME IMAGE**\n\n"
"Send me the new welcome image (as photo).\n"
"This will be shown when users use /start command.\n\n"
"⚠️ Send as photo, not document.",
reply_markup=InlineKeyboardMarkup([
[InlineKeyboardButton("❌ Cancel", callback_data="admin_images")]
])
)
# Set state
user_id = callback_query.from_user.id
image_settings[user_id] = {"type": "welcome"}
# Store image settings
image_settings = {}
@Client.on_message(filters.photo & filters.user(ADMINS))
async def save_custom_image(client, message):
user_id = message.from_user.id
if user_id in image_settings:
image_type = image_settings[user_id]["type"]
file_id = message.photo.file_id
# Save to database or file
# For now, we'll just save to a variable
if image_type == "welcome":
# Save to database or config
await message.reply_text(
f"✅ **Welcome Image Updated!**\n\n"
f"New welcome image has been set.\n"
f"File ID: `{file_id}`\n\n"
f"Test with /start command."
)
elif image_type == "broadcast":
await message.reply_text(
f"✅ **Broadcast Image Updated!**\n\n"
f"New broadcast image has been set."
)
# Clear state
del image_settings[user_id]
# ==================== BACK BUTTON ====================
@Client.on_callback_query(filters.regex("admin_back"))
async def admin_back(client, callback_query):
await admin_panel(client, callback_query.message)
# ==================== QUICK COMMANDS ====================
@Client.on_message(filters.command("broadcast") & filters.user(ADMINS))
async def quick_broadcast(client, message):
if len(message.command) < 2:
await message.reply_text("**Usage:**\n`/broadcast your message`\n`/broadcast_image`")
return
text = message.text.split(None, 1)[1]
keyboard = InlineKeyboardMarkup([
[InlineKeyboardButton("✅ Text Only", callback_data=f"quick_broadcast_text_{message.from_user.id}"),
InlineKeyboardButton("🖼️ With Image", callback_data="broadcast_image")],
[InlineKeyboardButton("❌ Cancel", callback_data="cancel")]
])
await message.reply_text(
f"📢 **Broadcast Preview:**\n\n{text}\n\n"
f"Send to all users?",
reply_markup=keyboard
)
# Export users command
@Client.on_message(filters.command("export") & filters.user(ADMINS))
async def export_users(client, message):
users = await db.get_all_users()
with open('users_list.txt', 'w') as f:
f.write("ID | Name | Date\n")
f.write("-" * 50 + "\n")
for user in users:
f.write(f"{user['id']} | {user.get('name', 'N/A')} | {user.get('date', 'N/A')}\n")
await message.reply_document(
'users_list.txt',
caption=f"📊 **Users Export**\nTotal Users: {len(users)}"
)
os.remove('users_list.txt')