🩵 Thanks for Being Here 🩵
8 | 9 | 10 | ### CONFIGS VARIABLES 11 | 12 | * `BOT_TOKEN` - Get bot token from Bot Father 13 | * `API_ID` - Get api id from Telegram Auth 14 | * `API_HASH` - Get api hash from Telegram Auth 15 | * `OWNER_ID` - Bot admin/owner user id. 16 | * `DATABASE_URI` - Mongo Database URL from Mongo DB 17 | * `DATABASE_NAME` - Your database name from mongoDB. (Optional) 18 | * `BOT_SESSION` - Your Bot session name. (Optional) 19 | 20 | 21 | 22 | ### DEPLOYEMENT SUPPORT 23 | 24 |
26 |
27 |
28 |
29 |
30 |
34 |
35 |
36 |
37 |
38 |
madflixofficial@axl
"
48 | keybord = InlineKeyboardMarkup([
49 | [InlineKeyboardButton("🦋 Admin",url = "https://t.me/CallAdminRobot"),
50 | InlineKeyboardButton("✖️ Close",callback_data = "close_btn") ]])
51 | await message.reply_text(text = text,reply_markup = keybord)
52 |
53 |
54 |
55 |
56 |
57 |
58 | # Jishu Developer
59 | # Don't Remove Credit 🥺
60 | # Telegram Channel @Madflix_Bots
61 | # Backup Channel @JishuBotz
62 | # Developer @JishuDeveloper
63 |
--------------------------------------------------------------------------------
/plugins/broadcast.py:
--------------------------------------------------------------------------------
1 | # Jishu Developer
2 | # Don't Remove Credit 🥺
3 | # Telegram Channel @Madflix_Bots
4 | # Backup Channel @JishuBotz
5 | # Developer @JishuDeveloper
6 |
7 |
8 |
9 |
10 | import asyncio
11 | import time, datetime
12 | from database import db
13 | from config import Config
14 | from pyrogram import Client, filters
15 | from pyrogram.errors import InputUserDeactivated, FloodWait, UserIsBlocked
16 |
17 |
18 |
19 | @Client.on_message(filters.command(["broadcast", "b"]) & filters.user(Config.OWNER_ID) & filters.reply)
20 | async def broadcast (bot, message):
21 | users = await db.get_all_users()
22 | b_msg = message.reply_to_message
23 | sts = await message.reply_text(
24 | text='Broadcasting Your Messages...'
25 | )
26 | start_time = time.time()
27 | total_users, k = await db.total_users_bots_count()
28 | done = 0
29 | blocked = 0
30 | deleted = 0
31 | failed = 0
32 | success = 0
33 | async for user in users:
34 | pti, sh = await broadcast_messages(int(user['id']), b_msg, bot.log)
35 | if pti:
36 | success += 1
37 | await asyncio.sleep(2)
38 | elif pti == False:
39 | if sh == "Blocked":
40 | blocked+=1
41 | elif sh == "Deleted":
42 | deleted += 1
43 | elif sh == "Error":
44 | failed += 1
45 | done += 1
46 | if not done % 20:
47 | await sts.edit(f"Broadcast In Progress :\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nBlocked: {blocked}\nDeleted: {deleted}")
48 | time_taken = datetime.timedelta(seconds=int(time.time()-start_time))
49 | await sts.edit(f"Broadcast Completed :\n\nCompleted in {time_taken} seconds.\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nBlocked: {blocked}\nDeleted: {deleted}")
50 |
51 | async def broadcast_messages(user_id, message, log):
52 | try:
53 | await message.copy(chat_id=user_id)
54 | return True, "Success"
55 | except FloodWait as e:
56 | await asyncio.sleep(e.x)
57 | return await broadcast_messages(user_id, message, log)
58 | except InputUserDeactivated:
59 | await db.delete_user(int(user_id))
60 | log.info(f"{user_id}-Removed from Database, since deleted account.")
61 | return False, "Deleted"
62 | except UserIsBlocked:
63 | log.info(f"{user_id} -Blocked the bot.")
64 | return False, "Blocked"
65 | except Exception as e:
66 | return False, "Error"
67 |
68 |
69 |
70 |
71 |
72 |
73 | # Jishu Developer
74 | # Don't Remove Credit 🥺
75 | # Telegram Channel @Madflix_Bots
76 | # Backup Channel @JishuBotz
77 | # Developer @JishuDeveloper
--------------------------------------------------------------------------------
/plugins/commands.py:
--------------------------------------------------------------------------------
1 | # Jishu Developer
2 | # Don't Remove Credit 🥺
3 | # Telegram Channel @Madflix_Bots
4 | # Backup Channel @JishuBotz
5 | # Developer @JishuDeveloper
6 |
7 |
8 |
9 |
10 | import os
11 | import sys
12 | import asyncio
13 | from database import db, mongodb_version
14 | from config import Config, temp
15 | from platform import python_version
16 | from translation import Translation
17 | from pyrogram import Client, filters, enums, __version__ as pyrogram_version
18 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, InputMediaDocument
19 |
20 | main_buttons = [[
21 | InlineKeyboardButton('📢 Updates', url='https://t.me/Madflix_Bots'),
22 | InlineKeyboardButton('💬 Support', url='https://t.me/MadflixBots_Support')
23 | ],[
24 | InlineKeyboardButton('🛠️ Help', callback_data='help'),
25 | InlineKeyboardButton('🩷 About', callback_data='about')
26 | ],[
27 | InlineKeyboardButton('🧑💻 Developer 🧑💻', url='https://t.me/CallAdminRobot')
28 | ]]
29 |
30 |
31 |
32 | #===================Start Function===================#
33 |
34 | @Client.on_message(filters.private & filters.command(['start']))
35 | async def start(client, message):
36 | user = message.from_user
37 | if not await db.is_user_exist(user.id):
38 | await db.add_user(user.id, user.first_name)
39 | reply_markup = InlineKeyboardMarkup(main_buttons)
40 | jishubotz = await message.reply_sticker("CAACAgUAAxkBAAECEEBlLA-nYcsWmsNWgE8-xqIkriCWAgACJwEAAsiUZBTiPWKAkUSmmh4E")
41 | await asyncio.sleep(2)
42 | await jishubotz.delete()
43 | text=Translation.START_TXT.format(user.mention)
44 | await message.reply_text(
45 | text=text,
46 | reply_markup=reply_markup,
47 | quote=True
48 | )
49 |
50 |
51 |
52 | #==================Restart Function==================#
53 |
54 | @Client.on_message(filters.private & filters.command(['restart', "r"]) & filters.user(Config.OWNER_ID))
55 | async def restart(client, message):
56 | msg = await message.reply_text(
57 | text="Trying To Restarting.....",
58 | quote=True
59 | )
60 | await asyncio.sleep(5)
61 | await msg.edit("Server Restarted Successfully ✅")
62 | os.execl(sys.executable, sys.executable, *sys.argv)
63 |
64 |
65 |
66 | #==================Callback Functions==================#
67 |
68 | @Client.on_callback_query(filters.regex(r'^help'))
69 | async def helpcb(bot, query):
70 | await query.message.edit_text(
71 | text=Translation.HELP_TXT,
72 | reply_markup=InlineKeyboardMarkup(
73 | [[
74 | InlineKeyboardButton('🛠️ How To Use Me 🛠️', callback_data='how_to_use')
75 | ],[
76 | InlineKeyboardButton('⚙️ Settings ⚙️', callback_data='settings#main'),
77 | InlineKeyboardButton('📊 Stats 📊', callback_data='status')
78 | ],[
79 | InlineKeyboardButton('🔙 Back', callback_data='back')
80 | ]]
81 | ))
82 |
83 |
84 |
85 | @Client.on_callback_query(filters.regex(r'^how_to_use'))
86 | async def how_to_use(bot, query):
87 | await query.message.edit_text(
88 | text=Translation.HOW_USE_TXT,
89 | reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton('🔙 Back', callback_data='help')]]),
90 | disable_web_page_preview=True
91 | )
92 |
93 |
94 |
95 | @Client.on_callback_query(filters.regex(r'^back'))
96 | async def back(bot, query):
97 | reply_markup = InlineKeyboardMarkup(main_buttons)
98 | await query.message.edit_text(
99 | reply_markup=reply_markup,
100 | text=Translation.START_TXT.format(
101 | query.from_user.first_name))
102 |
103 |
104 |
105 | @Client.on_callback_query(filters.regex(r'^about'))
106 | async def about(bot, query):
107 | await query.message.edit_text(
108 | text=Translation.ABOUT_TXT.format(bot.me.mention),
109 | reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton('🔙 Back', callback_data='back')]]),
110 | disable_web_page_preview=True,
111 | parse_mode=enums.ParseMode.HTML,
112 | )
113 |
114 |
115 |
116 | @Client.on_callback_query(filters.regex(r'^status'))
117 | async def status(bot, query):
118 | users_count, bots_count = await db.total_users_bots_count()
119 | total_channels = await db.total_channels()
120 | await query.message.edit_text(
121 | text=Translation.STATUS_TXT.format(users_count, bots_count, temp.forwardings, total_channels, temp.BANNED_USERS ),
122 | reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton('🔙 Back', callback_data='help')]]),
123 | parse_mode=enums.ParseMode.HTML,
124 | disable_web_page_preview=True,
125 | )
126 |
127 |
128 |
129 |
130 |
131 |
132 | # Jishu Developer
133 | # Don't Remove Credit 🥺
134 | # Telegram Channel @Madflix_Bots
135 | # Backup Channel @JishuBotz
136 | # Developer @JishuDeveloper
--------------------------------------------------------------------------------
/plugins/public.py:
--------------------------------------------------------------------------------
1 | # Jishu Developer
2 | # Don't Remove Credit 🥺
3 | # Telegram Channel @Madflix_Bots
4 | # Backup Channel @JishuBotz
5 | # Developer @JishuDeveloper
6 |
7 |
8 |
9 |
10 |
11 | import re
12 | import asyncio
13 | from .utils import STS
14 | from database import db
15 | from config import temp
16 | from translation import Translation
17 | from pyrogram import Client, filters, enums
18 | from pyrogram.errors import FloodWait
19 | from pyrogram.errors.exceptions.not_acceptable_406 import ChannelPrivate as PrivateChat
20 | from pyrogram.errors.exceptions.bad_request_400 import ChannelInvalid, ChatAdminRequired, UsernameInvalid, UsernameNotModified, ChannelPrivate
21 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, CallbackQuery, KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove
22 |
23 |
24 |
25 |
26 | #===================Run Function===================#
27 |
28 | @Client.on_message(filters.private & filters.command(["fwd", "forward"]))
29 | async def run(bot, message):
30 | buttons = []
31 | btn_data = {}
32 | user_id = message.from_user.id
33 | _bot = await db.get_bot(user_id)
34 | if not _bot:
35 | return await message.reply("You Did Not Added Any Bot. Please Add A Bot Using /settings !")
36 | channels = await db.get_user_channels(user_id)
37 | if not channels:
38 | return await message.reply_text("Please Set A To Channel In /settings Before Forwarding")
39 | if len(channels) > 1:
40 | for channel in channels:
41 | buttons.append([KeyboardButton(f"{channel['title']}")])
42 | btn_data[channel['title']] = channel['chat_id']
43 | buttons.append([KeyboardButton("cancel")])
44 | _toid = await bot.ask(message.chat.id, Translation.TO_MSG.format(_bot['name'], _bot['username']), reply_markup=ReplyKeyboardMarkup(buttons, one_time_keyboard=True, resize_keyboard=True))
45 | if _toid.text.startswith(('/', 'cancel')):
46 | return await message.reply_text(Translation.CANCEL, reply_markup=ReplyKeyboardRemove())
47 | to_title = _toid.text
48 | toid = btn_data.get(to_title)
49 | if not toid:
50 | return await message.reply_text("Wrong Channel Choosen !", reply_markup=ReplyKeyboardRemove())
51 | else:
52 | toid = channels[0]['chat_id']
53 | to_title = channels[0]['title']
54 | fromid = await bot.ask(message.chat.id, Translation.FROM_MSG, reply_markup=ReplyKeyboardRemove())
55 | if fromid.text and fromid.text.startswith('/'):
56 | await message.reply(Translation.CANCEL)
57 | return
58 | if fromid.text and not fromid.forward_date:
59 | regex = re.compile(r"(https://)?(t\.me/|telegram\.me/|telegram\.dog/)(c/)?(\d+|[a-zA-Z_0-9]+)/(\d+)$")
60 | match = regex.match(fromid.text.replace("?single", ""))
61 | if not match:
62 | return await message.reply('Invalid Link')
63 | chat_id = match.group(4)
64 | last_msg_id = int(match.group(5))
65 | if chat_id.isnumeric():
66 | chat_id = int(("-100" + chat_id))
67 | elif fromid.forward_from_chat.type in [enums.ChatType.CHANNEL]:
68 | last_msg_id = fromid.forward_from_message_id
69 | chat_id = fromid.forward_from_chat.username or fromid.forward_from_chat.id
70 | if last_msg_id == None:
71 | return await message.reply_text("This May Be A Forwarded Message From A Group And Sended By Anonymous Admin. Instead Of This Please Send Last Message Link From Group")
72 | else:
73 | await message.reply_text("Invalid !")
74 | return
75 | try:
76 | title = (await bot.get_chat(chat_id)).title
77 | # except ChannelInvalid:
78 | #return await fromid.reply("**Given source chat is copyrighted channel/group. you can't forward messages from there**")
79 | except (PrivateChat, ChannelPrivate, ChannelInvalid):
80 | title = "private" if fromid.text else fromid.forward_from_chat.title
81 | except (UsernameInvalid, UsernameNotModified):
82 | return await message.reply('Invalid Link Specified.')
83 | except Exception as e:
84 | return await message.reply(f'Errors - {e}')
85 | skipno = await bot.ask(message.chat.id, Translation.SKIP_MSG)
86 | if skipno.text.startswith('/'):
87 | await message.reply(Translation.CANCEL)
88 | return
89 | forward_id = f"{user_id}-{skipno.id}"
90 | buttons = [[
91 | InlineKeyboardButton('Yes', callback_data=f"start_public_{forward_id}"),
92 | InlineKeyboardButton('No', callback_data="close_btn")
93 | ]]
94 | reply_markup = InlineKeyboardMarkup(buttons)
95 | await message.reply_text(
96 | text=Translation.DOUBLE_CHECK.format(botname=_bot['name'], botuname=_bot['username'], from_chat=title, to_chat=to_title, skip=skipno.text),
97 | disable_web_page_preview=True,
98 | reply_markup=reply_markup
99 | )
100 | STS(forward_id).store(chat_id, toid, int(skipno.text), int(last_msg_id))
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 | # Jishu Developer
109 | # Don't Remove Credit 🥺
110 | # Telegram Channel @Madflix_Bots
111 | # Backup Channel @JishuBotz
112 | # Developer @JishuDeveloper
--------------------------------------------------------------------------------
/plugins/regix.py:
--------------------------------------------------------------------------------
1 | # Jishu Developer
2 | # Don't Remove Credit 🥺
3 | # Telegram Channel @Madflix_Bots
4 | # Backup Channel @JishuBotz
5 | # Developer @JishuDeveloper
6 |
7 |
8 |
9 |
10 | import os
11 | import sys
12 | import math
13 | import time
14 | import asyncio
15 | import logging
16 | from .utils import STS
17 | from database import db
18 | from .test import CLIENT , start_clone_bot
19 | from config import Config, temp
20 | from translation import Translation
21 | from pyrogram import Client, filters
22 | #from pyropatch.utils import unpack_new_file_id
23 | from pyrogram.errors import FloodWait, MessageNotModified, RPCError
24 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, CallbackQuery, Message
25 |
26 | CLIENT = CLIENT()
27 | logger = logging.getLogger(__name__)
28 | logger.setLevel(logging.INFO)
29 | TEXT = Translation.TEXT
30 |
31 |
32 |
33 |
34 |
35 | @Client.on_callback_query(filters.regex(r'^start_public'))
36 | async def pub_(bot, message):
37 | user = message.from_user.id
38 | temp.CANCEL[user] = False
39 | frwd_id = message.data.split("_")[2]
40 | if temp.lock.get(user) and str(temp.lock.get(user))=="True":
41 | return await message.answer("Please Wait Until Previous Task Complete", show_alert=True)
42 | sts = STS(frwd_id)
43 | if not sts.verify():
44 | await message.answer("Your Are Clicking On My Old Button", show_alert=True)
45 | return await message.message.delete()
46 | i = sts.get(full=True)
47 | if i.TO in temp.IS_FRWD_CHAT:
48 | return await message.answer("In Target Chat A Task Is Progressing. Please Wait Until Task Complete", show_alert=True)
49 | m = await msg_edit(message.message, "Verifying Your Data's, Please Wait.")
50 | _bot, caption, forward_tag, data, protect, button = await sts.get_data(user)
51 | if not _bot:
52 | return await msg_edit(m, "You Didn't Added Any Bot. Please Add A Bot Using /settings !", wait=True)
53 | try:
54 | client = await start_clone_bot(CLIENT.client(_bot))
55 | except Exception as e:
56 | return await m.edit(e)
57 | await msg_edit(m, "Processing...")
58 | try:
59 | await client.get_messages(sts.get("FROM"), sts.get("limit"))
60 | except:
61 | await msg_edit(m, f"Source Chat May Be A Private Channel / Group. Use Userbot (User Must Be Member Over There) Or If Make Your [Bot](t.me/{_bot['username']}) An Admin Over There", retry_btn(frwd_id), True)
62 | return await stop(client, user)
63 | try:
64 | k = await client.send_message(i.TO, "Testing")
65 | await k.delete()
66 | except:
67 | await msg_edit(m, f"Please Make Your [UserBot / Bot](t.me/{_bot['username']}) Admin In Target Channel With Full Permissions", retry_btn(frwd_id), True)
68 | return await stop(client, user)
69 | temp.forwardings += 1
70 | await db.add_frwd(user)
71 | await send(client, user, "🩷 Forwarding Started")
72 | sts.add(time=True)
73 | sleep = 1 if _bot['is_bot'] else 10
74 | await msg_edit(m, "Processing...")
75 | temp.IS_FRWD_CHAT.append(i.TO)
76 | temp.lock[user] = locked = True
77 | if locked:
78 | try:
79 | MSG = []
80 | pling=0
81 | await edit(m, 'Progressing', 10, sts)
82 | print(f"Starting Forwarding Process... From :{sts.get('FROM')} To: {sts.get('TO')} Totel: {sts.get('limit')} Stats : {sts.get('skip')})")
83 | async for message in client.iter_messages(
84 | client,
85 | chat_id=sts.get('FROM'),
86 | limit=int(sts.get('limit')),
87 | offset=int(sts.get('skip')) if sts.get('skip') else 0
88 | ):
89 | if await is_cancelled(client, user, m, sts):
90 | return
91 | if pling %20 == 0:
92 | await edit(m, 'Progressing', 10, sts)
93 | pling += 1
94 | sts.add('fetched')
95 | if message == "DUPLICATE":
96 | sts.add('duplicate')
97 | continue
98 | elif message == "FILTERED":
99 | sts.add('filtered')
100 | continue
101 | if message.empty or message.service:
102 | sts.add('deleted')
103 | continue
104 | if forward_tag:
105 | MSG.append(message.id)
106 | notcompleted = len(MSG)
107 | completed = sts.get('total') - sts.get('fetched')
108 | if ( notcompleted >= 100
109 | or completed <= 100):
110 | await forward(client, MSG, m, sts, protect)
111 | sts.add('total_files', notcompleted)
112 | await asyncio.sleep(10)
113 | MSG = []
114 | else:
115 | new_caption = custom_caption(message, caption)
116 | details = {"msg_id": message.id, "media": media(message), "caption": new_caption, 'button': button, "protect": protect}
117 | await copy(client, details, m, sts)
118 | sts.add('total_files')
119 | await asyncio.sleep(sleep)
120 | except Exception as e:
121 | await msg_edit(m, f'Error :\n{e}
', wait=True)
122 | temp.IS_FRWD_CHAT.remove(sts.TO)
123 | return await stop(client, user)
124 | temp.IS_FRWD_CHAT.remove(sts.TO)
125 | await send(client, user, "🎉 Forwarding Completed")
126 | await edit(m, 'Completed', "completed", sts)
127 | await stop(client, user)
128 |
129 | async def copy(bot, msg, m, sts):
130 | try:
131 | if msg.get("media") and msg.get("caption"):
132 | await bot.send_cached_media(
133 | chat_id=sts.get('TO'),
134 | file_id=msg.get("media"),
135 | caption=msg.get("caption"),
136 | reply_markup=msg.get('button'),
137 | protect_content=msg.get("protect"))
138 | else:
139 | await bot.copy_message(
140 | chat_id=sts.get('TO'),
141 | from_chat_id=sts.get('FROM'),
142 | caption=msg.get("caption"),
143 | message_id=msg.get("msg_id"),
144 | reply_markup=msg.get('button'),
145 | protect_content=msg.get("protect"))
146 | except FloodWait as e:
147 | await edit(m, 'Progressing', e.value, sts)
148 | await asyncio.sleep(e.value)
149 | await edit(m, 'Progressing', 10, sts)
150 | await copy(bot, msg, m, sts)
151 | except Exception as e:
152 | print(e)
153 | sts.add('deleted')
154 |
155 | async def forward(bot, msg, m, sts, protect):
156 | try:
157 | await bot.forward_messages(
158 | chat_id=sts.get('TO'),
159 | from_chat_id=sts.get('FROM'),
160 | protect_content=protect,
161 | message_ids=msg)
162 | except FloodWait as e:
163 | await edit(m, 'Progressing', e.value, sts)
164 | await asyncio.sleep(e.value)
165 | await edit(m, 'Progressing', 10, sts)
166 | await forward(bot, msg, m, sts, protect)
167 |
168 | PROGRESS = """
169 | 📈 Percetage : {0} %
170 |
171 | ♻️ Fetched : {1}
172 |
173 | 🔥 Forwarded : {2}
174 |
175 | 🫠 Remaining : {3}
176 |
177 | 📊 Status : {4}
178 |
179 | ⏳️ ETA : {5}
180 | """
181 |
182 | async def msg_edit(msg, text, button=None, wait=None):
183 | try:
184 | return await msg.edit(text, reply_markup=button)
185 | except MessageNotModified:
186 | pass
187 | except FloodWait as e:
188 | if wait:
189 | await asyncio.sleep(e.value)
190 | return await msg_edit(msg, text, button, wait)
191 |
192 | async def edit(msg, title, status, sts):
193 | i = sts.get(full=True)
194 | status = 'Forwarding' if status == 10 else f"Sleeping {status} s" if str(status).isnumeric() else status
195 | percentage = "{:.0f}".format(float(i.fetched)*100/float(i.total))
196 |
197 | now = time.time()
198 | diff = int(now - i.start)
199 | speed = sts.divide(i.fetched, diff)
200 | elapsed_time = round(diff) * 1000
201 | time_to_completion = round(sts.divide(i.total - i.fetched, int(speed))) * 1000
202 | estimated_total_time = elapsed_time + time_to_completion
203 | progress = "▰{0}{1}".format(
204 | ''.join(["▰" for i in range(math.floor(int(percentage) / 10))]),
205 | ''.join(["▱" for i in range(10 - math.floor(int(percentage) / 10))]))
206 | button = [[InlineKeyboardButton(title, f'fwrdstatus#{status}#{estimated_total_time}#{percentage}#{i.id}')]]
207 | estimated_total_time = TimeFormatter(milliseconds=estimated_total_time)
208 | estimated_total_time = estimated_total_time if estimated_total_time != '' else '0 s'
209 |
210 | text = TEXT.format(i.fetched, i.total_files, i.duplicate, i.deleted, i.skip, status, percentage, estimated_total_time, progress)
211 | if status in ["cancelled", "completed"]:
212 | button.append(
213 | [InlineKeyboardButton('📢 Updates', url='https://t.me/Madflix_Bots'),
214 | InlineKeyboardButton('💬 Support', url='https://t.me/MadflixBots_Support')]
215 | )
216 | else:
217 | button.append([InlineKeyboardButton('✖️ Cancel ✖️', 'terminate_frwd')])
218 | await msg_edit(msg, text, InlineKeyboardMarkup(button))
219 |
220 | async def is_cancelled(client, user, msg, sts):
221 | if temp.CANCEL.get(user)==True:
222 | temp.IS_FRWD_CHAT.remove(sts.TO)
223 | await edit(msg, "Cancelled", "completed", sts)
224 | await send(client, user, "❌ Forwarding Process Cancelled")
225 | await stop(client, user)
226 | return True
227 | return False
228 |
229 | async def stop(client, user):
230 | try:
231 | await client.stop()
232 | except:
233 | pass
234 | await db.rmve_frwd(user)
235 | temp.forwardings -= 1
236 | temp.lock[user] = False
237 |
238 | async def send(bot, user, text):
239 | try:
240 | await bot.send_message(user, text=text)
241 | except:
242 | pass
243 |
244 | def custom_caption(msg, caption):
245 | if msg.media:
246 | if (msg.video or msg.document or msg.audio or msg.photo):
247 | media = getattr(msg, msg.media.value, None)
248 | if media:
249 | file_name = getattr(media, 'file_name', '')
250 | file_size = getattr(media, 'file_size', '')
251 | fcaption = getattr(msg, 'caption', '')
252 | if fcaption:
253 | fcaption = fcaption.html
254 | if caption:
255 | return caption.format(filename=file_name, size=get_size(file_size), caption=fcaption)
256 | return fcaption
257 | return None
258 |
259 | def get_size(size):
260 | units = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB"]
261 | size = float(size)
262 | i = 0
263 | while size >= 1024.0 and i < len(units):
264 | i += 1
265 | size /= 1024.0
266 | return "%.2f %s" % (size, units[i])
267 |
268 | def media(msg):
269 | if msg.media:
270 | media = getattr(msg, msg.media.value, None)
271 | if media:
272 | return getattr(media, 'file_id', None)
273 | return None
274 |
275 | def TimeFormatter(milliseconds: int) -> str:
276 | seconds, milliseconds = divmod(int(milliseconds), 1000)
277 | minutes, seconds = divmod(seconds, 60)
278 | hours, minutes = divmod(minutes, 60)
279 | days, hours = divmod(hours, 24)
280 | tmp = ((str(days) + "d, ") if days else "") + \
281 | ((str(hours) + "h, ") if hours else "") + \
282 | ((str(minutes) + "m, ") if minutes else "") + \
283 | ((str(seconds) + "s, ") if seconds else "") + \
284 | ((str(milliseconds) + "ms, ") if milliseconds else "")
285 | return tmp[:-2]
286 |
287 | def retry_btn(id):
288 | return InlineKeyboardMarkup([[InlineKeyboardButton('♻️ Retry ♻️', f"start_public_{id}")]])
289 |
290 |
291 |
292 |
293 | @Client.on_callback_query(filters.regex(r'^terminate_frwd$'))
294 | async def terminate_frwding(bot, m):
295 | user_id = m.from_user.id
296 | temp.lock[user_id] = False
297 | temp.CANCEL[user_id] = True
298 | await m.answer("Forwarding Cancelled !", show_alert=True)
299 |
300 |
301 |
302 |
303 | @Client.on_callback_query(filters.regex(r'^fwrdstatus'))
304 | async def status_msg(bot, msg):
305 | _, status, est_time, percentage, frwd_id = msg.data.split("#")
306 | sts = STS(frwd_id)
307 | if not sts.verify():
308 | fetched, forwarded, remaining = 0
309 | else:
310 | fetched, forwarded = sts.get('fetched'), sts.get('total_files')
311 | remaining = fetched - forwarded
312 | est_time = TimeFormatter(milliseconds=est_time)
313 | est_time = est_time if (est_time != '' or status not in ['completed', 'cancelled']) else '0 s'
314 | return await msg.answer(PROGRESS.format(percentage, fetched, forwarded, remaining, status, est_time), show_alert=True)
315 |
316 |
317 |
318 |
319 | @Client.on_callback_query(filters.regex(r'^close_btn$'))
320 | async def close(bot, update):
321 | await update.answer()
322 | await update.message.delete()
323 | await update.message.reply_to_message.delete()
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 | # Jishu Developer
332 | # Don't Remove Credit 🥺
333 | # Telegram Channel @Madflix_Bots
334 | # Backup Channel @JishuBotz
335 | # Developer @JishuDeveloper
--------------------------------------------------------------------------------
/plugins/settings.py:
--------------------------------------------------------------------------------
1 | # Jishu Developer
2 | # Don't Remove Credit 🥺
3 | # Telegram Channel @Madflix_Bots
4 | # Backup Channel @JishuBotz
5 | # Developer @JishuDeveloper
6 |
7 |
8 |
9 |
10 | import asyncio
11 | from database import db
12 | from config import Config
13 | from translation import Translation
14 | from pyrogram import Client, filters
15 | from .test import get_configs, update_configs, CLIENT, parse_buttons
16 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
17 |
18 | CLIENT = CLIENT()
19 |
20 |
21 |
22 | @Client.on_message(filters.private & filters.command(['settings']))
23 | async def settings(client, message):
24 | text="Change Your Settings As Your Wish"
25 | await message.reply_text(
26 | text=text,
27 | reply_markup=main_buttons(),
28 | quote=True
29 | )
30 |
31 |
32 |
33 |
34 | @Client.on_callback_query(filters.regex(r'^settings'))
35 | async def settings_query(bot, query):
36 | user_id = query.from_user.id
37 | i, type = query.data.split("#")
38 | buttons = [[InlineKeyboardButton('🔙 Back', callback_data="settings#main")]]
39 |
40 | if type=="main":
41 | await query.message.edit_text(
42 | "Change Your Settings As Your Wish",
43 | reply_markup=main_buttons())
44 |
45 | elif type=="bots":
46 | buttons = []
47 | _bot = await db.get_bot(user_id)
48 | if _bot is not None:
49 | buttons.append([InlineKeyboardButton(_bot['name'],
50 | callback_data=f"settings#editbot")])
51 | else:
52 | buttons.append([InlineKeyboardButton('✚ Add Bot ✚',
53 | callback_data="settings#addbot")])
54 | buttons.append([InlineKeyboardButton('✚ Add User Bot ✚',
55 | callback_data="settings#adduserbot")])
56 | buttons.append([InlineKeyboardButton('🔙 Back',
57 | callback_data="settings#main")])
58 | await query.message.edit_text(
59 | "My Bots\n\nYou Can Manage Your Bots In Here",
60 | reply_markup=InlineKeyboardMarkup(buttons))
61 |
62 | elif type=="addbot":
63 | await query.message.delete()
64 | bot = await CLIENT.add_bot(bot, query)
65 | if bot != True: return
66 | await query.message.reply_text(
67 | "Bot Token Successfully Added To Database",
68 | reply_markup=InlineKeyboardMarkup(buttons))
69 |
70 | elif type=="adduserbot":
71 | await query.message.delete()
72 | user = await CLIENT.add_session(bot, query)
73 | if user != True: return
74 | await query.message.reply_text(
75 | "Session Successfully Added To Database",
76 | reply_markup=InlineKeyboardMarkup(buttons))
77 |
78 | elif type=="channels":
79 | buttons = []
80 | channels = await db.get_user_channels(user_id)
81 | for channel in channels:
82 | buttons.append([InlineKeyboardButton(f"{channel['title']}",
83 | callback_data=f"settings#editchannels_{channel['chat_id']}")])
84 | buttons.append([InlineKeyboardButton('✚ Add Channel ✚',
85 | callback_data="settings#addchannel")])
86 | buttons.append([InlineKeyboardButton('🔙 Back',
87 | callback_data="settings#main")])
88 | await query.message.edit_text(
89 | "My Channels\n\nYou Can Manage Your Target Chats In Here",
90 | reply_markup=InlineKeyboardMarkup(buttons))
91 |
92 | elif type=="addchannel":
93 | await query.message.delete()
94 | try:
95 | text = await bot.send_message(user_id, "Set Target Chat\n\nForward A Message From Your Target Chat\n/cancel - To Cancel This Process")
96 | chat_ids = await bot.listen(chat_id=user_id, timeout=300)
97 | if chat_ids.text=="/cancel":
98 | await chat_ids.delete()
99 | return await text.edit_text(
100 | "Process Canceled",
101 | reply_markup=InlineKeyboardMarkup(buttons))
102 | elif not chat_ids.forward_date:
103 | await chat_ids.delete()
104 | return await text.edit_text("This Is Not A Forward Message")
105 | else:
106 | chat_id = chat_ids.forward_from_chat.id
107 | title = chat_ids.forward_from_chat.title
108 | username = chat_ids.forward_from_chat.username
109 | username = "@" + username if username else "private"
110 | chat = await db.add_channel(user_id, chat_id, title, username)
111 | await chat_ids.delete()
112 | await text.edit_text(
113 | "Successfully Updated" if chat else "This Channel Already Added",
114 | reply_markup=InlineKeyboardMarkup(buttons))
115 | except asyncio.exceptions.TimeoutError:
116 | await text.edit_text('Process Has Been Automatically Cancelled', reply_markup=InlineKeyboardMarkup(buttons))
117 |
118 | elif type=="editbot":
119 | bot = await db.get_bot(user_id)
120 | TEXT = Translation.BOT_DETAILS if bot['is_bot'] else Translation.USER_DETAILS
121 | buttons = [[InlineKeyboardButton('❌ Remove ❌', callback_data=f"settings#removebot")
122 | ],
123 | [InlineKeyboardButton('🔙 Back', callback_data="settings#bots")]]
124 | await query.message.edit_text(
125 | TEXT.format(bot['name'], bot['id'], bot['username']),
126 | reply_markup=InlineKeyboardMarkup(buttons))
127 |
128 | elif type=="removebot":
129 | await db.remove_bot(user_id)
130 | await query.message.edit_text(
131 | "Successfully Updated",
132 | reply_markup=InlineKeyboardMarkup(buttons))
133 |
134 | elif type.startswith("editchannels"):
135 | chat_id = type.split('_')[1]
136 | chat = await db.get_channel_details(user_id, chat_id)
137 | buttons = [[InlineKeyboardButton('❌ Remove ❌', callback_data=f"settings#removechannel_{chat_id}")
138 | ],
139 | [InlineKeyboardButton('🔙 Back', callback_data="settings#channels")]]
140 | await query.message.edit_text(
141 | f"📄 Channel Details\n\nTitle : {chat['title']}
\nChannel ID : {chat['chat_id']}
\nUsername : {chat['username']}",
142 | reply_markup=InlineKeyboardMarkup(buttons))
143 |
144 | elif type.startswith("removechannel"):
145 | chat_id = type.split('_')[1]
146 | await db.remove_channel(user_id, chat_id)
147 | await query.message.edit_text(
148 | "Successfully Updated",
149 | reply_markup=InlineKeyboardMarkup(buttons))
150 |
151 | elif type=="caption":
152 | buttons = []
153 | data = await get_configs(user_id)
154 | caption = data['caption']
155 | if caption is None:
156 | buttons.append([InlineKeyboardButton('✚ Add Caption ✚',
157 | callback_data="settings#addcaption")])
158 | else:
159 | buttons.append([InlineKeyboardButton('👀 See Caption',
160 | callback_data="settings#seecaption")])
161 | buttons[-1].append(InlineKeyboardButton('🗑️ Delete Caption',
162 | callback_data="settings#deletecaption"))
163 | buttons.append([InlineKeyboardButton('🔙 Back',
164 | callback_data="settings#main")])
165 | await query.message.edit_text(
166 | "Custom Caption\n\nYou Can Set A Custom Caption To Videos And Documents. Normaly Use Its Default Caption\n\nAvailable Fillings :\n\n{filename}
: Filename\n{size}
: File Size\n{caption}
: Default Caption",
167 | reply_markup=InlineKeyboardMarkup(buttons))
168 |
169 | elif type=="seecaption":
170 | data = await get_configs(user_id)
171 | buttons = [[InlineKeyboardButton('✏️ Edit Caption',
172 | callback_data="settings#addcaption")
173 | ],[
174 | InlineKeyboardButton('🔙 Back',
175 | callback_data="settings#caption")]]
176 | await query.message.edit_text(
177 | f"Your Custom Caption\n\n{data['caption']}
",
178 | reply_markup=InlineKeyboardMarkup(buttons))
179 |
180 | elif type=="deletecaption":
181 | await update_configs(user_id, 'caption', None)
182 | await query.message.edit_text(
183 | "Successfully Updated",
184 | reply_markup=InlineKeyboardMarkup(buttons))
185 |
186 | elif type=="addcaption":
187 | await query.message.delete()
188 | try:
189 | text = await bot.send_message(query.message.chat.id, "Send your custom caption\n/cancel - cancel this process
")
190 | caption = await bot.listen(chat_id=user_id, timeout=300)
191 | if caption.text=="/cancel":
192 | await caption.delete()
193 | return await text.edit_text(
194 | "Process Canceled !",
195 | reply_markup=InlineKeyboardMarkup(buttons))
196 | try:
197 | caption.text.format(filename='', size='', caption='')
198 | except KeyError as e:
199 | await caption.delete()
200 | return await text.edit_text(
201 | f"Wrong Filling {e} Used In Your Caption. Change It",
202 | reply_markup=InlineKeyboardMarkup(buttons))
203 | await update_configs(user_id, 'caption', caption.text)
204 | await caption.delete()
205 | await text.edit_text(
206 | "Successfully Updated",
207 | reply_markup=InlineKeyboardMarkup(buttons))
208 | except asyncio.exceptions.TimeoutError:
209 | await text.edit_text('Process Has Been Automatically Cancelled', reply_markup=InlineKeyboardMarkup(buttons))
210 |
211 | elif type=="button":
212 | buttons = []
213 | button = (await get_configs(user_id))['button']
214 | if button is None:
215 | buttons.append([InlineKeyboardButton('✚ Add Button ✚',
216 | callback_data="settings#addbutton")])
217 | else:
218 | buttons.append([InlineKeyboardButton('👀 See Button',
219 | callback_data="settings#seebutton")])
220 | buttons[-1].append(InlineKeyboardButton('🗑️ Remove Button ',
221 | callback_data="settings#deletebutton"))
222 | buttons.append([InlineKeyboardButton('🔙 Back',
223 | callback_data="settings#main")])
224 | await query.message.edit_text(
225 | "Custom Button\n\nYou Can Set A Inline Button To Messages.\n\nFormat :\n`[Madflix Botz][buttonurl:https://t.me/Madflix_Bots]`\n",
226 | reply_markup=InlineKeyboardMarkup(buttons))
227 |
228 | elif type=="addbutton":
229 | await query.message.delete()
230 | try:
231 | txt = await bot.send_message(user_id, text="**Send your custom button.\n\nFORMAT:**\n`[forward bot][buttonurl:https://t.me/KR_Forward_Bot]`\n")
232 | ask = await bot.listen(chat_id=user_id, timeout=300)
233 | button = parse_buttons(ask.text.html)
234 | if not button:
235 | await ask.delete()
236 | return await txt.edit_text("Invalid Button")
237 | await update_configs(user_id, 'button', ask.text.html)
238 | await ask.delete()
239 | await txt.edit_text("Successfully Button Added",
240 | reply_markup=InlineKeyboardMarkup(buttons))
241 | except asyncio.exceptions.TimeoutError:
242 | await txt.edit_text('Process Has Been Automatically Cancelled', reply_markup=InlineKeyboardMarkup(buttons))
243 |
244 | elif type=="seebutton":
245 | button = (await get_configs(user_id))['button']
246 | button = parse_buttons(button, markup=False)
247 | button.append([InlineKeyboardButton("🔙 Back", "settings#button")])
248 | await query.message.edit_text(
249 | "**Your Custom Button**",
250 | reply_markup=InlineKeyboardMarkup(button))
251 |
252 | elif type=="deletebutton":
253 | await update_configs(user_id, 'button', None)
254 | await query.message.edit_text(
255 | "Successfully Button Deleted",
256 | reply_markup=InlineKeyboardMarkup(buttons))
257 |
258 | elif type=="database":
259 | buttons = []
260 | db_uri = (await get_configs(user_id))['db_uri']
261 | if db_uri is None:
262 | buttons.append([InlineKeyboardButton('✚ Add URL ✚',
263 | callback_data="settings#addurl")])
264 | else:
265 | buttons.append([InlineKeyboardButton('👀 See URL',
266 | callback_data="settings#seeurl")])
267 | buttons[-1].append(InlineKeyboardButton('🗑️ Remove URL',
268 | callback_data="settings#deleteurl"))
269 | buttons.append([InlineKeyboardButton('🔙 Back',
270 | callback_data="settings#main")])
271 | await query.message.edit_text(
272 | "Database\n\nDatabase Is Required For Store Your Duplicate Messages Permenant. Other Wise Stored Duplicate Media May Be Disappeared When After Bot Restart.",
273 | reply_markup=InlineKeyboardMarkup(buttons))
274 |
275 | elif type=="addurl":
276 | await query.message.delete()
277 | uri = await bot.ask(user_id, "please send your mongodb url.\n\nget your Mongodb url from [here](https://mongodb.com)", disable_web_page_preview=True)
278 | if uri.text=="/cancel":
279 | return await uri.reply_text(
280 | "Process Cancelled !",
281 | reply_markup=InlineKeyboardMarkup(buttons))
282 | if not uri.text.startswith("mongodb+srv://") and not uri.text.endswith("majority"):
283 | return await uri.reply("Invalid Mongodb URL",
284 | reply_markup=InlineKeyboardMarkup(buttons))
285 | await update_configs(user_id, 'db_uri', uri.text)
286 | await uri.reply("Successfully Database URL Added ✅",
287 | reply_markup=InlineKeyboardMarkup(buttons))
288 |
289 | elif type=="seeurl":
290 | db_uri = (await get_configs(user_id))['db_uri']
291 | await query.answer(f"Database URL : {db_uri}", show_alert=True)
292 |
293 | elif type=="deleteurl":
294 | await update_configs(user_id, 'db_uri', None)
295 | await query.message.edit_text(
296 | "Successfully Your Database URL Deleted",
297 | reply_markup=InlineKeyboardMarkup(buttons))
298 |
299 | elif type=="filters":
300 | await query.message.edit_text(
301 | "Custom Filters\n\nConfigure The Type Of Messages Which You Want Forward",
302 | reply_markup=await filters_buttons(user_id))
303 |
304 | elif type=="nextfilters":
305 | await query.edit_message_reply_markup(
306 | reply_markup=await next_filters_buttons(user_id))
307 |
308 | elif type.startswith("updatefilter"):
309 | i, key, value = type.split('-')
310 | if value=="True":
311 | await update_configs(user_id, key, False)
312 | else:
313 | await update_configs(user_id, key, True)
314 | if key in ['poll', 'protect']:
315 | return await query.edit_message_reply_markup(
316 | reply_markup=await next_filters_buttons(user_id))
317 | await query.edit_message_reply_markup(
318 | reply_markup=await filters_buttons(user_id))
319 |
320 | elif type.startswith("file_size"):
321 | settings = await get_configs(user_id)
322 | size = settings.get('file_size', 0)
323 | i, limit = size_limit(settings['size_limit'])
324 | await query.message.edit_text(
325 | f'Size Limit\n\nYou Can Set File Size Limit To Forward\n\nStatus : Files With {limit} `{size} MB` Will Forward',
326 | reply_markup=size_button(size))
327 |
328 | elif type.startswith("update_size"):
329 | size = int(query.data.split('-')[1])
330 | if 0 < size > 2000:
331 | return await query.answer("Size Limit Exceeded", show_alert=True)
332 | await update_configs(user_id, 'file_size', size)
333 | i, limit = size_limit((await get_configs(user_id))['size_limit'])
334 | await query.message.edit_text(
335 | f'Size Limit\n\nYou Can Set File Size Limit To Forward\n\nStatus : Files With {limit} `{size} MB` Will Forward',
336 | reply_markup=size_button(size))
337 |
338 | elif type.startswith('update_limit'):
339 | i, limit, size = type.split('-')
340 | limit, sts = size_limit(limit)
341 | await update_configs(user_id, 'size_limit', limit)
342 | await query.message.edit_text(
343 | f'Size Limit\n\nYou Can Set File Size Limit To Forward\n\nStatus : Files With {sts} `{size} MB` Will Forward',
344 | reply_markup=size_button(int(size)))
345 |
346 | elif type == "add_extension":
347 | await query.message.delete()
348 | ext = await bot.ask(user_id, text="Please Send Your Extensions (Seperete By Space)")
349 | if ext.text == '/cancel':
350 | return await ext.reply_text(
351 | "Process Cancelled",
352 | reply_markup=InlineKeyboardMarkup(buttons))
353 | extensions = ext.text.split(" ")
354 | extension = (await get_configs(user_id))['extension']
355 | if extension:
356 | for extn in extensions:
357 | extension.append(extn)
358 | else:
359 | extension = extensions
360 | await update_configs(user_id, 'extension', extension)
361 | await ext.reply_text(
362 | f"Successfully Updated",
363 | reply_markup=InlineKeyboardMarkup(buttons))
364 |
365 | elif type == "get_extension":
366 | extensions = (await get_configs(user_id))['extension']
367 | btn = extract_btn(extensions)
368 | btn.append([InlineKeyboardButton('✚ Add ✚', 'settings#add_extension')])
369 | btn.append([InlineKeyboardButton('Remove All', 'settings#rmve_all_extension')])
370 | btn.append([InlineKeyboardButton('🔙 Back', 'settings#main')])
371 | await query.message.edit_text(
372 | text='Extensions\n\nFiles With These Extiontions Will Not Forward',
373 | reply_markup=InlineKeyboardMarkup(btn))
374 |
375 | elif type == "rmve_all_extension":
376 | await update_configs(user_id, 'extension', None)
377 | await query.message.edit_text(text="Successfully Deleted",
378 | reply_markup=InlineKeyboardMarkup(buttons))
379 | elif type == "add_keyword":
380 | await query.message.delete()
381 | ask = await bot.ask(user_id, text="Please Send The Keywords (Seperete By Space)")
382 | if ask.text == '/cancel':
383 | return await ask.reply_text(
384 | "Process Canceled",
385 | reply_markup=InlineKeyboardMarkup(buttons))
386 | keywords = ask.text.split(" ")
387 | keyword = (await get_configs(user_id))['keywords']
388 | if keyword:
389 | for word in keywords:
390 | keyword.append(word)
391 | else:
392 | keyword = keywords
393 | await update_configs(user_id, 'keywords', keyword)
394 | await ask.reply_text(
395 | f"Successfully Updated",
396 | reply_markup=InlineKeyboardMarkup(buttons))
397 |
398 | elif type == "get_keyword":
399 | keywords = (await get_configs(user_id))['keywords']
400 | btn = extract_btn(keywords)
401 | btn.append([InlineKeyboardButton('✚ Add ✚', 'settings#add_keyword')])
402 | btn.append([InlineKeyboardButton('Remove All', 'settings#rmve_all_keyword')])
403 | btn.append([InlineKeyboardButton('🔙 Back', 'settings#main')])
404 | await query.message.edit_text(
405 | text='Keywords\n\nFile With These Keywords In File Name Will Forwad',
406 | reply_markup=InlineKeyboardMarkup(btn))
407 |
408 | elif type == "rmve_all_keyword":
409 | await update_configs(user_id, 'keywords', None)
410 | await query.message.edit_text(text="Successfully Deleted",
411 | reply_markup=InlineKeyboardMarkup(buttons))
412 | elif type.startswith("alert"):
413 | alert = type.split('_')[1]
414 | await query.answer(alert, show_alert=True)
415 |
416 | def main_buttons():
417 | buttons = [[
418 | InlineKeyboardButton('🤖 Bots',
419 | callback_data=f'settings#bots'),
420 | InlineKeyboardButton('🔥 Channels',
421 | callback_data=f'settings#channels')
422 | ],[
423 | InlineKeyboardButton('✏️ Caption',
424 | callback_data=f'settings#caption'),
425 | InlineKeyboardButton('🗃 MongoDB',
426 | callback_data=f'settings#database')
427 | ],[
428 | InlineKeyboardButton('🕵♀ Filters',
429 | callback_data=f'settings#filters'),
430 | InlineKeyboardButton('🏓 Button',
431 | callback_data=f'settings#button')
432 | ],[
433 | InlineKeyboardButton('⚙️ Extra Settings',
434 | callback_data='settings#nextfilters')
435 | ],[
436 | InlineKeyboardButton('🔙 Back', callback_data='back')
437 | ]]
438 | return InlineKeyboardMarkup(buttons)
439 |
440 | def size_limit(limit):
441 | if str(limit) == "None":
442 | return None, ""
443 | elif str(limit) == "True":
444 | return True, "more than"
445 | else:
446 | return False, "less than"
447 |
448 | def extract_btn(datas):
449 | i = 0
450 | btn = []
451 | if datas:
452 | for data in datas:
453 | if i >= 5:
454 | i = 0
455 | if i == 0:
456 | btn.append([InlineKeyboardButton(data, f'settings#alert_{data}')])
457 | i += 1
458 | continue
459 | elif i > 0:
460 | btn[-1].append(InlineKeyboardButton(data, f'settings#alert_{data}'))
461 | i += 1
462 | return btn
463 |
464 | def size_button(size):
465 | buttons = [[
466 | InlineKeyboardButton('+',
467 | callback_data=f'settings#update_limit-True-{size}'),
468 | InlineKeyboardButton('=',
469 | callback_data=f'settings#update_limit-None-{size}'),
470 | InlineKeyboardButton('-',
471 | callback_data=f'settings#update_limit-False-{size}')
472 | ],[
473 | InlineKeyboardButton('+1',
474 | callback_data=f'settings#update_size-{size + 1}'),
475 | InlineKeyboardButton('-1',
476 | callback_data=f'settings#update_size_-{size - 1}')
477 | ],[
478 | InlineKeyboardButton('+5',
479 | callback_data=f'settings#update_size-{size + 5}'),
480 | InlineKeyboardButton('-5',
481 | callback_data=f'settings#update_size_-{size - 5}')
482 | ],[
483 | InlineKeyboardButton('+10',
484 | callback_data=f'settings#update_size-{size + 10}'),
485 | InlineKeyboardButton('-10',
486 | callback_data=f'settings#update_size_-{size - 10}')
487 | ],[
488 | InlineKeyboardButton('+50',
489 | callback_data=f'settings#update_size-{size + 50}'),
490 | InlineKeyboardButton('-50',
491 | callback_data=f'settings#update_size_-{size - 50}')
492 | ],[
493 | InlineKeyboardButton('+100',
494 | callback_data=f'settings#update_size-{size + 100}'),
495 | InlineKeyboardButton('-100',
496 | callback_data=f'settings#update_size_-{size - 100}')
497 | ],[
498 | InlineKeyboardButton('↩ Back',
499 | callback_data="settings#main")
500 | ]]
501 | return InlineKeyboardMarkup(buttons)
502 |
503 | async def filters_buttons(user_id):
504 | filter = await get_configs(user_id)
505 | filters = filter['filters']
506 | buttons = [[
507 | InlineKeyboardButton('🏷️ Forward Tag',
508 | callback_data=f'settings_#updatefilter-forward_tag-{filter["forward_tag"]}'),
509 | InlineKeyboardButton('✅' if filter['forward_tag'] else '❌',
510 | callback_data=f'settings#updatefilter-forward_tag-{filter["forward_tag"]}')
511 | ],[
512 | InlineKeyboardButton('🖍️ Texts',
513 | callback_data=f'settings_#updatefilter-text-{filters["text"]}'),
514 | InlineKeyboardButton('✅' if filters['text'] else '❌',
515 | callback_data=f'settings#updatefilter-text-{filters["text"]}')
516 | ],[
517 | InlineKeyboardButton('📁 Documents',
518 | callback_data=f'settings_#updatefilter-document-{filters["document"]}'),
519 | InlineKeyboardButton('✅' if filters['document'] else '❌',
520 | callback_data=f'settings#updatefilter-document-{filters["document"]}')
521 | ],[
522 | InlineKeyboardButton('🎞️ Videos',
523 | callback_data=f'settings_#updatefilter-video-{filters["video"]}'),
524 | InlineKeyboardButton('✅' if filters['video'] else '❌',
525 | callback_data=f'settings#updatefilter-video-{filters["video"]}')
526 | ],[
527 | InlineKeyboardButton('📷 Photos',
528 | callback_data=f'settings_#updatefilter-photo-{filters["photo"]}'),
529 | InlineKeyboardButton('✅' if filters['photo'] else '❌',
530 | callback_data=f'settings#updatefilter-photo-{filters["photo"]}')
531 | ],[
532 | InlineKeyboardButton('🎧 Audios',
533 | callback_data=f'settings_#updatefilter-audio-{filters["audio"]}'),
534 | InlineKeyboardButton('✅' if filters['audio'] else '❌',
535 | callback_data=f'settings#updatefilter-audio-{filters["audio"]}')
536 | ],[
537 | InlineKeyboardButton('🎤 Voices',
538 | callback_data=f'settings_#updatefilter-voice-{filters["voice"]}'),
539 | InlineKeyboardButton('✅' if filters['voice'] else '❌',
540 | callback_data=f'settings#updatefilter-voice-{filters["voice"]}')
541 | ],[
542 | InlineKeyboardButton('🎭 Animations',
543 | callback_data=f'settings_#updatefilter-animation-{filters["animation"]}'),
544 | InlineKeyboardButton('✅' if filters['animation'] else '❌',
545 | callback_data=f'settings#updatefilter-animation-{filters["animation"]}')
546 | ],[
547 | InlineKeyboardButton('🃏 Stickers',
548 | callback_data=f'settings_#updatefilter-sticker-{filters["sticker"]}'),
549 | InlineKeyboardButton('✅' if filters['sticker'] else '❌',
550 | callback_data=f'settings#updatefilter-sticker-{filters["sticker"]}')
551 | ],[
552 | InlineKeyboardButton('▶️ Skip Duplicate',
553 | callback_data=f'settings_#updatefilter-duplicate-{filter["duplicate"]}'),
554 | InlineKeyboardButton('✅' if filter['duplicate'] else '❌',
555 | callback_data=f'settings#updatefilter-duplicate-{filter["duplicate"]}')
556 | ],[
557 | InlineKeyboardButton('🔙 back',
558 | callback_data="settings#main")
559 | ]]
560 | return InlineKeyboardMarkup(buttons)
561 |
562 | async def next_filters_buttons(user_id):
563 | filter = await get_configs(user_id)
564 | filters = filter['filters']
565 | buttons = [[
566 | InlineKeyboardButton('📊 Poll',
567 | callback_data=f'settings_#updatefilter-poll-{filters["poll"]}'),
568 | InlineKeyboardButton('✅' if filters['poll'] else '❌',
569 | callback_data=f'settings#updatefilter-poll-{filters["poll"]}')
570 | ],[
571 | InlineKeyboardButton('🔒 Secure Message',
572 | callback_data=f'settings_#updatefilter-protect-{filter["protect"]}'),
573 | InlineKeyboardButton('✅' if filter['protect'] else '❌',
574 | callback_data=f'settings#updatefilter-protect-{filter["protect"]}')
575 | ],[
576 | InlineKeyboardButton('🛑 Size Limit',
577 | callback_data='settings#file_size')
578 | ],[
579 | InlineKeyboardButton('💾 Extension',
580 | callback_data='settings#get_extension')
581 | ],[
582 | InlineKeyboardButton('📌 Keywords',
583 | callback_data='settings#get_keyword')
584 | ],[
585 | InlineKeyboardButton('🔙 Back',
586 | callback_data="settings#main")
587 | ]]
588 | return InlineKeyboardMarkup(buttons)
589 |
590 |
591 |
592 |
593 |
594 |
595 | # Jishu Developer
596 | # Don't Remove Credit 🥺
597 | # Telegram Channel @Madflix_Bots
598 | # Backup Channel @JishuBotz
599 | # Developer @JishuDeveloper
--------------------------------------------------------------------------------
/plugins/test.py:
--------------------------------------------------------------------------------
1 | # Jishu Developer
2 | # Don't Remove Credit 🥺
3 | # Telegram Channel @Madflix_Bots
4 | # Backup Channel @JishuBotz
5 | # Developer @JishuDeveloper
6 |
7 |
8 |
9 |
10 | import os
11 | import re
12 | import sys
13 | import typing
14 | import asyncio
15 | import logging
16 | from database import db
17 | from config import Config, temp
18 | from pyrogram import Client, filters
19 | from pyrogram.raw.all import layer
20 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, CallbackQuery, Message
21 | from pyrogram.errors.exceptions.bad_request_400 import AccessTokenExpired, AccessTokenInvalid
22 | from pyrogram.errors import FloodWait
23 | from config import Config
24 | from translation import Translation
25 |
26 | from typing import Union, Optional, AsyncGenerator
27 |
28 | logger = logging.getLogger(__name__)
29 | logger.setLevel(logging.INFO)
30 |
31 | BTN_URL_REGEX = re.compile(r"(\[([^\[]+?)]\[buttonurl:/{0,2}(.+?)(:same)?])")
32 | BOT_TOKEN_TEXT = "1) Create A Bot Using @BotFather\n\n2) Then You Will Get A Message With Bot Token\n\n3) Forward That Message To Me"
33 | SESSION_STRING_SIZE = 351
34 |
35 |
36 |
37 | async def start_clone_bot(FwdBot, data=None):
38 | await FwdBot.start()
39 | #
40 | async def iter_messages(
41 | self,
42 | chat_id: Union[int, str],
43 | limit: int,
44 | offset: int = 0,
45 | search: str = None,
46 | filter: "types.TypeMessagesFilter" = None,
47 | ) -> Optional[AsyncGenerator["types.Message", None]]:
48 | """Iterate through a chat sequentially.
49 | This convenience method does the same as repeatedly calling :meth:`~pyrogram.Client.get_messages` in a loop, thus saving
50 | you from the hassle of setting up boilerplate code. It is useful for getting the whole chat messages with a
51 | single call.
52 | Parameters:
53 | chat_id (``int`` | ``str``):
54 | Unique identifier (int) or username (str) of the target chat.
55 | For your personal cloud (Saved Messages) you can simply use "me" or "self".
56 | For a contact that exists in your Telegram address book you can use his phone number (str).
57 |
58 | limit (``int``):
59 | Identifier of the last message to be returned.
60 |
61 | offset (``int``, *optional*):
62 | Identifier of the first message to be returned.
63 | Defaults to 0.
64 | Returns:
65 | ``Generator``: A generator yielding :obj:`~pyrogram.types.Message` objects.
66 | Example:
67 | .. code-block:: python
68 | for message in app.iter_messages("pyrogram", 1, 15000):
69 | print(message.text)
70 | """
71 | current = offset
72 | while True:
73 | new_diff = min(200, limit - current)
74 | if new_diff <= 0:
75 | return
76 | messages = await self.get_messages(chat_id, list(range(current, current+new_diff+1)))
77 | for message in messages:
78 | yield message
79 | current += 1
80 | #
81 | FwdBot.iter_messages = iter_messages
82 | return FwdBot
83 |
84 |
85 |
86 | class CLIENT:
87 | def __init__(self):
88 | self.api_id = Config.API_ID
89 | self.api_hash = Config.API_HASH
90 |
91 | def client(self, data, user=None):
92 | if user == None and data.get('is_bot') == False:
93 | return Client("USERBOT", self.api_id, self.api_hash, session_string=data.get('session'))
94 | elif user == True:
95 | return Client("USERBOT", self.api_id, self.api_hash, session_string=data)
96 | elif user != False:
97 | data = data.get('token')
98 | return Client("BOT", self.api_id, self.api_hash, bot_token=data, in_memory=True)
99 |
100 |
101 |
102 | async def add_bot(self, bot, message):
103 | user_id = int(message.from_user.id)
104 | msg = await bot.ask(chat_id=user_id, text=BOT_TOKEN_TEXT)
105 | if msg.text=='/cancel':
106 | return await msg.reply('Process Cancelled !')
107 | elif not msg.forward_date:
108 | return await msg.reply_text("This Is Not A Forward Message")
109 | elif str(msg.forward_from.id) != "93372553":
110 | return await msg.reply_text("This Message Was Not Forward From Bot Father")
111 | bot_token = re.findall(r'\d[0-9]{8,10}:[0-9A-Za-z_-]{35}', msg.text, re.IGNORECASE)
112 | bot_token = bot_token[0] if bot_token else None
113 | if not bot_token:
114 | return await msg.reply_text("There Is No Bot Token In That Message")
115 | try:
116 | _client = await start_clone_bot(self.client(bot_token, False), True)
117 | except Exception as e:
118 | await msg.reply_text(f"Bot Error : `{e}`")
119 | _bot = _client.me
120 | details = {
121 | 'id': _bot.id,
122 | 'is_bot': True,
123 | 'user_id': user_id,
124 | 'name': _bot.first_name,
125 | 'token': bot_token,
126 | 'username': _bot.username
127 | }
128 | await db.add_bot(details)
129 | return True
130 |
131 |
132 |
133 | async def add_session(self, bot, message):
134 | user_id = int(message.from_user.id)
135 | text = "⚠️ Disclaimer ⚠️\n\nYou Can Use Your Session For Forward Message From Private Chat To Another Chat.\nPlease Add Your Pyrogram Session With Your Own Risk. Their Is A Chance To Ban Your Account. My Developer Is Not Responsible If Your Account May Get Banned."
136 | await bot.send_message(user_id, text=text)
137 | msg = await bot.ask(chat_id=user_id, text="Send your pyrogram session.\nget it from @mdsessiongenbot\n\n/cancel - cancel the process")
138 | if msg.text=='/cancel':
139 | return await msg.reply('Process Cancelled !')
140 | elif len(msg.text) < SESSION_STRING_SIZE:
141 | return await msg.reply('Invalid Session String')
142 | try:
143 | client = await start_clone_bot(self.client(msg.text, True), True)
144 | except Exception as e:
145 | await msg.reply_text(f"User Bot Error : `{e}`")
146 | user = client.me
147 | details = {
148 | 'id': user.id,
149 | 'is_bot': False,
150 | 'user_id': user_id,
151 | 'name': user.first_name,
152 | 'session': msg.text,
153 | 'username': user.username
154 | }
155 | await db.add_bot(details)
156 | return True
157 |
158 |
159 |
160 |
161 |
162 |
163 | @Client.on_message(filters.private & filters.command('reset'))
164 | async def forward_tag(bot, m):
165 | default = await db.get_configs("01")
166 | temp.CONFIGS[m.from_user.id] = default
167 | await db.update_configs(m.from_user.id, default)
168 | await m.reply("Successfully Settings Reseted ✔️")
169 |
170 |
171 |
172 |
173 | @Client.on_message(filters.command('resetall') & filters.user(Config.OWNER_ID))
174 | async def resetall(bot, message):
175 | users = await db.get_all_users()
176 | sts = await message.reply("Processing")
177 | TEXT = "Total: {}\nSuccess: {}\nFailed: {}\nExcept: {}"
178 | total = success = failed = already = 0
179 | ERRORS = []
180 | async for user in users:
181 | user_id = user['id']
182 | default = await get_configs(user_id)
183 | default['db_uri'] = None
184 | total += 1
185 | if total %10 == 0:
186 | await sts.edit(TEXT.format(total, success, failed, already))
187 | try:
188 | await db.update_configs(user_id, default)
189 | success += 1
190 | except Exception as e:
191 | ERRORS.append(e)
192 | failed += 1
193 | if ERRORS:
194 | await message.reply(ERRORS[:100])
195 | await sts.edit("Completed\n" + TEXT.format(total, success, failed, already))
196 |
197 |
198 |
199 | async def get_configs(user_id):
200 | #configs = temp.CONFIGS.get(user_id)
201 | #if not configs:
202 | configs = await db.get_configs(user_id)
203 | #temp.CONFIGS[user_id] = configs
204 | return configs
205 |
206 |
207 |
208 | async def update_configs(user_id, key, value):
209 | current = await db.get_configs(user_id)
210 | if key in ['caption', 'duplicate', 'db_uri', 'forward_tag', 'protect', 'file_size', 'size_limit', 'extension', 'keywords', 'button']:
211 | current[key] = value
212 | else:
213 | current['filters'][key] = value
214 | # temp.CONFIGS[user_id] = value
215 | await db.update_configs(user_id, current)
216 |
217 |
218 | def parse_buttons(text, markup=True):
219 | buttons = []
220 | for match in BTN_URL_REGEX.finditer(text):
221 | n_escapes = 0
222 | to_check = match.start(1) - 1
223 | while to_check > 0 and text[to_check] == "\\":
224 | n_escapes += 1
225 | to_check -= 1
226 |
227 | if n_escapes % 2 == 0:
228 | if bool(match.group(4)) and buttons:
229 | buttons[-1].append(InlineKeyboardButton(
230 | text=match.group(2),
231 | url=match.group(3).replace(" ", "")))
232 | else:
233 | buttons.append([InlineKeyboardButton(
234 | text=match.group(2),
235 | url=match.group(3).replace(" ", ""))])
236 | if markup and buttons:
237 | buttons = InlineKeyboardMarkup(buttons)
238 | return buttons if buttons else None
239 |
240 |
241 |
242 |
243 |
244 |
245 | # Jishu Developer
246 | # Don't Remove Credit 🥺
247 | # Telegram Channel @Madflix_Bots
248 | # Backup Channel @JishuBotz
249 | # Developer @JishuDeveloper
--------------------------------------------------------------------------------
/plugins/unequify.py:
--------------------------------------------------------------------------------
1 | # Jishu Developer
2 | # Don't Remove Credit 🥺
3 | # Telegram Channel @Madflix_Bots
4 | # Backup Channel @JishuBotz
5 | # Developer @JishuDeveloper
6 |
7 |
8 |
9 |
10 | import re, asyncio
11 | from database import db
12 | from config import temp
13 | from .test import CLIENT , start_clone_bot
14 | from translation import Translation
15 | from pyrogram import Client, filters
16 | #from pyropatch.utils import unpack_new_file_id
17 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
18 |
19 | CLIENT = CLIENT()
20 | COMPLETED_BTN = InlineKeyboardMarkup(
21 | [
22 | [InlineKeyboardButton('📢 Updates', url='https://t.me/Madflix_Bots')],
23 | [InlineKeyboardButton('💬 Support', url='https://t.me/MadflixBots_Support')]
24 | ]
25 | )
26 |
27 | CANCEL_BTN = InlineKeyboardMarkup([[InlineKeyboardButton('✖️ Cancel ✖️', 'terminate_frwd')]])
28 |
29 |
30 |
31 |
32 |
33 | @Client.on_message(filters.command("unequify") & filters.private)
34 | async def unequify(client, message):
35 | user_id = message.from_user.id
36 | temp.CANCEL[user_id] = False
37 | if temp.lock.get(user_id) and str(temp.lock.get(user_id))=="True":
38 | return await message.reply("Please Wait Until Previous Task Complete")
39 | _bot = await db.get_bot(user_id)
40 | if not _bot or _bot['is_bot']:
41 | return await message.reply("Need Userbot To Fo This Process. Please Add A Userbot Using /settings")
42 | target = await client.ask(user_id, text="Forward The Last Message From Target Chat Or Send Last Message Link.\n/cancel - To Cancel This Process")
43 | if target.text.startswith("/"):
44 | return await message.reply("Process Cancelled !")
45 | elif target.text:
46 | regex = re.compile(r"(https://)?(t\.me/|telegram\.me/|telegram\.dog/)(c/)?(\d+|[a-zA-Z_0-9]+)/(\d+)$")
47 | match = regex.match(target.text.replace("?single", ""))
48 | if not match:
49 | return await message.reply('Invalid Link')
50 | chat_id = match.group(4)
51 | last_msg_id = int(match.group(5))
52 | if chat_id.isnumeric():
53 | chat_id = int(("-100" + chat_id))
54 | elif fromid.forward_from_chat.type in ['channel', 'supergroup']:
55 | last_msg_id = target.forward_from_message_id
56 | chat_id = target.forward_from_chat.username or target.forward_from_chat.id
57 | else:
58 | return await message.reply_text("Invalid !")
59 | confirm = await client.ask(user_id, text="Send /yes To Start The Process And /no To Cancel This Process")
60 | if confirm.text.lower() == '/no':
61 | return await confirm.reply("Process Cancelled !")
62 | sts = await confirm.reply("Processing..")
63 | try:
64 | bot = await start_clone_bot(CLIENT.client(_bot))
65 | except Exception as e:
66 | return await sts.edit(e)
67 | try:
68 | k = await bot.send_message(chat_id, text="testing")
69 | await k.delete()
70 | except:
71 | await sts.edit(f"Please Make Your [Userbot](t.me/{_bot['username']}) Admin In Target Chat With Full Permissions")
72 | return await bot.stop()
73 | MESSAGES = []
74 | DUPLICATE = []
75 | total=deleted=0
76 | temp.lock[user_id] = True
77 | try:
78 | await sts.edit(Translation.DUPLICATE_TEXT.format(total, deleted, "Progressing"), reply_markup=CANCEL_BTN)
79 | async for message in bot.search_messages(chat_id=chat_id, filter="document"):
80 | if temp.CANCEL.get(user_id) == True:
81 | await sts.edit(Translation.DUPLICATE_TEXT.format(total, deleted, "Cancelled"), reply_markup=COMPLETED_BTN)
82 | return await bot.stop()
83 | file = message.document
84 | file_id = unpack_new_file_id(file.file_id)
85 | if file_id in MESSAGES:
86 | DUPLICATE.append(message.id)
87 | else:
88 | MESSAGES.append(file_id)
89 | total += 1
90 | if total %10000 == 0:
91 | await sts.edit(Translation.DUPLICATE_TEXT.format(total, deleted, "Progressing"), reply_markup=CANCEL_BTN)
92 | if len(DUPLICATE) >= 100:
93 | await bot.delete_messages(chat_id, DUPLICATE)
94 | deleted += 100
95 | await sts.edit(Translation.DUPLICATE_TEXT.format(total, deleted, "Cancelled"), reply_markup=CANCEL_BTN)
96 | DUPLICATE = []
97 | if DUPLICATE:
98 | await bot.delete_messages(chat_id, DUPLICATE)
99 | deleted += len(DUPLICATE)
100 | except Exception as e:
101 | temp.lock[user_id] = False
102 | await sts.edit(f"**Error**\n\n`{e}`")
103 | return await bot.stop()
104 | temp.lock[user_id] = False
105 | await sts.edit(Translation.DUPLICATE_TEXT.format(total, deleted, "Completed"), reply_markup=COMPLETED_BTN)
106 | await bot.stop()
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | # Jishu Developer
115 | # Don't Remove Credit 🥺
116 | # Telegram Channel @Madflix_Bots
117 | # Backup Channel @JishuBotz
118 | # Developer @JishuDeveloper
--------------------------------------------------------------------------------
/plugins/utils.py:
--------------------------------------------------------------------------------
1 | # Jishu Developer
2 | # Don't Remove Credit 🥺
3 | # Telegram Channel @Madflix_Bots
4 | # Backup Channel @JishuBotz
5 | # Developer @JishuDeveloper
6 |
7 |
8 |
9 |
10 | import time as tm
11 | from database import db
12 | from .test import parse_buttons
13 |
14 | STATUS = {}
15 |
16 | class STS:
17 | def __init__(self, id):
18 | self.id = id
19 | self.data = STATUS
20 |
21 | def verify(self):
22 | return self.data.get(self.id)
23 |
24 | def store(self, From, to, skip, limit):
25 | self.data[self.id] = {"FROM": From, 'TO': to, 'total_files': 0, 'skip': skip, 'limit': limit,
26 | 'fetched': skip, 'filtered': 0, 'deleted': 0, 'duplicate': 0, 'total': limit, 'start': 0}
27 | self.get(full=True)
28 | return STS(self.id)
29 |
30 | def get(self, value=None, full=False):
31 | values = self.data.get(self.id)
32 | if not full:
33 | return values.get(value)
34 | for k, v in values.items():
35 | setattr(self, k, v)
36 | return self
37 |
38 | def add(self, key=None, value=1, time=False):
39 | if time:
40 | return self.data[self.id].update({'start': tm.time()})
41 | self.data[self.id].update({key: self.get(key) + value})
42 |
43 | def divide(self, no, by):
44 | by = 1 if int(by) == 0 else by
45 | return int(no) / by
46 |
47 | async def get_data(self, user_id):
48 | bot = await db.get_bot(user_id)
49 | k, filters = self, await db.get_filters(user_id)
50 | size, configs = None, await db.get_configs(user_id)
51 | if configs['duplicate']:
52 | duplicate = [configs['db_uri'], self.TO]
53 | else:
54 | duplicate = False
55 | button = parse_buttons(configs['button'] if configs['button'] else '')
56 | if configs['file_size'] != 0:
57 | size = [configs['file_size'], configs['size_limit']]
58 | return bot, configs['caption'], configs['forward_tag'], {'chat_id': k.FROM, 'limit': k.limit, 'offset': k.skip, 'filters': filters,
59 | 'keywords': configs['keywords'], 'media_size': size, 'extensions': configs['extension'], 'skip_duplicate': duplicate}, configs['protect'], button
60 |
61 |
62 | def get_readable_time(seconds: int) -> str:
63 | result = ""
64 | (days, remainder) = divmod(seconds, 86400)
65 | days = int(days)
66 | if days != 0:
67 | result += f"{days}d"
68 | (hours, remainder) = divmod(remainder, 3600)
69 | hours = int(hours)
70 | if hours != 0:
71 | result += f"{hours}h"
72 | (minutes, seconds) = divmod(remainder, 60)
73 | minutes = int(minutes)
74 | if minutes != 0:
75 | result += f"{minutes}m"
76 | seconds = int(seconds)
77 | result += f"{seconds}s"
78 | return result
79 |
80 |
81 |
82 | # Jishu Developer
83 | # Don't Remove Credit 🥺
84 | # Telegram Channel @Madflix_Bots
85 | # Backup Channel @JishuBotz
86 | # Developer @JishuDeveloper
87 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | pyrofork
2 | motor
3 | TgCrypto
4 | Dnspython
5 | aiohttp
6 | pytz
--------------------------------------------------------------------------------
/start.sh:
--------------------------------------------------------------------------------
1 | echo "Cloning Repo...."
2 | if [ -z $BRANCH ]
3 | then
4 | echo "Cloning main branch...."
5 | git clone https://github.com/JishuDeveloper/Ultra-Forward-Bot JishuDeveloper/Ultra-Forward-Bot
6 | else
7 | echo "Cloning $BRANCH branch...."
8 | git clone https://github.com/JishuDeveloper/Ultra-Forward-Bot -b $BRANCH /Ultra-Forward-Bot
9 | fi
10 | cd JishuDeveloper/Ultra-Forward-Bot
11 | pip3 install -U -r requirements.txt
12 | echo "Starting Bot...."
13 | python3 main.py
14 |
--------------------------------------------------------------------------------
/translation.py:
--------------------------------------------------------------------------------
1 | # Jishu Developer
2 | # Don't Remove Credit 🥺
3 | # Telegram Channel @Madflix_Bots
4 | # Backup Channel @JishuBotz
5 | # Developer @JishuDeveloper
6 |
7 |
8 |
9 |
10 | import os
11 | from config import Config
12 |
13 | class Translation(object):
14 | START_TXT = """Hey {}
15 |
16 | ➻ I Am A Advanced Auto Forward Bot
17 |
18 | ➻ I Can Forward All Message From One Channel To Another Channel
19 |
20 | ➻ Click Help Button To Know More About Me
21 |
22 | Bot Is Made By @Madflix_Bots"""
23 |
24 |
25 | HELP_TXT = """🛠️ Help
26 |
27 | 📚 Available Commands :
28 | ⏣ __/start - Check I'm Alive__
29 | ⏣ __/forward - Forward Messages__
30 | ⏣ __/unequify - Delete Duplicate Messages In Channels__
31 | ⏣ __/settings - Configure Your Settings__
32 | ⏣ __/reset - Reset Your Settings__
33 |
34 | 💢 Features :
35 | ► __Forward Message From Public Channel To Your Channel Without Admin Permission. If The Channel Is Private Need Admin Permission__
36 | ► __Forward Message From Private Channel To Your Channel By Using Userbot(User Must Be Member In There)__
37 | ► __Custom Caption__
38 | ► __Custom Button__
39 | ► __Support Restricted Chats__
40 | ► __Skip Duplicate Messages__
41 | ► __Filter Type Of Messages__
42 | ► __Skip Messages Based On Extensions & Keywords & Size__
43 | """
44 |
45 | HOW_USE_TXT = """⚠️ Before Forwarding :
46 |
47 | ► __Add A Bot Or Userbot__
48 | ► __Add Atleast One To Channel (Your Bot/Userbot Must Be Admin In There)__
49 | ► __You Can Add Chats Or Bots By Using /settings__
50 | ► __If The **From Channel** Is Private Your Userbot Must Be Member In There Or Your Bot Must Need Admin Permission In There Also__
51 | ► __Then Use /forward To Forward Messages__"""
52 |
53 | ABOUT_TXT = """🤖 My Name : {}
54 | 📝 Language : Python 3
55 | 📚 Library : Pyrogram 2.0
56 | 🚀 Server : Heroku
57 | 📢 Channel : Madflix Botz
58 | 🧑💻 Developer : Jishu Developer
59 |
60 | ♻️ Bot Made By : @Madflix_Bots"""
61 |
62 | STATUS_TXT = """Bot Status
63 |
64 | 👱 Total Users : {}
65 |
66 | 🤖 Total Bots : {}
67 |
68 | 🔃 Forwardings : {}
69 | """
70 |
71 | FROM_MSG = "Set Source Chat>>\n\nForward The Last Message Or Last Message Link Of Source Chat.\n/cancel - To Cancel This Process"
72 | TO_MSG = "Choose Target Chat\n\nChoose Your Target Chat From The Given Buttons.\n/cancel - To Cancel This Process"
73 | SKIP_MSG = "Set Message Skiping Number\n\nSkip The Message As Much As You Enter The Number And The Rest Of The Message Will Be Forwarded\nDefault Skip Number = 0
\neg: You Enter 0 = 0 Message Skiped\nYou Enter 5 = 5 Message Skiped
\n/cancel - To Cancel This Process"
74 | CANCEL = "Process Cancelled Succefully !"
75 | BOT_DETAILS = "📄 Bot Details\n\n➣ Name : {}
\n➣ Bot ID : {}
\n➣ Username : @{}"
76 | USER_DETAILS = "📄 UserBot Details\n\n➣ Name : {}
\n➣ User ID : {}
\n➣ Username : @{}"
77 |
78 | TEXT = """Forward Status
79 |
80 | 🕵 Fetch Message : {}
81 |
82 | ✅ Successfully Forward : {}
83 |
84 | 👥 Dublicate Message : {}
85 |
86 | 🗑 Deleted Message : {}
87 |
88 | 🪆 Skipped Message : {}
89 |
90 | 🔁 Filtered Message : {}
91 |
92 | 📊 Current Status : {}
93 |
94 | 🔥 Percentage : {}
%
95 |
96 | {}
97 | """
98 |
99 | TEXT1 = """Forwarded Status
100 |
101 | 🕵 Fetched Message : {}
102 |
103 | ✅ Successfully Forward : {}
104 |
105 | 👥 Dublicate Message : {}
106 |
107 | 🗑 Deleted Message : {}
108 |
109 | 🪆 Skipped : {}
110 |
111 | 📊 Stats : {}
112 |
113 | ⏳ Progress : {}
114 |
115 | ⏰ ETA : {}
116 |
117 | {}"""
118 |
119 | DUPLICATE_TEXT = """Unequify Status
120 |
121 | 🕵 Fetched Files : {}
122 |
123 | 👥 Dublicate Deleted : {}
124 |
125 | {}
126 | """
127 | DOUBLE_CHECK = """Double Checking
128 |
129 | Before Forwarding The Messages Click The Yes Button Only After Checking The Following
130 |
131 | ★ Your Bot : [{botname}](t.me/{botuname})
132 | ★ From Channel : {from_chat}<>
133 | ★ To Channel : {to_chat}
134 | ★ Skip Messages : {skip}
135 |
136 | ° [{botname}](t.me/{botuname}) Must Be Admin In Target Chat ({to_chat}
)
137 | ° If The Source Chat Is Private Your Userbot Must Be Member Or Your Bot Must Be Admin In There Also
138 |
139 | If The Above Is Checked Then The Yes Button Can Be Clicked"""
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 | # Jishu Developer
151 | # Don't Remove Credit 🥺
152 | # Telegram Channel @Madflix_Bots
153 | # Backup Channel @JishuBotz
154 | # Developer @JishuDeveloper
--------------------------------------------------------------------------------