├── Dockerfile ├── Procfile ├── README.md ├── annabelle.py ├── annabelle ├── __init__.py ├── database │ ├── gban_db.py │ ├── gmute_db.py │ ├── pmpermit_db.py │ └── users_db.py ├── helper_funcs │ ├── admin_check.py │ └── strings.py └── modules │ ├── afk.py │ ├── alive.py │ ├── autobio.py │ ├── autodp.py │ ├── block.py │ ├── blockusername.py │ ├── calculator.py │ ├── checks.py │ ├── clone.py │ ├── covid.py │ ├── create.py │ ├── forward_all.py │ ├── gban.py │ ├── github.py │ ├── help.py │ ├── helpers │ ├── afk_handler.py │ └── mirror_func.py │ ├── helpmenu │ └── help_menu.py │ ├── inline.py │ ├── leave.py │ ├── mirror.py │ ├── pin.py │ ├── ping.py │ ├── pmpermit.py │ ├── purge.py │ ├── qoutly.py │ ├── screenshot.py │ ├── sendmod.py │ ├── set.py │ ├── spam.py │ ├── tagall.py │ ├── thumbnail.py │ ├── typewritter.py │ └── wiki.py ├── app.json ├── bot.py ├── config.py ├── docker-compose.yml ├── mainbot └── start.py ├── requirements.txt ├── runtime.txt └── start /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.9.1 2 | WORKDIR /app 3 | COPY requirements.txt requirements.txt 4 | RUN pip3 install -r requirements.txt 5 | COPY . . 6 | CMD python3 bot.py 7 | CMD python3 annabelle.py 8 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | worker: python3 Annabelle.py 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
Annabelle is telegram's lightest, fastest and most secure userbot.
Annabelle is filled with
11 | • Admin tools
12 | • Funs
13 | • Private tools
14 |
26 | API_ID
: API_ID from website or botAPI_HASH
: API_HASH from site or botSESSION_STRING
: pyrogram session string from bot or reposDATABASE_NAME
: Your MongoDB database nameDATABASE_URL
: Your MONGODB urlHANDLER
: The command prefix. eg . , SUDO_USERS
: ID of users who can use your bot's certain other than youMY_ID
: Your telegram ID{e}
")
17 |
18 |
19 | @Client.on_message(filters.command(["unblock"], prefixes=f"{HANDLER}") & filters.me)
20 | async def unblock(client: Client, message: Message):
21 | try:
22 | user_id = message.command[1]
23 | await client.unblock_user(user_id)
24 | await message.edit(
25 | f"☺️ User removed from the blacklist!"
26 | )
27 | except Exception as e:
28 | await message.edit(f"😰 Oops: {e}
")
29 |
30 |
31 | modules_help.append(
32 | {
33 | "blacklist": [
34 | {"block [user_id]*": "Block user"},
35 | {"unblock [user_id]*": "Unblock user"},
36 | ]
37 | }
38 | )
39 |
--------------------------------------------------------------------------------
/annabelle/modules/calculator.py:
--------------------------------------------------------------------------------
1 | """
2 |
3 |
4 | # Copyright ©️
5 |
6 |
7 |
8 | """
9 |
10 | import asyncio
11 | from pyrogram import Client, filters
12 | from pyrogram.types import Message
13 | from config import HANDLER
14 | from annabelle.modules.helpmenu.help_menu import modules_help
15 |
16 |
17 | @Client.on_message(filters.command("calc", prefixes=f"{HANDLER}") & filters.me)
18 | async def calc(client: Client, message: Message):
19 | if len(message.command) <= 1:
20 | return
21 | args = " ".join(message.command[1:])
22 | try:
23 | result = str(eval(args))
24 |
25 | if len(result) > 4096:
26 | i = 0
27 | for x in range(0, len(result), 4096):
28 | if i == 0:
29 | await message.edit(
30 | f"{args}={result[x:x + 4000]}
",
31 | parse_mode="HTML",
32 | )
33 | else:
34 | await message.reply(
35 | f"{result[x:x + 4096]}
", parse_mode="HTML"
36 | )
37 | i += 1
38 | await asyncio.sleep(0.18)
39 | else:
40 | await message.edit(
41 | f"{args}={result}
", parse_mode="HTML"
42 | )
43 | except Exception as e:
44 | await message.edit(f"{args}=={e}
", parse_mode="HTML")
45 |
46 |
47 | modules_help.append(
48 | {
49 | "calculator": [
50 | {
51 | "calc [expression]*": "Solve a math problem\n+ – addition\n– – subtraction\n* – multiplication\n/ – division\n** – degree"
52 | }
53 | ]
54 | }
55 | )
56 |
--------------------------------------------------------------------------------
/annabelle/modules/checks.py:
--------------------------------------------------------------------------------
1 | from annabelle import Annabelle
2 | from annabelle.database.gbans import check_gban
3 | from annabelle.database.gmutes import check_gmute
4 | from config import MY_ID
5 | from pyrogram.types import ChatPermissions
6 |
7 | @Annabelle.on_message(filters.new_chat_member & filters.group)
8 | async def ayoo(Annabelle, message):
9 | id = message.from_user.id
10 | member = await Annabelle.get_chat_member(message.chat.id, MY_ID)
11 | x = check_gban(id)
12 | if x is not False:
13 | try:
14 | await bot.kick_chat_member(message.chat.id, id)
15 | await message.reply(f"`Recently joined user is globally banned! I have kicked him`\nreason:`{x}`")
16 | except:
17 | await message.reply(f"`Warning! Recently joined user is globally banned!`\nreason: `{x}`")
18 | else:
19 | id = message.from_user.id
20 | x = check_gmute(id)
21 | if x is not False:
22 | try:
23 | await Annabelle.restrict_chat_member(message.chat.id, id, ChatPermissions())
24 | await message.reply(f"`Recently joined user is globally muted!` I have muted him`\nreason: `{x}`")
25 | except:
26 | await message.reply(f"`WARNING\n Recently joined user is globally muted for reason: {x}`")
27 |
28 |
29 | # hope it works
30 |
--------------------------------------------------------------------------------
/annabelle/modules/clone.py:
--------------------------------------------------------------------------------
1 | from annabelle import Annabelle
2 | from pyrogram import Client
3 | from config import MY_ID, HANDLER
4 | from pyrogram import filters as vrn
5 | from pyrogram.types.messages_and_media import Message
6 |
7 |
8 |
9 | @Annabelle.on_message(filters.command("clone", HANDLER) & filters.me)
10 | async def clone(bot:Client, msg:Message) :
11 | if msg.from_user.id == MY_ID :
12 | if msg.chat.type == "group" or msg.chat.type == "supergroup" :
13 | try :
14 | user = msg.reply_to_message.from_user
15 |
16 | try :
17 | pic = await bot.download_media(message=user.photo.big_file_id)
18 | await bot.set_profile_photo(photo=pic)
19 | except :
20 | print("No profile photo !")
21 |
22 | firstname = user.first_name
23 |
24 | if user.last_name :
25 | lastname = user.last_name
26 | else :
27 | lastname = ""
28 |
29 | await bot.update_profile(first_name=firstname, last_name=lastname)
30 | await msg.edit_text(text="`Cloned Successfully !`")
31 |
32 | except :
33 | await msg.edit_text(text="`Couldnt clone !!`")
34 |
35 |
36 | elif msg.chat.type == "private" :
37 | try :
38 |
39 | try :
40 | user = msg.chat
41 | except :
42 | user = msg.reply_to_message.from_user
43 |
44 | try :
45 | pic = user.photo.big_file_id
46 | await bot.set_profile_photo(photo=pic)
47 | except :
48 | pic = ""
49 |
50 | firstname = user.first_name
51 |
52 | if user.last_name :
53 | lastname = user.last_name
54 | else :
55 | lastname = ""
56 |
57 | await bot.update_profile(first_name=firstname, last_name=lastname)
58 |
59 | await msg.edit_text(text="**Cloned Successfully !**")
60 | except :
61 | await msg.edit_text(text="**Couldnt Clone !**")
62 | else :
63 | await msg.edit_text(text=**Couldnt Clone !**")
64 |
65 |
--------------------------------------------------------------------------------
/annabelle/modules/covid.py:
--------------------------------------------------------------------------------
1 | import os
2 | import requests
3 | from requests.utils import requote_uri
4 | from pyrogram import filters as vrn
5 | from config import HANDLER
6 | from annabelle import Annabelle
7 |
8 | API = "https://api.sumanjay.cf/covid/?country="
9 |
10 | @Annabelle.on_message(filters.command("covid", HANDLER))
11 | async def reply_info(client, message):
12 | query = message.text.split(None, 1)[1]
13 | reply_markup = BUTTONS
14 | await message.edit(
15 | text=covid_info(query),
16 | disable_web_page_preview=True,
17 | quote=True,
18 | )
19 |
20 |
21 | def covid_info(country_name):
22 | try:
23 | r = requests.get(API + requote_uri(country_name.lower()))
24 | info = r.json()
25 | country = info['country'].capitalize()
26 | active = info['active']
27 | confirmed = info['confirmed']
28 | deaths = info['deaths']
29 | info_id = info['id']
30 | last_update = info['last_update']
31 | latitude = info['latitude']
32 | longitude = info['longitude']
33 | recovered = info['recovered']
34 | covid_info = f"""
35 | **♻️ Covid 19 Information**
36 | **🌐 Country :** `{country}`
37 | **🎭 Actived :** `{active}`
38 | **✅ Confirmed :** `{confirmed}`
39 | **⚰️ Deaths :** `{deaths}`
40 | **🆔 ID :** `{info_id}`
41 | **🚨 Last Update :** `{last_update}`
42 | **⚓ Latitude :** `{latitude}`
43 | **🗼 Longitude :** `{longitude}`
44 | **🎙️ Recovered :** `{recovered}`
45 | """
46 | return covid_info
47 | except Exception as error:
48 | return error
49 |
50 |
51 | @Annabelle.on_message(vrn.command("corona", HANDELR))
52 | async def covid(Annabelle, message):
53 | query = message.text.split(None, 1)[1]
54 | reply_markup = BUTTONS
55 | await message.edit(
56 | text=covid_info(query),
57 | disable_web_page_preview=True,
58 | quote=True
59 | )
60 |
--------------------------------------------------------------------------------
/annabelle/modules/create.py:
--------------------------------------------------------------------------------
1 | from annabelle import Annabelle
2 | from pyrogram import filters as vrn
3 |
4 | @Annabelle.on_message(vrn.command('group', HANDLER))
5 | async def create_gr(Annabelle, message):
6 | if message.from_user.id == MY_ID:
7 | if message.reply_to_message:
8 | try:
9 | add_id = message.reply_to_message.from_user.id
10 | args = message.text.split(None, 1)
11 | title = args[1]
12 | await Annabelle.create_group(title, add_id)
13 | await message.edit(f"`successfully made a new group {title}`")
14 | except:
15 | await message.edit("`That user cant be added to a group`")
16 |
17 | @Annabelle.on_message(vrn.command('channel', HANDLER))
18 | async def create_ch(Annabelle, message):
19 | if message.from_user.id == MY_ID:
20 | args = message.text.split(None, 1)
21 | title = args[1]
22 | await Annabelle.create_channel(title, 'made with annabelle userbot')
23 | await message.edit(f"`successfully made a new channel {title}`")
24 |
--------------------------------------------------------------------------------
/annabelle/modules/forward_all.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | from pyrogram import Client, filters
3 | from pyrogram.errors import FloodWait
4 | from pyrogram.types import Message
5 | from config import HANDLER
6 | from annabelle.modules.helpmenu.help_menu import modules_help
7 |
8 |
9 | @Client.on_message(filters.command(["fwdall"], prefixes=f"{HANDLER}") & filters.me)
10 | async def forward(client: Client, message: Message):
11 | stat = None if len(message.text.split(" ")) < 2 else message.text.split(" ")[1]
12 | if sta is not None:
13 | await message.edit("On it...
", parse_mode="html")
14 | try:
15 | target = await client.get_chat(stat)
16 | except:
17 | await message.edit("Unknown target.
", parse_mode="html")
18 | target = None
19 | if target is not None:
20 | msgs = []
21 | async for msg in client.iter_history(message.chat.id, reverse=True):
22 | msgs.append(msg.message_id)
23 | if len(msgs) >= 100:
24 | try:
25 | await client.forward_messages(target.id, message.chat.id, msgs)
26 | except FloodWait as e:
27 | await asyncio.sleep(e.x)
28 | await client.forward_messages(target.id, message.chat.id, msgs)
29 | msgs = []
30 | if msgs:
31 | try:
32 | await client.forward_messages(target.id, message.chat.id, msgs)
33 | except FloodWait as e:
34 | await asyncio.sleep(e.x)
35 | await client.forward_messages(target.id, message.chat.id, msgs)
36 | await message.edit("Forwarded successfully.
", parse_mode="html")
37 | else:
38 | await message.edit("No target passed.
", parse_mode="html")
39 |
40 |
41 | modules_help.append(
42 | {
43 | "forwardall": [
44 | {
45 | "fwdall [target]*": "Foraward all messages to defined target [username/chat_id/chat_link]."
46 | }
47 | ]
48 | }
49 | )
50 |
--------------------------------------------------------------------------------
/annabelle/modules/gban.py:
--------------------------------------------------------------------------------
1 | from config import MY_ID, HANDLER, SUDO_USERS
2 | from pyrogram import filters as vrn
3 | from annabelle.helper_funcs.admin_check import admin_check
4 | from annabelle.helper_funcs.strings import GBAN_TXT
5 | from annabelle import Annabelle
6 | from annabelle.database.gban_db import add_gban, un_gban, check_gban
7 |
8 | import logging
9 | logging = logging.getLogger(__name__)
10 |
11 | @Annabelle.on_message(vrn.command('gban', HANDLER))
12 | async def gban(Annabelle, message):
13 | if message.from_user.id == MY_ID or message.from_user.id in SUDO_USERS:
14 | if message.reply_to_message:
15 | args = message.text.split(None,1)
16 | if len(args) >= 2:
17 | reason = args[1]
18 | id = message.reply_to_message.from_user.id
19 | member = Annabelle.get_chat_member(message.chat.id, message.reply_to_message.from_user.id)
20 | add_ban(id, reason)
21 | await message.edit(GBAN_TXT.format(message.reply_to_message.from_user.mention, reason))
22 | else:
23 | reason = ""
24 | else:
25 | await message.edit("You didn't specify whom to gban")
26 | else:
27 | return
28 |
29 | @Annabelle.on_message(vrn.me &vrn.command('ungban', HANDLER) & vrn.group)
30 | async def ungban(Annabelle, message):
31 | if not message.reply_to_message:
32 | message.edit("`reply to message of user who needs to be unbanned!`")
33 | else:
34 | id = message.reply_to_message.from_user.id
35 | x = un_gban(id)
36 | if x is False:
37 | await message.edit("`That user is not globally banned!`")
38 | else:
39 | await message.edit(f"**__{message.reply_to_message.from_user.mention}[{id}]__** has been unbanned")
40 |
--------------------------------------------------------------------------------
/annabelle/modules/github.py:
--------------------------------------------------------------------------------
1 | import json
2 | import requests
3 | from annabelle import Annabelle
4 | from config import MY_ID, HANDLER
5 | from pyrogram import filters as vrn
6 | from pyrogram.types.messages_and_media import Message
7 |
8 |
9 | @Annabelle.on_message(filters.command("github", HANDLER))
10 | async def github(bot:Annabelle, msg:Message) :
11 | if msg.from_user.id == MY_ID :
12 | args = msg.text.split(None, 1)
13 | if len(args) >= 2:
14 | query = args[1]
15 | await msg.edit("`searching github...`")
16 | try :
17 | get_url = f"https://api.github.com/search/users?q={query}"
18 | request1 = requests.get(get_url)
19 | json_data = request1.json()
20 | raw_data = json_data["items"]
21 | data_ = raw_data[0]
22 | url = data_["html_url"]
23 | request2 = requests.get(url)
24 | data = request2.json()
25 | await msg.edit_text(text=f""" **__Stdout__**
26 | **Query** : `{query}`
27 |
28 | **ID** : `{data["id"]}`
29 | **Url** : ʟɪɴᴋ
30 | **Type** : `{data["type"]}`
31 | **Name** : `{data["name"]}`
32 | **Login** : `{data["login"]}`
33 | **Public Repos** : `{data["public_repos"]}`
34 | **Following** : `{data["following"]}`
35 | **Followers** : `{data["followers"]}`
36 | **Email** : `{data["email"]}`
37 |
38 | **ANABELLE USERBOT**
39 | """)
40 | except :
41 | await msg.edit_text(text=f"**Couldnt find results for** `{query}`")
42 | else:
43 | await message.edit("`Give a username to search`")
44 |
45 |
--------------------------------------------------------------------------------
/annabelle/modules/help.py:
--------------------------------------------------------------------------------
1 | from pyrogram import Client, filters
2 | from pyrogram.types import Message
3 | from config import HANDLER
4 | from annabelle.modules.helpmenu.help_menu import modules_help
5 |
6 |
7 | @Client.on_message(filters.command(["help", "h"], prefixes=f"{HANDLER}") & filters.me)
8 | async def help(client, message: Message):
9 | module_name = " ".join(message.command[1:])
10 | if module_name == "":
11 | messages = [
12 | f"""Help for Annabelle Userbot\nFor more help on how to use a command, type {HANDLER}help [module]
\n\nAvailable Modules:\n"""
13 | ]
14 | msg_cnt = 0
15 | for mod in modules_help:
16 | help_message = (
17 | "• "
18 | + list(mod.keys())[0].title()
19 | + ": "
20 | + " ".join(
21 | [
22 | "" + HANDLER + str(cmd.split()[0]) + "
"
23 | for cmd in [
24 | list(rc.keys())[0] for rc in list(mod.values()).pop(0)
25 | ]
26 | ]
27 | )
28 | + "\n"
29 | )
30 | if len(messages[msg_cnt] + help_message) < 2048:
31 | messages[msg_cnt] = messages[msg_cnt] + help_message
32 | else:
33 | msg_cnt += 1
34 | messages.append(help_message)
35 | tc = """\nThe number of modules in the userbot: """ + str(
36 | float(len(modules_help))
37 | )
38 | if len(messages[msg_cnt] + tc) < 2048:
39 | messages[msg_cnt] += tc
40 | else:
41 | messages.append(tc)
42 | await message.edit(
43 | messages[0], parse_mode="HTML", disable_web_page_preview=True
44 | )
45 | messages.pop(0)
46 | for msg in messages:
47 | await message.reply(msg, parse_mode="HTML", disable_web_page_preview=True)
48 | else:
49 | text = f"Help for {module_name}\n\nUsage:\n"
50 | found = False
51 | for mh in modules_help:
52 | if list(mh.keys())[0].lower() == module_name.lower():
53 | found = True
54 | cmds = list(mh.values()).pop(0)
55 | for u_cmd in cmds:
56 | cmd = list(u_cmd.items())[0]
57 | text += f"""{HANDLER + cmd[0]}
- {cmd[1]}\n"""
58 | if found:
59 | await message.edit(text, parse_mode="HTML")
60 | else:
61 | await message.edit(f"Module {module_name} not found!")
62 |
63 |
64 | modules_help.append(
65 | {"help": [{"help [module name]": "To get help. Module name isn't required."}]}
66 | )
67 |
--------------------------------------------------------------------------------
/annabelle/modules/helpers/afk_handler.py:
--------------------------------------------------------------------------------
1 | # functions
2 |
3 | import datetime
4 | from pyrogram import Client, filters
5 |
6 | async def afk_handler(client, message):
7 | try:
8 | global start, end
9 | end = datetime.datetime.now().replace(microsecond=0)
10 | afk_dur = end - start
11 | user_is_bot = message.from_user.is_bot
12 | if user_is_bot is False:
13 | await message.reply_text(
14 | f"I afk {afk_dur}\n" f"Reason: {reason}"
15 | )
16 | except NameError:
17 | pass
18 |
--------------------------------------------------------------------------------
/annabelle/modules/helpers/mirror_func.py:
--------------------------------------------------------------------------------
1 | import os
2 | from PIL import ImageOps, Image
3 | from pyrogram import Client
4 |
5 | async def make(client, message, o):
6 | reply = message.reply_to_message
7 | if reply.photo or reply.sticker:
8 | if reply.photo:
9 | downloads = await client.download_media(reply.photo.file_id)
10 | else:
11 | downloads = await client.download_media(reply.sticker.file_id)
12 | path = f"{downloads}"
13 | img = Image.open(path)
14 | await message.delete()
15 | w, h = img.size
16 | if o in [1, 2]:
17 | if o == 2:
18 | img = ImageOps.mirror(img)
19 | part = img.crop([0, 0, w // 2, h])
20 | img = ImageOps.mirror(img)
21 | else:
22 | if o == 4:
23 | img = ImageOps.flip(img)
24 | part = img.crop([0, 0, w, h // 2])
25 | img = ImageOps.flip(img)
26 | img.paste(part, (0, 0))
27 | img.save(path)
28 | if reply.photo:
29 | return await reply.reply_photo(photo=path)
30 | elif reply.sticker:
31 | return await reply.reply_sticker(sticker=path)
32 | os.remove(path)
33 |
34 | return await message.edit("Need to answer the photo/sticker")
35 |
36 |
--------------------------------------------------------------------------------
/annabelle/modules/helpmenu/help_menu.py:
--------------------------------------------------------------------------------
1 | modules_help = []
2 | requirements_list = []
3 |
--------------------------------------------------------------------------------
/annabelle/modules/inline.py:
--------------------------------------------------------------------------------
1 | from config import MY_ID, HANDLER
2 | from annabelle import Annabelle
3 | from pyrogram import Client
4 | from pyrogram import filters as vrn
5 | from pyrogram.types.messages_and_media import Message
6 |
7 |
8 | @Annabelle.on_message(vrn.command("inline", HANDLER))
9 | async def inline(bot:Annabelle, msg:Message) :
10 | chat_id = msg.chat.id
11 | peer_id = "Annabellev1_bot"
12 | try :
13 | try :
14 | chat_id = 5292470029
15 | await bot.send_message(chat_id, text="/start")
16 | except :
17 | user_id = 5292470029
18 | await bot.unblock_user(user_id)
19 | await bot.send_message(chat_id=user_id, text="/start")
20 | except :
21 | await bot.resolve_peer(peer_id)
22 |
23 | result = await bot.get_inline_bot_results(bot=peer_id, query="inline")
24 | query_id = result.query_id
25 | result_id = result.results[0].id
26 | await bot.send_inline_bot_result(chat_id, query_id, result_id)
27 |
--------------------------------------------------------------------------------
/annabelle/modules/leave.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | from pyrogram import Client, filters
3 | from annabelle.modules.helpmenu.help_menu import modules_help
4 | from config import HANDLER
5 |
6 |
7 | @Client.on_message(
8 | filters.command(["leave", "lc"], prefixes=f"{HANDLER}") & filters.me
9 | )
10 | async def leave_chat(client: Client, message):
11 | chat = message.chat.type
12 | chat_id = message.chat.id
13 | if chat in ["group", "supergroup"]:
14 | await message.edit("My Master Doesn't Like This Chat, Leaving Bye...")
15 | await asyncio.sleep(3)
16 | await client.leave_chat(chat_id)
17 | else:
18 | await message.edit("This chat is not in group or supergroup")
19 |
20 | modules_help.append(
21 | {"leave": [{"leave" or "lc": "Leaves chat"}]
22 | )
23 |
24 | # most of the codes are simple because of time limitation
25 | # there will more features will pushed through some updates
26 |
27 |
--------------------------------------------------------------------------------
/annabelle/modules/mirror.py:
--------------------------------------------------------------------------------
1 | from pyrogram import Client, filters
2 | from pyrogram.types import Message
3 | from config import HANDLER
4 | from annabelle.modules.helpmenu.help_menu import modules_help
5 | from annabelle.modules.helpers.mirror_func import make
6 |
7 | @Client.on_message(
8 | filters.command(["ll", "rr", "dd", "uu"], prefixes=f"{HANDLER}") & filters.me
9 | )
10 | async def mirror_flip(client: Client, message: Message):
11 | await message.edit("Processing...
")
12 | param = {"ll": 1, "rr": 2, "dd": 3, "uu": 4}[message.command[0]]
13 | await make(client, message, param)
14 |
15 |
16 | modules_help.append(
17 | {
18 | "mirror_flip": [
19 | {"ll [reply on photo or sticker]*": "reflects the left side"},
20 | {"rr [reply on photo or sticker]*": "reflects the right side"},
21 | {"uu [reply on photo or sticker]*": "reflects the top"},
22 | {"dd [reply on photo or sticker]*": "reflects the bottom"},
23 | ]
24 | }
25 | )
26 |
--------------------------------------------------------------------------------
/annabelle/modules/pin.py:
--------------------------------------------------------------------------------
1 | from config import HANDLER
2 | from annabelle import logger
3 | from annabelle import Annabelle
4 |
5 | from pyrogram import filters
6 | from pyrogram.types import Message
7 | from pyrogram.errors import ChatAdminRequired, RightForbidden, RPCError
8 |
9 | @Annabelle.on_message(filters.command('pin', HANDLER) & filters.group)
10 | async def pin(client: Annabelle, message: Message):
11 | admins = await client.get_chat_member(message.chat.id, message.from_user.id)
12 | if not ((admins.status == "administrator") or (admins.status == "creator")):
13 | await message.reply_text("**Your not allowed to use this.**")
14 | return
15 | if not message.reply_to_message:
16 | await message.reply_text("**Reply to a message to pin.**")
17 | return
18 | try:
19 | message.reply_to_message.pin()
20 | logger.info(
21 | f"I have pinned a message in {message.chat.id}\nMessage link: {message.reply_to_message.link}"
22 | )
23 | await message.edit("Pinned successfully!
")
24 | except ChatAdminRequired:
25 | await message.reply_text("I am not admin here.")
26 | #expect RightForbidden:
27 | #await message.reply_text("I don't have enough rights to pin messages.")
28 | #expect RPCError as e:
29 | #await message.reply_text(f"Some error occurred\n\n*Error:*\n{e}")
30 |
31 | @Annabelle.on_message(filters.command('unpin', HANDLER))
32 | async def unpin(client: Annabelle, message: Message):
33 | if not ((admins.status == "administrator") or (admins.status == "creator")):
34 | await message.reply_text("**Your not allowed to use this.**")
35 | return
36 | if not message.reply_to_message:
37 | await message.reply_text("**Reply to a message to pin.**")
38 | return
39 | try:
40 | message.reply_to_message.pin()
41 | logger.info(
42 | f"I have unpinned a message in {message.chat.id}\nMessage link: {message.reply_to_message.link}"
43 | )
44 | await message.edit("Unpinned successfully!
")
45 | except ChatAdminRequired:
46 | await message.reply_text("I am not admin here.")
47 | #expect RightForbidden:
48 | #await message.reply_text("I don't have enough rights to unpin messages.")
49 | #expect RPCError as error:
50 | #await message.reply_text(f"Some error occurred\n\n*Error:*\n{error}")
51 |
--------------------------------------------------------------------------------
/annabelle/modules/ping.py:
--------------------------------------------------------------------------------
1 | from datetime import datetime
2 | from time import time
3 | from pyrogram import Client, filters
4 | from pyrogram.types import Message
5 | from config import HANDLER
6 | from annabelle.modules.helpmenu.help_menu import modules_help
7 |
8 | # System Uptime
9 | START_TIME = datetime.utcnow()
10 | TIME_DURATION_UNITS = (
11 | ("Week", 60 * 60 * 24 * 7),
12 | ("Day", 60 * 60 * 24),
13 | ("Hour", 60 * 60),
14 | ("Min", 60),
15 | ("Sec", 1),
16 | )
17 |
18 |
19 | async def _human_time_duration(seconds):
20 | if seconds == 0:
21 | return "inf"
22 | parts = []
23 | for unit, div in TIME_DURATION_UNITS:
24 | amount, seconds = divmod(int(seconds), div)
25 | if amount > 0:
26 | parts.append("{} {}{}".format(amount, unit, "" if amount == 1 else ""))
27 | return ", ".join(parts)
28 |
29 |
30 | @Client.on_message(filters.command(["ping"], prefixes=f"{HNDLR}"))
31 | async def ping(client, m: Message):
32 | start = time()
33 | current_time = datetime.utcnow()
34 | m_reply = await m.reply_text("⚡️")
35 | delta_ping = time() - start
36 | uptime_sec = (current_time - START_TIME).total_seconds()
37 | uptime = await _human_time_duration(int(uptime_sec))
38 | await m_reply.edit(
39 | f"🤴I'm Online\n📟`{delta_ping * 1000:.3f} ms` \n⏱️Uptime - `{uptime}`"
40 | )
41 |
42 |
43 | modules_help.append({"ping": [{"ping": "To find out the ping"}]})
44 |
--------------------------------------------------------------------------------
/annabelle/modules/pmpermit.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | from asyncio import sleep
3 | from pyrogram import filters
4 | from config import SUDO_USERS, HANDLER
5 | from pmpermit_db import check_permit, add_permit, del_permit
6 | from annabelle import Annabelle
7 | PM_PERMIT = False
8 |
9 | @Annabelle.on_message(filters.command('a', HANDLER) & filters.me)
10 | async def addpm(Annabelle, message):
11 | if message.reply_to_message:
12 | id = message.reply_to_message.from_user.id
13 | x = add_permit(id)
14 | if x is False:
15 | await message.edit("`That user is already permitted`")
16 | asyncio.sleep(3)
17 | await message.delete()
18 | else:
19 | await message.edit("`That user can send pm messages`")
20 | else:
21 | await message.edit("`Reply to that user's message`")
22 |
23 | @Annabelle.on_message(filters.command('una', HANDLER) & filters.me)
24 | async def delpm(Annabelle, message):
25 | if messege.reply_to_message:
26 | id = message.reply_to_message.from_user.id
27 | x = del_permit(id)
28 | if x is False:
29 | await message.edit("`That user was not even approved`")
30 | else:
31 | await message.edit("`That user is unapproved to pm you`")
32 | else:
33 | await message.edit("`Reply to that user's message`")
34 |
35 | @Annabelle.on_message(filters.command('pmpermit', HANDLER) & filters.me)
36 | async def togglepm(Annabelle, message, PM_PERMIT):
37 | args = message.text.split(None, 1)
38 | if len(args) >= 2:
39 | toggle = args[1]
40 | if toggle.lower() in ['on', 'yes', 'true']:
41 | PM_PERMIT = True
42 | await message.edit("`PM guard turned on`")
43 | elif toggle.lower() in ['no', 'off', 'false']:
44 | PM_PERMIT = True
45 | await message.edit("`PM guard turned off`")
46 | else:
47 | await message.edit("`What are you saying?`")
48 | else:
49 | await message.edit("`Command incomplete`")
50 |
51 | @Annabelle.on_message(filters.private & filters.incoming)
52 | async def testpm(Annabelle, message, PM_PERMIT):
53 | while PM_PERMIT is True:
54 | id = message.from_user.id
55 | x = check_permit(id)
56 | if x is not True:
57 | await message.delete()
58 | await Annabelle.send_message(message.chat.id, PM_TEXT)
59 | else:
60 | continue
61 |
--------------------------------------------------------------------------------
/annabelle/modules/purge.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 |
3 | from config import HANDLER
4 | from annabelle.modules.helpmenu.help_menu import modules_help
5 |
6 | from pyrogram.types import Message
7 | from pyrogram import Client, filters
8 |
9 | @Client.on_message(filters.command("del", HANDLER) & filters.me)
10 | async def del_msg(client: Client, message: Message):
11 | if not message.reply_to_message:
12 | await message.reply_text("Reply to message to delete")
13 | return
14 | message_id = message.reply_to_message.message_id
15 | await message.delete()
16 | await client.delete_messages(
17 | chat_id=message.chat.id,
18 | message_ids=message_id,
19 | )
20 | k = await message.reply("I've deleted the message for you")
21 | await asyncio.sleep(3)
22 | await k.delete()
23 |
24 | @Client.on_message(filters.command("purge", HANDLER) & filters.me)
25 | async def purge(client: Client, message: Message):
26 | messages_to_purge = []
27 | if not message.reply_to_message:
28 | await message.reply_text("Reply to message to purge")
29 | return
30 | async for msg in client.iter_history(
31 | chat_id=message.chat.id,
32 | offset_id=message.reply_to_message.message_id,
33 | reverse=True,
34 | ):
35 | messages_to_purge.append(msg.message_id)
36 | for msgs in [
37 | messages_to_purge[i : i + 1000] for i in range(0, len(messages_to_purge), 1000)
38 | ]:
39 | await client.delete_messages(message.chat.id, msgs)
40 | await asyncio.sleep(1)
41 | await message.reply("Purge completed")
42 | await asyncio.sleep(2)
43 | await message.delete()
44 |
45 |
46 | modules_help.append(
47 | {
48 | "purge": [
49 | {
50 | "purge [reply]*": "Reply to a message after which you want to delete messages"
51 | },
52 | {"del [reply]*": "Reply to the message you want to delete"},
53 | ]
54 | }
55 | )
56 |
--------------------------------------------------------------------------------
/annabelle/modules/qoutly.py:
--------------------------------------------------------------------------------
1 | import base64
2 | import os
3 | from io import BytesIO
4 | import requests
5 | from pyrogram import Client, errors, filters, types
6 | from config import HANDLER
7 | from annabelle.modules.helpmenu.help_menu import modules_help
8 |
9 |
10 | @Client.on_message(filters.command(["q", "quote"], prefixes=f"{HANDLER}") & filters.me)
11 | async def quote_cmd(client: Client, message: types.Message):
12 | if not message.reply_to_message:
13 | return await message.edit("Specify message(s) for quote")
14 |
15 | if len(message.command) > 1 and message.command[1].isdigit():
16 | count = int(message.command[1])
17 | if count < 1:
18 | count = 1
19 | elif count > 15:
20 | count = 15
21 | else:
22 | count = 1
23 |
24 | is_png = "!png" in message.command or "!file" in message.command
25 | send_for_me = "!me" in message.command or "!ls" in message.command
26 | no_reply = "!noreply" in message.command or "!nr" in message.command
27 |
28 | messages = list(
29 | filter(
30 | lambda x: x.message_id < message.message_id,
31 | await client.get_messages(
32 | message.chat.id,
33 | range(
34 | message.reply_to_message.message_id,
35 | message.reply_to_message.message_id + count,
36 | ),
37 | ),
38 | )
39 | )
40 |
41 | if no_reply:
42 | messages[0].reply_to_message = None
43 |
44 | if send_for_me:
45 | await message.delete()
46 | message = await client.send_message("me", "Generating...")
47 | else:
48 | await message.edit("Generating...")
49 |
50 | url = "https://quotes.fl1yd.su/generate"
51 | params = {
52 | "messages": [
53 | await render_message(client, msg) for msg in messages if not msg.empty
54 | ],
55 | "quote_color": "#162330",
56 | "text_color": "#fff",
57 | }
58 |
59 | response = requests.post(url, json=params)
60 | if not response.ok:
61 | return await message.edit(
62 | f"Quotes API error!\n" f"{response.text}
"
63 | )
64 |
65 | file_io = BytesIO(response.content)
66 | file_io.name = "sticker.png" if is_png else "sticker.webp"
67 | await message.edit("Sending...")
68 |
69 | try:
70 | func = client.send_document if is_png else client.send_sticker
71 | chat_id = "me" if send_for_me else message.chat.id
72 | await func(chat_id, file_io)
73 | except errors.RPCError as e: # no rights to send stickers, etc
74 | await message.edit(f"Telegram API error!\n" f"{e}
")
75 | else:
76 | await message.delete()
77 |
78 |
79 | @Client.on_message(
80 | filters.command(["fq", "fakequote"], prefixes=f"{HANDLER}") & filters.me
81 | )
82 | async def fake_quote_cmd(client: Client, message: types.Message):
83 | if not message.reply_to_message:
84 | return await message.edit("Specify message for fake quote")
85 |
86 | is_png = "!png" in message.command or "!file" in message.command
87 | send_for_me = "!me" in message.command or "!ls" in message.command
88 | no_reply = "!noreply" in message.command or "!nr" in message.command
89 |
90 | fake_quote_text = " ".join(
91 | [
92 | arg
93 | for arg in message.command[1:]
94 | if arg not in ["!png", "!file", "!me", "!ls", "!noreply", "!nr"]
95 | ] # remove some special arg words
96 | )
97 |
98 | if not fake_quote_text:
99 | return await message.edit("Fake quote text is empty")
100 |
101 | q_message = await client.get_messages(
102 | message.chat.id, message.reply_to_message.message_id
103 | )
104 | q_message.text = fake_quote_text
105 | q_message.entities = None
106 | if no_reply:
107 | q_message.reply_to_message = None
108 |
109 | if send_for_me:
110 | await message.delete()
111 | message = await client.send_message("me", "Generating...")
112 | else:
113 | await message.edit("Generating...")
114 |
115 | url = "https://quotes.fl1yd.su/generate"
116 | params = {
117 | "messages": [await render_message(client, q_message)],
118 | "quote_color": "#162330",
119 | "text_color": "#fff",
120 | }
121 |
122 | response = requests.post(url, json=params)
123 | if not response.ok:
124 | return await message.edit(
125 | f"Quotes API error!\n" f"{response.text}
"
126 | )
127 |
128 | file_io = BytesIO(response.content)
129 | file_io.name = "sticker.png" if is_png else "sticker.webp"
130 | await message.edit("Sending...")
131 |
132 | try:
133 | func = client.send_document if is_png else client.send_sticker
134 | chat_id = "me" if send_for_me else message.chat.id
135 | await func(chat_id, file_io)
136 | except errors.RPCError as e: # no rights to send stickers, etc
137 | await message.edit(f"Telegram API error!\n" f"{e}
")
138 | else:
139 | await message.delete()
140 |
141 |
142 | files_cache = {}
143 |
144 |
145 | async def render_message(app: Client, message: types.Message) -> dict:
146 | async def get_file(file_id) -> str:
147 | if file_id in files_cache:
148 | return files_cache[file_id]
149 |
150 | file_name = await app.download_media(file_id)
151 | with open(file_name, "rb") as f:
152 | content = f.read()
153 | os.remove(file_name)
154 | data = base64.b64encode(content).decode()
155 | files_cache[file_id] = data
156 | return data
157 |
158 | # text
159 | if message.photo:
160 | text = message.caption if message.caption else ""
161 | elif message.poll:
162 | text = get_poll_text(message.poll)
163 | elif message.sticker:
164 | text = ""
165 | else:
166 | text = get_reply_text(message)
167 |
168 | # media
169 | if message.photo:
170 | media = await get_file(message.photo.file_id)
171 | elif message.sticker:
172 | media = await get_file(message.sticker.file_id)
173 | else:
174 | media = ""
175 |
176 | # entities
177 | entities = []
178 | if message.entities:
179 | for entity in message.entities:
180 | entities.append(
181 | {
182 | "offset": entity.offset,
183 | "length": entity.length,
184 | "type": entity.type,
185 | }
186 | )
187 |
188 | def move_forwards(msg: types.Message):
189 | if msg.forward_from:
190 | msg.from_user = msg.forward_from
191 | elif msg.forward_sender_name:
192 | msg.from_user.id = 0
193 | msg.from_user.first_name = msg.forward_sender_name
194 | msg.from_user.last_name = ""
195 | elif msg.forward_from_chat:
196 | msg.sender_chat = msg.forward_from_chat
197 |
198 | move_forwards(message)
199 |
200 | # author
201 | author = {}
202 | if message.from_user:
203 | author["id"] = message.from_user.id
204 | author["name"] = get_full_name(message.from_user)
205 | if message.chat.type != "supergroup" or message.from_user.id == 0:
206 | author["rank"] = ""
207 | else:
208 | try:
209 | member = await message.chat.get_member(message.from_user.id)
210 | except errors.UserNotParticipant:
211 | author["rank"] = ""
212 | else:
213 | author["rank"] = getattr(member, "title", "") or (
214 | "owner"
215 | if member.status == "creator"
216 | else "admin"
217 | if member.status == "administrator"
218 | else ""
219 | )
220 |
221 | if message.from_user.id == 0 or not message.from_user.photo:
222 | author["avatar"] = ""
223 | else:
224 | author["avatar"] = await get_file(message.from_user.photo.big_file_id)
225 | else:
226 | author["id"] = message.sender_chat.id
227 | author["name"] = message.sender_chat.title
228 | author["rank"] = "channel" if message.sender_chat.type == "channel" else ""
229 |
230 | if message.sender_chat.photo:
231 | author["avatar"] = await get_file(message.sender_chat.photo.big_file_id)
232 | else:
233 | author["avatar"] = ""
234 | author["via_bot"] = message.via_bot.username if message.via_bot else ""
235 |
236 | # reply
237 | reply = {}
238 | reply_msg = message.reply_to_message
239 | if reply_msg and not reply_msg.empty:
240 | move_forwards(reply_msg)
241 |
242 | if reply_msg.from_user:
243 | reply["id"] = reply_msg.from_user.id
244 | reply["name"] = get_full_name(reply_msg.from_user)
245 | else:
246 | reply["id"] = reply_msg.sender_chat.id
247 | reply["name"] = reply_msg.sender_chat.title
248 |
249 | reply["text"] = get_reply_text(reply_msg)
250 |
251 | return {
252 | "text": text,
253 | "media": media,
254 | "entities": entities,
255 | "author": author,
256 | "reply": reply,
257 | }
258 |
259 |
260 | def get_audio_text(audio: types.Audio) -> str:
261 | if audio.title and audio.performer:
262 | return f" ({audio.title} — {audio.performer})"
263 | elif audio.title:
264 | return f" ({audio.title})"
265 | elif audio.performer:
266 | return f" ({audio.performer})"
267 | else:
268 | return ""
269 |
270 |
271 | def get_reply_text(reply: types.Message) -> str:
272 | return (
273 | "📷 Photo" + ("\n" + reply.caption if reply.caption else "")
274 | if reply.photo
275 | else get_reply_poll_text(reply.poll)
276 | if reply.poll
277 | else "📍 Location"
278 | if reply.location or reply.venue
279 | else "👤 Contact"
280 | if reply.contact
281 | else "🖼 GIF"
282 | if reply.animation
283 | else "🎧 Music" + get_audio_text(reply.audio)
284 | if reply.audio
285 | else "📹 Video"
286 | if reply.video
287 | else "📹 Videomessage"
288 | if reply.video_note
289 | else "🎵 Voice"
290 | if reply.voice
291 | else (reply.sticker.emoji + " " if reply.sticker.emoji else "") + "Sticker"
292 | if reply.sticker
293 | else "💾 File " + reply.document.file_name
294 | if reply.document
295 | else "🎮 Game"
296 | if reply.game
297 | else "🎮 set new record"
298 | if reply.game_high_score
299 | else f"{reply.dice.emoji} - {reply.dice.value}"
300 | if reply.dice
301 | else (
302 | "👤 joined the group"
303 | if reply.new_chat_members[0].id == reply.from_user.id
304 | else "👤 invited %s to the group"
305 | % (get_full_name(reply.new_chat_members[0]))
306 | )
307 | if reply.new_chat_members
308 | else (
309 | "👤 left the group"
310 | if reply.left_chat_member.id == reply.from_user.id
311 | else "👤 removed %s" % (get_full_name(reply.left_chat_member))
312 | )
313 | if reply.left_chat_member
314 | else f"✏ changed group name to {reply.new_chat_title}"
315 | if reply.new_chat_title
316 | else "🖼 changed group photo"
317 | if reply.new_chat_photo
318 | else "🖼 removed group photo"
319 | if reply.delete_chat_photo
320 | else "📍 pinned message"
321 | if reply.pinned_message
322 | else "🎤 started a new video chat"
323 | if reply.voice_chat_started
324 | else "🎤 ended the video chat"
325 | if reply.voice_chat_ended
326 | else "🎤 invited participants to the video chat"
327 | if reply.voice_chat_members_invited
328 | else "👥 created the group"
329 | if reply.group_chat_created or reply.supergroup_chat_created
330 | else "👥 created the channel"
331 | if reply.channel_chat_created
332 | else reply.text or "unsupported message"
333 | )
334 |
335 |
336 | def get_poll_text(poll: types.Poll) -> str:
337 | text = get_reply_poll_text(poll) + "\n"
338 |
339 | text += poll.question + "\n"
340 | for option in poll.options:
341 | text += f"- {option.text}"
342 | if option.voter_count > 0:
343 | text += f" ({option.voter_count} voted)"
344 | text += "\n"
345 |
346 | text += f"Total: {poll.total_voter_count} voted"
347 |
348 | return text
349 |
350 |
351 | def get_reply_poll_text(poll: types.Poll) -> str:
352 | if poll.is_anonymous:
353 | text = "📊 Anonymous poll" if poll.type == "regular" else "📊 Anonymous quiz"
354 | else:
355 | text = "📊 Poll" if poll.type == "regular" else "📊 Quiz"
356 | if poll.is_closed:
357 | text += " (closed)"
358 |
359 | return text
360 |
361 |
362 | def get_full_name(user: types.User) -> str:
363 | name = user.first_name
364 | if user.last_name:
365 | name += " " + user.last_name
366 | return name
367 |
368 |
369 | modules_help.append(
370 | {
371 | "squotes": [
372 | {
373 | "q [reply]* [count] [args]": "Generate a quote\nAvailable args: !png — send a quote as png; !me — send a quote to saved messages; !noreply - make a quote without reply message"
374 | },
375 | {"fq [reply]* [args] [text]": "Generate a fake quote"},
376 | ]
377 | }
378 | )
379 |
--------------------------------------------------------------------------------
/annabelle/modules/screenshot.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | from pyrogram import Client, filters
3 | from pyrogram.raw import functions
4 | from pyrogram.types import Message
5 | from config import HANDLER
6 | from annabelle.modules.helpmenu.help_menu import modules_help
7 |
8 | @Client.on_message(
9 | filters.command(["scr", "screenshot"], prefixes=f"{HANDLER}") & filters.me
10 | )
11 | async def scrshot(client: Client, message: Message):
12 | quantity = int(message.command[1])
13 | chat = message.chat.id
14 | await message.delete()
15 | for _ in range(quantity):
16 | await asyncio.sleep(2)
17 | await client.send(
18 | functions.messages.SendScreenshotNotification(
19 | peer = await client.resolve_peer(chat),
20 | reply_to_msg_id = 0,
21 | random_id = rnd_id(),
22 | )
23 | )
24 |
25 |
26 | modules_help.append(
27 | {
28 | "screenshot": [
29 | {
30 | "scr [amount of screenshots]": "Take a screenshot\nThis only works in private messages!"
31 | }
32 | ]
33 | }
34 | )
35 |
--------------------------------------------------------------------------------
/annabelle/modules/sendmod.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import os
3 | from pyrogram import Client, filters
4 | from pyrogram.types import Message
5 | from config import HANDLER
6 | from annabelle.modules.helpmenu.help_menu import modules_help
7 |
8 |
9 | @Client.on_message(filters.command(["sendmod", "sm"], prefixes=f"{HANDLER}") & filters.me)
10 | async def sendmod(client: Client, message: Message):
11 | module_name = message.command[1]
12 | try:
13 | await message.edit("Dispatch...
")
14 | text = f"Help for {module_name}\n\nUsage:\n"
15 | found = False
16 | for mh in modules_help:
17 | if list(mh.keys())[0].lower() == module_name.lower():
18 | found = True
19 | cmds = list(mh.values()).pop(0)
20 | for u_cmd in cmds:
21 | cmd = list(u_cmd.items())[0]
22 | text += f"""{HNDLR + cmd[0]}
- {cmd[1]}\n"""
23 | if not found:
24 | text = "Module {module_name} not found!"
25 |
26 | if os.path.isfile(f"Mister_Dark_Prince/{module_name.lower()}.py"):
27 | await client.send_document(
28 | message.chat.id,
29 | f"Mister_Dark_Prince/{module_name.lower()}.py",
30 | caption=text,
31 | )
32 | elif os.path.isfile(
33 | f"Mister_Dark_Prince/custom_modules/{module_name.lower()}.py"
34 | ):
35 | await client.send_document(
36 | message.chat.id,
37 | f"Mister_Dark_Prince/custom_modules/{module_name.lower()}.py",
38 | caption=text,
39 | )
40 | await message.delete()
41 | except:
42 | await message.edit("Invalid module name!")
43 | await asyncio.sleep(5)
44 | await message.delete()
45 |
46 |
47 | modules_help.append(
48 | {
49 | "sendmod": [
50 | {"sendmod [module name]*": "Send one of the modules to the interlocutor"}
51 | ]
52 | }
53 | )
54 |
--------------------------------------------------------------------------------
/annabelle/modules/set.py:
--------------------------------------------------------------------------------
1 | from annabelle import Annabelle
2 | from pyrogram import filters as vrn
3 |
4 | @Annabelle.on_message(vrn.command('setemoji', HANDLER))
5 | async def setemoji(Annabelle, message):
6 | if message.from_user.id == MY_ID:
7 | args = message.text.split(None, 1)
8 | if len(args) >= 2:
9 | ALIVE_EMOJI = args[1]
10 | await message.edit(f"`ALIVE_EMOJI has been set to {ALIVE_EMOJI}")
11 |
12 | else:
13 | await message.edit("`At least mention what to reply with!`")
14 |
15 | @Annabelle.on_message(vrn.command('alivepic', HANDLER))
16 | async def setpic(Annabelle, message):
17 | if message.from_user.id == MY_ID:
18 | args = message.text.split(None, 1)
19 | if len(args) >= 2:
20 | x = args[1]
21 | if x.endswith["jpg", "jpeg", "png"]:
22 | ALIVE_IMG = x
23 | await message.edit(f"ALIVE_IMG has been set to {ALIVE_IMG}")
24 | else:
25 | await message.edit("`Available types are jpg, jpeg, png.`")
26 | else:
27 | await message.edit("`Set to what?`")
28 |
--------------------------------------------------------------------------------
/annabelle/modules/spam.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | from pyrogram import Client, filters
3 | from pyrogram.types import Message
4 | from config import HANDLER
5 | from annabelle.modules.helpmenu.help_menu import modules_help
6 |
7 |
8 | @Client.on_message(filters.command("spamstats", prefixes=f"{HANDLER}") & filters.me)
9 | async def statspam(client: Client, message: Message):
10 | quantity = message.command[1]
11 | spam_text = " ".join(message.command[2:])
12 | quantity = int(quantity)
13 | await message.delete()
14 | for _ in range(quantity):
15 | msg = await client.send_message(message.chat.id, spam_text)
16 | await asyncio.sleep(0.1)
17 | await msg.delete()
18 | await asyncio.sleep(0.1)
19 |
20 |
21 | @Client.on_message(filters.command("spam", prefixes=f"{HANDLER}") & filters.me)
22 | async def spam(client: Client, message: Message):
23 | quantity = message.command[1]
24 | spam_text = " ".join(message.command[2:])
25 | quantity = int(quantity)
26 | await message.delete()
27 |
28 | if message.reply_to_message:
29 | reply_to_id = message.reply_to_message.message_id
30 | for _ in range(quantity):
31 | await client.send_message(
32 | message.chat.id, spam_text, reply_to_message_id=reply_to_id
33 | )
34 | await asyncio.sleep(0.15)
35 | return
36 |
37 | for _ in range(quantity):
38 | await client.send_message(message.chat.id, spam_text)
39 | await asyncio.sleep(0.15)
40 |
41 |
42 | @Client.on_message(filters.command("fastspam", prefixes=f"{HANDLER}") & filters.me)
43 | async def fastspam(client: Client, message: Message):
44 | quantity = message.command[1]
45 | spam_text = " ".join(message.command[2:])
46 | quantity = int(quantity)
47 | await message.delete()
48 |
49 | if message.reply_to_message:
50 | reply_to_id = message.reply_to_message.message_id
51 | for _ in range(quantity):
52 | await client.send_message(
53 | message.chat.id, spam_text, reply_to_message_id=reply_to_id
54 | )
55 | await asyncio.sleep(0.02)
56 | return
57 |
58 | for _ in range(quantity):
59 | await client.send_message(message.chat.id, spam_text)
60 | await asyncio.sleep(0.02)
61 |
62 |
63 | @Client.on_message(filters.command("slowspam", prefixes=f"{HANDLER}") & filters.me)
64 | async def slowspam(client: Client, message: Message):
65 | quantity = message.command[1]
66 | spam_text = " ".join(message.command[2:])
67 | quantity = int(quantity)
68 | await message.delete()
69 |
70 | if message.reply_to_message:
71 | reply_to_id = message.reply_to_message.message_id
72 | for _ in range(quantity):
73 | await client.send_message(
74 | message.chat.id, spam_text, reply_to_message_id=reply_to_id
75 | )
76 | await asyncio.sleep(0.9)
77 | return
78 |
79 | for _ in range(quantity):
80 | await client.send_message(message.chat.id, spam_text)
81 | await asyncio.sleep(0.9)
82 |
83 |
84 | modules_help.append(
85 | {
86 | "spam": [
87 | {"spam [amount of spam]* [spam text]*": "Start spam"},
88 | {"statspam [amount of spam]* [spam text]*": "Send and delete"},
89 | {"fastspam [amount of spam]* [spam text]*": "Start fast spam"},
90 | {"slowspam [amount of spam]* [spam text]*": "Start slow spam"},
91 | ]
92 | }
93 | )
94 |
--------------------------------------------------------------------------------
/annabelle/modules/tagall.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | from pyrogram import Client, filters
3 | from pyrogram.types import Message
4 | from config import HANDLER
5 | from annabelle.modules.helpmenu.help_menu import modules_help
6 |
7 | @Client.on_message(filters.command("tagall", prefixes=f"{HANDLER}") & filters.me)
8 | async def tagall(client: Client, message: Message):
9 | await message.delete()
10 | chat_id = message.chat.id
11 | string = ""
12 | limit = 1
13 | icm = client.iter_chat_members(chat_id)
14 | async for member in icm:
15 | tag = member.user.username
16 | if limit <= 10:
17 | string += f"@{tag}\n" if tag != None else f"{member.user.mention}\n"
18 | limit += 1
19 | else:
20 | await client.send_message(chat_id, text=string)
21 | limit = 1
22 | string = ""
23 | await asyncio.sleep(2)
24 |
25 |
26 | modules_help.append({"tagall": [{"tagall": "Tag all members"}]})
27 |
--------------------------------------------------------------------------------
/annabelle/modules/thumbnail.py:
--------------------------------------------------------------------------------
1 | import ytthumb
2 | from pyrogram import Client, filters as vrn
3 |
4 | @Client.on_message(vrn.command('thumb', prefixes=f"{HANDLER}) & filter.me)
5 | async def thumb(Client, message):
6 | try:
7 | args = message.text.split(None, 1)
8 | d=await message.reply("```Processing...```")
9 | link=args[1]
10 | thumb=ytthumb.thumbnail(video=link,
11 | quality="maxres")
12 | await message.reply_photo(photo=thumb)
13 | await d.delete()
14 | except:
15 | await message.reply("No results found!\nTry to check your link..")
16 | await d.delete()
17 |
--------------------------------------------------------------------------------
/annabelle/modules/typewritter.py:
--------------------------------------------------------------------------------
1 | # don't type large text.. Your account will be banned ❗️
2 |
3 | import asyncio
4 | import time
5 | from pyrogram import Client, filters
6 | from pyrogram.errors import FloodWait
7 | from pyrogram.types import Message
8 | from config import HANDLER
9 | from annabelle.modules.helpmenu.help_menu import modules_help
10 |
11 | @Client.on_message(filters.command("type", prefixes=f"{HANDLER}") & filters.me)
12 | async def type(client: Client, message: Message):
13 | orig_text = " ".join(message.command[1:])
14 | text = orig_text
15 | tbp = ""
16 | typing_symbol = "⌨️"
17 |
18 | while tbp != text:
19 | try:
20 | await message.edit(tbp + typing_symbol)
21 | await asyncio.sleep(0.1)
22 |
23 | tbp += text[0]
24 | text = text[1:]
25 |
26 | await message.edit(tbp)
27 | await asyncio.sleep(0.1)
28 |
29 | except FloodWait as e:
30 | time.sleep(e.x)
31 |
32 |
33 | modules_help.append(
34 | {
35 | "type": [
36 | {
37 | "type [text]*": "Typing emulation\nDon't use for a lot of characters. Your account may be banned!"
38 | }
39 | ]
40 | }
41 | )
42 |
--------------------------------------------------------------------------------
/annabelle/modules/wiki.py:
--------------------------------------------------------------------------------
1 | import wikipedia
2 | from pyrogram import Client, filters
3 | from pyrogram.types import Message
4 | from config import HANDLER
5 | from annabelle.modules.helpmenu.help_menu import modules_help
6 |
7 | @Client.on_message(filters.command("wiki", prefixes=f"{HANDLER}") & filters.me)
8 | async def wiki(client: Client, message: Message):
9 | lang = message.command[1]
10 | user_request = " ".join(message.command[2:])
11 | if user_request == "":
12 | wikipedia.set_lang("en")
13 | user_request = " ".join(message.command[1:])
14 | try:
15 | if lang == "ml":
16 | wikipedia.set_lang("ml")
17 |
18 | result = wikipedia.summary(user_request)
19 | await message.edit(
20 | f"""Request:
21 | {user_request}
22 | Result:
23 | {result}
"""
24 | )
25 |
26 | except Exception as exc:
27 | await message.edit(
28 | f"""Request:
29 | {user_request}
30 | Result:
31 | {exc}
"""
32 | )
33 |
34 |
35 | modules_help.append(
36 | {"wikipedia": [{"wiki [lang] [request]*": "Search in Russian Wikipedia"}]}
37 | )
38 |
39 | requirements_list.append("wikipedia")
40 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Annabelle UserBot",
3 | "description": "A powerful userbot fully running in pyrogram .",
4 | "keywords": [
5 | "Telegram",
6 | "Userbot",
7 | "Heroku",
8 | "PyrogramUserBot"
9 | ],
10 | "repository": "https://github.com/AnnabelleTG/Annabelle",
11 | "website": "https://t.me/AnnabelleUB",
12 | "success_url": "https://github.com/AnnabelleTG/Annabelle",
13 | "env": {
14 | "API_ID": {
15 | "description": "API_ID from website or bot",
16 | "required": "True"
17 | },
18 | "API_HASH": {
19 | "description": "You can get this from @s4h_api_idbot",
20 | "required": "True"
21 | },
22 | "BOT_TOKEN": {
23 | "description": "Give a Bot token. Get it from @botfather",
24 | "required": "True"
25 | },
26 | "SESSION_STRING": {
27 | "description": "Your telegram session must be pyrogram session use @Pyrogram_String_Bot",
28 | "required": "True"
29 | },
30 | "DATABASE_NAME": {
31 | "description": "Your mongodb database name (use any name)",
32 | "required": "True"
33 | },
34 | "DATABASE_URL": {
35 | "description": "Mongodb database url",
36 | "required": "True"
37 | },
38 | "HANDLER": {
39 | "description": "You can set your prefix example : .,?+",
40 | "required": "True"
41 | },
42 | "SUDO_USERS": {
43 | "description": "ID of users who can use your bot's certain other than you",
44 | "required": "False"
45 | },
46 | "MY_ID": {
47 | "description": "Your telegram id",
48 | "required": "True"
49 | }
50 | },
51 | "stack": "heroku-20",
52 | "formation": {
53 | "worker": {
54 | "quantity": 1,
55 | "size": "free"
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/bot.py:
--------------------------------------------------------------------------------
1 | from pyrogram import Client
2 | from config import API_ID, API_HASH, BOT_TOKEN
3 |
4 | mainbot = Client(
5 | api_id = API_ID,
6 | api_hash = API_HASH,
7 | bot_token = BOT_TOKEN,
8 | session_name = "Annabelle-userbot")
9 |
10 |
11 | print("Mainbot has started!")
12 | mainbot.run()
13 |
--------------------------------------------------------------------------------
/config.py:
--------------------------------------------------------------------------------
1 | import os
2 | from os import environ
3 |
4 | # vars that need to run the bot
5 | API_ID = int(environ['API_ID'])
6 | API_HASH = environ['API_HASH']
7 | SESSION_STRING = environ['SESSION_STRING']
8 | BOT_TOKEN = environ['BOT_TOKEN']
9 | HANDLER = environ.get(('HANDLER'))
10 | MY_ID = int(environ.get('MY_ID'))
11 | SUDO_USERS = environ.get('SUDO_USERS', MY_ID).split()
12 | DATABASE_NAME = str(environ.get('DATABASE_NAME'))
13 | DATABASE_URL = environ.get('DATABASE_URL')
14 | CHANNEL_ID = environ.get('CHANNEL_ID')
15 | CMD_HELP = {}
16 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 | services:
3 | shop:
4 | build: .
5 | environment:
6 | API_ID: $API_ID
7 | API_HASH: $API_HASH
8 | BOT_TOKEN: $BOT_TOKEN
9 | DATABASE_URL: $DATABASE_URL
10 | HANDLER: $HANDLER
11 | DATABASE_NAME: $DATABASE_NAME
12 | SESSION_STRING: $SESSION_STRING
13 | MY_ID: $MY_ID
14 | SUDO_USERS: $SUDO_USERS
15 |
--------------------------------------------------------------------------------
/mainbot/start.py:
--------------------------------------------------------------------------------
1 | from pyrogram import filters as vrn
2 | from bot import mainbot
3 | from config import HANDLER, MY_ID
4 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
5 |
6 | import logging
7 |
8 | @mainbot.on_message(vrn.command('start', HANDLER) & vrn.private)
9 | async def start(mainbot, message):
10 | await message.reply_photo(
11 | photo = {},
12 | caption = f"Hola {message.from_user}, I am the horrifying Annabelle userbot made for [this person](t.me/user?id={MY_ID}). The messages you send here will be forwarded to my master",
13 | reply_markup = InlineKeyboardMarkup([
14 | [InlineKeyboardMarkup("Deploy your own bot", url="https://github.com/AnnabelleTG/Annabelle")],
15 | [InlineKeyboardButton("Support Channel", url="t.me/annabelleUB"), InlineKeyboardButton("Group", url="https://t.me/AnnaBelleSupportChat")]
16 | ])
17 | )
18 |
19 | @mainbot.on_message(vrn.incoming & vrn.private)
20 | async def frwd(mainbot, message):
21 | try:
22 | USER_ID = message.from_user.mention
23 | await mainbot.forward_message(message.from_user.id, MY_ID)
24 | except:
25 | mainbot.send_message(MY_ID, f"{USER_ID} is spamming me! I am not able to forward his messages")
26 |
27 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | aiohttp
2 | APScheduler==3.7.0
3 | cowpy
4 | dnspython
5 | git-python
6 | pillow
7 | pip-chill
8 | psutil
9 | ptable
10 | pymongo
11 | git+https://github.com/subinps/pyrogram.git@session
12 | python-dotenv
13 | python-git
14 | requests-async
15 | speedtest-cli==2.1.3
16 | tgcrypto
17 | yourls
18 | humanize
19 | thisapidoesnotexist
20 | aiofiles
21 | svglib
22 | reportlab
23 | spotipy
24 | ftpretty
25 | youtube_dl
26 | qrcode[pil]
27 | opencv-python
28 | humanize
29 | pytz
30 | wikipedia
31 | wget
32 | requests
33 | asyncio
34 |
--------------------------------------------------------------------------------
/runtime.txt:
--------------------------------------------------------------------------------
1 | python-3.9.6
2 |
--------------------------------------------------------------------------------
/start:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cyan="\033[1;36m"
4 | reset="\033[0m"
5 | white="\033[1;97m"
6 | red="\033[1;91m"
7 |
8 | echo -e "${white}[ ${red}* ${white}] ${cyan} Installing required packages !!${reset}\n"
9 |
10 | packages=(git python)
11 |
12 | for pkg in "${packages[@]}" ; do
13 | if ! hash ${pkg} > /dev/null 2>&1 ; then
14 | echo -e "\n${white}[ ${red}* ${white}] ${cyan} Installing ${pkg} ${reset}\n"
15 | apt install "${pkg}" -y || sudo apt install "${pkg}" -y
16 | fi
17 |
18 | done
19 |
20 | if [ ! -d "./annabelle" ] ; then
21 |
22 | echo -e "\n${white}[ ${red}* ${white}] ${cyan} Cloning into Annabelle ${reset}\n"
23 | git clone https://github.com/AnnabelleTG/Annabelle
24 |
25 | echo -e "${white}[ ${red}* ${white}] ${cyan} Instaling pip modules !${reset}\n"
26 | pip install -r ./Annabelle/requirements.txt
27 |
28 | echo "Starting Annabelle!"
29 | python3 ./Annabelle/bot.py &
30 | python3 ./Annabelle/annabelle.py
31 |
--------------------------------------------------------------------------------