├── Emilia ├── utils │ ├── __init__.py │ ├── Logo │ │ ├── go3v2.ttf │ │ ├── Chopsic.otf │ │ ├── Maghrib.ttf │ │ ├── default.ttf │ │ ├── True Lies.ttf │ │ ├── No Surrender.otf │ │ ├── No Surrender.ttf │ │ ├── Vampire Wars.otf │ │ ├── Vampire Wars.ttf │ │ ├── CloisterBlack.ttf │ │ ├── Deadly Advance.otf │ │ ├── Deadly Advance.ttf │ │ ├── Respective-VP6y.ttf │ │ ├── Roboto-Medium.ttf │ │ ├── Roboto-Regular.ttf │ │ ├── No Surrender Italic.otf │ │ ├── No Surrender Italic.ttf │ │ ├── Vampire Wars Italic.otf │ │ ├── Vampire Wars Italic.ttf │ │ ├── Another Danger - Demo.otf │ │ ├── Deadly Advance Italic.otf │ │ ├── Deadly Advance Italic.ttf │ │ ├── beyond-wonderland.regular.ttf │ │ ├── Stranger back in the Night.ttf │ │ ├── Another Danger Slanted - Demo.otf │ │ └── RemachineScriptPersonalUseOnly-yZL3.ttf │ ├── auth.py │ ├── executors.py │ ├── db.py │ └── constants.py ├── tele │ ├── __init__.py │ ├── test.py │ ├── donate.py │ ├── ping.py │ ├── truthdare.py │ ├── mentionall.py │ ├── wallpaper.py │ ├── write.py │ └── telegraph.py ├── anime │ ├── downloads │ │ └── __init__.py │ └── jikan.py ├── pyro │ ├── greetings │ │ ├── captcha │ │ │ ├── CaptchaDump │ │ │ │ └── __init__.py │ │ │ ├── setcaptchatext.py │ │ │ └── captcharules.py │ │ ├── utils │ │ │ ├── random_string_gen.py │ │ │ └── actions.py │ │ ├── reset_goodbye.py │ │ ├── reset_welcome.py │ │ ├── set_welcome.py │ │ ├── set_goodbye.py │ │ ├── clean_welcome.py │ │ └── clean_service.py │ ├── locks │ │ ├── locktypes.py │ │ ├── lock_map.py │ │ ├── locks.py │ │ ├── rmallowlistall.py │ │ └── rmallowlist.py │ ├── pin │ │ ├── pininfo.py │ │ ├── pinned.py │ │ ├── cleanlinked_checker.py │ │ ├── antichannelpin_checker.py │ │ ├── unpin.py │ │ ├── pin.py │ │ └── unpinall.py │ ├── disabling │ │ ├── disableable.py │ │ ├── disabled.py │ │ ├── disabledel.py │ │ ├── enable.py │ │ └── disable.py │ ├── users │ │ ├── forcecachechat.py │ │ └── logging.py │ ├── connection │ │ ├── disconnect.py │ │ ├── reconnect.py │ │ ├── allow_connection.py │ │ └── connection.py │ ├── joke.py │ ├── notes │ │ ├── private_notes.py │ │ ├── notes.py │ │ ├── save_note.py │ │ └── set_private_notes.py │ ├── warnings │ │ ├── reset_warns.py │ │ ├── add_warn.py │ │ ├── remove_warn_callback.py │ │ ├── warns.py │ │ ├── set_warn_limit.py │ │ ├── warn.py │ │ └── warnings.py │ ├── rules │ │ ├── reset_rules_button.py │ │ ├── reset_rules.py │ │ ├── set_rules_button.py │ │ ├── setrules.py │ │ └── private_rules.py │ ├── blocklists │ │ ├── resetblocklistreason.py │ │ ├── addblocklist.py │ │ ├── blocklist.py │ │ ├── rmblocklist.py │ │ └── setblocklistreason.py │ ├── mute │ │ ├── unmute.py │ │ ├── tmute.py │ │ └── mute.py │ ├── log_channels │ │ ├── logchannel.py │ │ └── unsetlog.py │ ├── filters │ │ ├── filters.py │ │ ├── stop.py │ │ ├── get_filter.py │ │ └── filter.py │ ├── webshot.py │ ├── report │ │ ├── report.py │ │ └── reports.py │ ├── github.py │ └── pokedex.py ├── data.py ├── info │ ├── upload_info.py │ ├── format.py │ ├── nightmode_info.py │ ├── images_info.py │ ├── chatbot_info.py │ ├── nsfw_info.py │ ├── fed_admin_info.py │ ├── karma_info.py │ ├── meme_info.py │ ├── misc_info.py │ ├── rules_info.py │ ├── fed_info.py │ ├── antichannel_info.py │ ├── filter_ex_usage.py │ ├── filters_info.py │ ├── stickers_info.py │ ├── approval_info.py │ ├── topics_info.py │ ├── notes_info.py │ ├── log_channels_info.py │ ├── antispam_info.py │ ├── admin_info.py │ ├── connection_info.py │ ├── fed_user_info.py │ ├── warn_info.py │ ├── extra_info.py │ ├── pin_info.py │ ├── purge_info.py │ ├── report_info.py │ ├── lock_ex_info.py │ ├── greetings_ex_usage.py │ ├── formatting.py │ ├── disable_info.py │ ├── greetings_info.py │ ├── info_info.py │ ├── notes_ex.py │ ├── fillings.py │ ├── sfw_info.py │ ├── __init__.py │ ├── fun_info.py │ ├── lock_info.py │ ├── antiflood_info.py │ ├── chatlevels_info.py │ ├── captcha_info.py │ ├── blocklists_example_info.py │ ├── bans_info.py │ ├── clone_info.py │ ├── blocklists_info.py │ ├── import_info.py │ ├── fed_owner_info.py │ ├── anime_info.py │ └── lock_desc.py ├── mongo │ ├── ai_mongo.py │ ├── report_mongo.py │ ├── nightmode_mongo.py │ ├── nsfw_mongo.py │ ├── user_info.py │ ├── users_mongo.py │ ├── afk_mongo.py │ ├── pin_mongo.py │ ├── chats_settings_mongo.py │ ├── disable_mongo.py │ ├── log_channels_mongo.py │ ├── karma_mongo.py │ ├── rules_mongo.py │ └── connection_mongo.py ├── catbox.py ├── helper │ ├── convert.py │ ├── note_helper │ │ ├── note_misc_helper.py │ │ └── note_fillings.py │ ├── button_gen.py │ ├── welcome_helper │ │ └── welcome_fillings.py │ ├── get_data.py │ └── get_user.py └── config.py ├── Dockerfile ├── requirements.txt ├── meow.yml └── LICENSE /Emilia/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Emilia/tele/__init__.py: -------------------------------------------------------------------------------- 1 | "gay" 2 | -------------------------------------------------------------------------------- /Emilia/anime/downloads/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Emilia/pyro/greetings/captcha/CaptchaDump/__init__.py: -------------------------------------------------------------------------------- 1 | "Memory allocation" 2 | -------------------------------------------------------------------------------- /Emilia/utils/Logo/go3v2.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/go3v2.ttf -------------------------------------------------------------------------------- /Emilia/utils/Logo/Chopsic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/Chopsic.otf -------------------------------------------------------------------------------- /Emilia/utils/Logo/Maghrib.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/Maghrib.ttf -------------------------------------------------------------------------------- /Emilia/utils/Logo/default.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/default.ttf -------------------------------------------------------------------------------- /Emilia/utils/Logo/True Lies.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/True Lies.ttf -------------------------------------------------------------------------------- /Emilia/utils/Logo/No Surrender.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/No Surrender.otf -------------------------------------------------------------------------------- /Emilia/utils/Logo/No Surrender.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/No Surrender.ttf -------------------------------------------------------------------------------- /Emilia/utils/Logo/Vampire Wars.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/Vampire Wars.otf -------------------------------------------------------------------------------- /Emilia/utils/Logo/Vampire Wars.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/Vampire Wars.ttf -------------------------------------------------------------------------------- /Emilia/utils/Logo/CloisterBlack.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/CloisterBlack.ttf -------------------------------------------------------------------------------- /Emilia/utils/Logo/Deadly Advance.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/Deadly Advance.otf -------------------------------------------------------------------------------- /Emilia/utils/Logo/Deadly Advance.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/Deadly Advance.ttf -------------------------------------------------------------------------------- /Emilia/utils/Logo/Respective-VP6y.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/Respective-VP6y.ttf -------------------------------------------------------------------------------- /Emilia/utils/Logo/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/Roboto-Medium.ttf -------------------------------------------------------------------------------- /Emilia/utils/Logo/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/Roboto-Regular.ttf -------------------------------------------------------------------------------- /Emilia/utils/Logo/No Surrender Italic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/No Surrender Italic.otf -------------------------------------------------------------------------------- /Emilia/utils/Logo/No Surrender Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/No Surrender Italic.ttf -------------------------------------------------------------------------------- /Emilia/utils/Logo/Vampire Wars Italic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/Vampire Wars Italic.otf -------------------------------------------------------------------------------- /Emilia/utils/Logo/Vampire Wars Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/Vampire Wars Italic.ttf -------------------------------------------------------------------------------- /Emilia/utils/Logo/Another Danger - Demo.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/Another Danger - Demo.otf -------------------------------------------------------------------------------- /Emilia/utils/Logo/Deadly Advance Italic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/Deadly Advance Italic.otf -------------------------------------------------------------------------------- /Emilia/utils/Logo/Deadly Advance Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/Deadly Advance Italic.ttf -------------------------------------------------------------------------------- /Emilia/utils/Logo/beyond-wonderland.regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/beyond-wonderland.regular.ttf -------------------------------------------------------------------------------- /Emilia/utils/Logo/Stranger back in the Night.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/Stranger back in the Night.ttf -------------------------------------------------------------------------------- /Emilia/utils/Logo/Another Danger Slanted - Demo.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/Another Danger Slanted - Demo.otf -------------------------------------------------------------------------------- /Emilia/utils/Logo/RemachineScriptPersonalUseOnly-yZL3.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArshCypherZ/Emilia/HEAD/Emilia/utils/Logo/RemachineScriptPersonalUseOnly-yZL3.ttf -------------------------------------------------------------------------------- /Emilia/data.py: -------------------------------------------------------------------------------- 1 | # This file holds shared data structures to avoid circular imports. 2 | 3 | IMPORTED = {} 4 | HELPABLE = {} 5 | SUB_MODE = {} 6 | HIDDEN_MOD = {} 7 | USER_INFO = [] -------------------------------------------------------------------------------- /Emilia/info/upload_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Upload" 2 | 3 | __help__ = """ 4 | **Commands**: 5 | 6 | • /tgm: Uploads replied media on `telegra.ph` and `graph.org` 7 | • /tgt: Uploads replied text on `telegra.ph` and `graph.org` 8 | """ 9 | -------------------------------------------------------------------------------- /Emilia/tele/test.py: -------------------------------------------------------------------------------- 1 | from Emilia.custom_filter import register 2 | from Emilia.utils.decorators import * 3 | 4 | 5 | @register(pattern="test") 6 | @rate_limit(RATE_LIMIT_GENERAL) 7 | async def test(event): 8 | await event.reply("test") -------------------------------------------------------------------------------- /Emilia/info/format.py: -------------------------------------------------------------------------------- 1 | from Emilia import BOT_NAME 2 | 3 | __mod_name__ = "Formatting" 4 | 5 | __sub_mod__ = ["Markdown Formatting", "Fillings"] 6 | 7 | __help__ = f""" 8 | {BOT_NAME} supports a large number of formatting options to make your messages more expressive. Take a look! 9 | """ 10 | -------------------------------------------------------------------------------- /Emilia/info/nightmode_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Night-Mode" 2 | 3 | __help__ = """ 4 | By using this module, bot will automatically turn off messages for non-admins in a group chat from 12 AM [IST] to 6 AM [IST]. 5 | 6 | **Admin Command**: 7 | • /nightmode: Shows control panel for nightmode module. 8 | """ 9 | -------------------------------------------------------------------------------- /Emilia/info/images_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Images" 2 | 3 | __help__ = """ 4 | This module allows user to get images from various sources. Also allows user to draw or play with them. 5 | 6 | **Commands**: 7 | • /mmf ``: Writes text on replied sticker. 8 | **Example**: `/mmf meow ; hello` 9 | """ 10 | -------------------------------------------------------------------------------- /Emilia/mongo/ai_mongo.py: -------------------------------------------------------------------------------- 1 | from Emilia import db 2 | 3 | chatbotdb1 = db.ai 4 | 5 | 6 | async def addchat_bot1(chat_id: int): 7 | await chatbotdb1.update_one({"chat_id": chat_id}, {"$set": {"chat_id": chat_id}}, upsert=True) 8 | 9 | 10 | async def rmchat_bot1(chat_id: int): 11 | await chatbotdb1.delete_one({"chat_id": chat_id}) 12 | -------------------------------------------------------------------------------- /Emilia/info/chatbot_info.py: -------------------------------------------------------------------------------- 1 | from Emilia import BOT_NAME 2 | 3 | __mod_name__ = "Chatbot" 4 | 5 | __help__ = f""" 6 | Chatbot makes {BOT_NAME} talk like a human. 7 | 8 | Basically, there is chatbot inserted in {BOT_NAME}, it can be used to talk in a frank way and can also be used to write essays, codes, birthday wishes, simply anything you want. 9 | 10 | **Commands**: 11 | 12 | • /chatbot: Shows chatbot control panel 13 | """ 14 | -------------------------------------------------------------------------------- /Emilia/info/nsfw_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "NSFW" 2 | 3 | __help__ = """ 4 | Sometimes a lil bit of horni-stuff is fine, check this module for fine stuff! 5 | 6 | **Admins Only**: 7 | • /addnsfw: To Activate NSFW commands. (for groups) 8 | • /rmnsfw: To Deactivate NSFW commands. (for groups) 9 | 10 | **Following are the NSFW commands**: 11 | • /nsfwwaifu 12 | • /blowjob 13 | • /nwaifu 14 | • /bj 15 | • /trap 16 | • /nsfwneko 17 | • /nneko 18 | • /spank 19 | """ 20 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.10-slim-bookworm 2 | 3 | WORKDIR /app 4 | 5 | RUN apt-get update && apt-get install -y \ 6 | git \ 7 | gcc \ 8 | python3-dev \ 9 | ffmpeg \ 10 | zip \ 11 | curl \ 12 | ca-certificates \ 13 | && rm -rf /var/lib/apt/lists/* 14 | 15 | COPY requirements.txt . 16 | 17 | RUN pip3 install --no-cache-dir -U -r requirements.txt 18 | 19 | COPY . . 20 | 21 | STOPSIGNAL SIGTERM 22 | 23 | CMD ["python3", "-u", "-m", "Emilia"] -------------------------------------------------------------------------------- /Emilia/mongo/report_mongo.py: -------------------------------------------------------------------------------- 1 | from Emilia import db 2 | 3 | reports = db.reports 4 | 5 | 6 | async def reports_db(chat_id: int, report_arg: bool): 7 | await reports.update_one( 8 | {"chat_id": chat_id}, {"$set": {"reports": report_arg}}, upsert=True 9 | ) 10 | 11 | 12 | async def get_report(chat_id: int) -> bool: 13 | doc = await reports.find_one({"chat_id": chat_id}, {"_id": 0, "reports": 1}) 14 | return doc.get("reports", True) if doc else True 15 | -------------------------------------------------------------------------------- /Emilia/info/fed_admin_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Fed Admin Commands" 2 | 3 | __hidden__ = True 4 | 5 | __help__ = """ 6 | The following is the list of all fed admin commands. To run these, you have to be a federation admin in the current federation. 7 | 8 | **Commands**: 9 | • /fban: Bans a user from the current chat's federation 10 | • /unfban: Unbans a user from the current chat's federation 11 | • /feddemoteme : Demote yourself from a fed. 12 | • /myfeds: List all feds you are an admin in. 13 | """ 14 | -------------------------------------------------------------------------------- /Emilia/info/karma_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Karma" 2 | 3 | __sub_mod__ = ["Fun"] 4 | 5 | __help__ = """ 6 | Karma is a fun module to increase/decrease respect points of a person in a group chat. 7 | 8 | **Detail**: 9 | **Upvote** - Use upvote keywords like "+", "+1", "thanks", etc. to upvote a message. 10 | **Downvote** - Use downvote keywords like "-", "-1", etc. to downvote a message. 11 | 12 | **Commands**: 13 | 14 | • /karma: Enable/Disable karma in your group. 15 | • /leaderboard: To check karma ranking in group and globally. 16 | 17 | """ 18 | -------------------------------------------------------------------------------- /Emilia/pyro/locks/locktypes.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client 2 | 3 | from Emilia import custom_filter 4 | from Emilia.helper.disable import disable 5 | from Emilia.pyro.locks import lock_map 6 | 7 | 8 | @Client.on_message(custom_filter.command(commands="locktypes", disable=True)) 9 | @disable 10 | async def locktypes(client, message): 11 | LOCKS_LIST = lock_map.LocksMap.list() 12 | 13 | text = "The available locktypes are:\n" 14 | for lock in LOCKS_LIST: 15 | text += f"• {lock}\n" 16 | 17 | await message.reply(text, quote=True) 18 | -------------------------------------------------------------------------------- /Emilia/tele/donate.py: -------------------------------------------------------------------------------- 1 | from Emilia.custom_filter import register 2 | from telethon import Button 3 | 4 | @register(pattern="donate") 5 | async def handle_donate(event): 6 | message = "🌟 Thank you for considering a donation! 🌟\n\n" 7 | message += "Your support helps us continue providing great services.\n\n" 8 | message += "To donate, please click on the button below.\n" 9 | message += "We appreciate your generosity! ❤️" 10 | button = [Button.url("Donate", "https://t.me/Elf_Robot/donation")] 11 | await event.reply(message, buttons=button) -------------------------------------------------------------------------------- /Emilia/mongo/nightmode_mongo.py: -------------------------------------------------------------------------------- 1 | from Emilia import db 2 | 3 | nightdb = db.nightmode 4 | 5 | 6 | async def nightmode_on(chat_id: int): 7 | return nightdb.update_one({"chat_id": chat_id}, {"$set": {"chat_id": chat_id}}, upsert=True) 8 | 9 | 10 | async def nightmode_off(chat_id: int): 11 | return nightdb.delete_one({"chat_id": chat_id}) 12 | 13 | 14 | async def get_nightchats() -> list: 15 | cursor = nightdb.find({"chat_id": {"$lt": 0}}, {"_id": 0, "chat_id": 1}) 16 | chats_list = [] 17 | async for doc in cursor: 18 | chats_list.append(doc) 19 | return chats_list 20 | -------------------------------------------------------------------------------- /Emilia/pyro/pin/pininfo.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client 2 | 3 | from Emilia import custom_filter 4 | from Emilia.helper.chat_status import isUserAdmin 5 | 6 | 7 | @Client.on_message(custom_filter.command(commands="pininfo")) 8 | async def pininfo(client, message): 9 | if not await isUserAdmin(message): 10 | return 11 | 12 | await message.reply( 13 | "`/antichannelpin` and `/cleanlinked` can't be enabled at the same time because there's no point in doing so.\n\nAs `/cleanlinked` automatically deletes messages sent by the linked channel and it's removed from the pin." 14 | ) 15 | -------------------------------------------------------------------------------- /Emilia/pyro/disabling/disableable.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client 2 | 3 | from Emilia import custom_filter 4 | from Emilia.custom_filter import DISABLE_COMMANDS 5 | from Emilia.helper.chat_status import isUserAdmin 6 | 7 | 8 | @Client.on_message(custom_filter.command(commands="disableable")) 9 | async def disable_list(client, message): 10 | if not await isUserAdmin(message): 11 | return 12 | 13 | text_header = "The following commands can be disabled:\n" 14 | for diable in DISABLE_COMMANDS: 15 | text_header += f"- `{diable}`\n" 16 | 17 | await message.reply(text_header, quote=True) 18 | -------------------------------------------------------------------------------- /Emilia/info/meme_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Memes" 2 | 3 | __sub_mod__ = ["SFW"] 4 | 5 | __help__ = """ 6 | Memes help you get through tough times, enjoy with our funny and healthy memes. 7 | 8 | **Commands**: 9 | 10 | • /memes: General command for memes. 11 | • /wmeme: Will give you wholesome memes. 12 | • /dank: Provides dank memes. 13 | • /cursed: Cursed memes 14 | • /shitposting: Random shitposts OwO 15 | 16 | • /fbi: FBI Memes (pols aagoi pols) 17 | 18 | • /teen: Teenagers meme 19 | • /hmeme: Horni Memes 20 | • /pewds: Pewdiepie Collection 21 | • /hornyjail: Senpai Arrested :p 22 | • /lolimeme: Loli Memes (fbi locating) 23 | """ 24 | -------------------------------------------------------------------------------- /Emilia/info/misc_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Misc" 2 | 3 | __sub_mod__ = ["Fun"] 4 | 5 | __help__ = """ 6 | An "odds and ends" module for small, simple commands which don't really fit anywhere. 7 | 8 | **Commands**: 9 | 10 | • /carbon ``: Makes carbon of text, try it out! 11 | 12 | • /id: Get a user's ID. 13 | 14 | • /github ``: Get info of any `github.com` profile 15 | 16 | • /all: Works only for admins, it will tag every member of a group chat. 17 | 18 | • /zip: reply to a telegram file to compress it in .zip format 19 | • /unzip: reply to a telegram file to decompress it from the .zip format 20 | 21 | • /count: Count total messages of a chat 22 | """ 23 | -------------------------------------------------------------------------------- /Emilia/info/rules_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Rules" 2 | 3 | __sub_mod__ = ["Formatting"] 4 | 5 | __help__ = """ 6 | Every chat works with different rules; this module will help make those rules clearer! 7 | 8 | **User commands**: 9 | • /rules: Check the current chat rules. 10 | 11 | **Admin commands**: 12 | 13 | • /setrules ``: Set the rules for this chat. Supports markdown and buttons. 14 | • /privaterules ``: Enable/disable whether the rules should be sent in private. 15 | • /resetrules: Reset the chat rules to default. 16 | • /setrulesbutton: Set the rules button name when using {rules}. 17 | • /resetrulesbutton: Reset the rules button name from {rules} to default. 18 | """ 19 | -------------------------------------------------------------------------------- /Emilia/utils/auth.py: -------------------------------------------------------------------------------- 1 | from typing import Iterable 2 | from Emilia import OWNER_ID, DEV_USERS 3 | 4 | DEV_SET = set(int(x) for x in (DEV_USERS or [])) 5 | DEV_SET.add(int(OWNER_ID)) 6 | 7 | 8 | def is_owner(user_id: int) -> bool: 9 | try: 10 | return int(user_id) == int(OWNER_ID) 11 | except Exception: 12 | return False 13 | 14 | 15 | def is_dev(user_id: int) -> bool: 16 | try: 17 | return int(user_id) in DEV_SET 18 | except Exception: 19 | return False 20 | 21 | 22 | def any_dev(user_ids: Iterable[int]) -> bool: 23 | try: 24 | return any(int(u) in DEV_SET for u in user_ids or []) 25 | except Exception: 26 | return False 27 | -------------------------------------------------------------------------------- /Emilia/catbox.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from Emilia import telethn 4 | 5 | from catbox import CatboxUploader 6 | from Emilia.tele.telegraph import resize_image 7 | 8 | 9 | uploader = CatboxUploader() 10 | 11 | 12 | TMP_DOWNLOAD_DIRECTORY = "catbox/" 13 | 14 | 15 | async def upload(img): 16 | downloaded_file_name = await telethn.download_media(img, TMP_DOWNLOAD_DIRECTORY) 17 | if downloaded_file_name.endswith((".webp")): 18 | resize_image(downloaded_file_name) 19 | try: 20 | media_urls = uploader.upload_file(downloaded_file_name) 21 | except: 22 | media_urls = uploader.upload_file(downloaded_file_name) 23 | os.remove(downloaded_file_name) 24 | return media_urls -------------------------------------------------------------------------------- /Emilia/tele/ping.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from Emilia.custom_filter import register 4 | from Emilia.functions.admins import get_time 5 | from Emilia.helper.disable import disable 6 | 7 | StartTime = time.time() 8 | 9 | 10 | @register(pattern="ping", disable=True) 11 | @disable 12 | async def ping(event): 13 | start_time = time.time() 14 | message = await event.reply("Pinging...") 15 | end_time = time.time() 16 | telegram_ping = str(round((end_time - start_time) * 1000, 3)) + " ms" 17 | uptime = await get_time((int(time.time()) - int(StartTime))) 18 | 19 | await message.edit( 20 | f"**PONG!!**\n**Time Taken:** `{telegram_ping}`\n**Service uptime:** `{uptime}`" 21 | ) 22 | -------------------------------------------------------------------------------- /Emilia/mongo/nsfw_mongo.py: -------------------------------------------------------------------------------- 1 | from Emilia import db 2 | 3 | nsfwdb = db.nsfw 4 | 5 | """NSFW System""" 6 | 7 | 8 | async def is_nsfw_on(chat_id: int) -> bool: 9 | doc = await nsfwdb.find_one({"chat_id": chat_id}, {"_id": 0, "chat_id": 1}) 10 | return not bool(doc) 11 | 12 | 13 | async def nsfw_on(chat_id: int): 14 | if await is_nsfw_on(chat_id): 15 | return 16 | return await nsfwdb.delete_one({"chat_id": chat_id}) 17 | 18 | 19 | async def nsfw_off(chat_id: int): 20 | if not await is_nsfw_on(chat_id): 21 | return 22 | # Idempotent create; relies on unique index on chat_id 23 | return await nsfwdb.update_one({"chat_id": chat_id}, {"$setOnInsert": {"chat_id": chat_id}}, upsert=True) 24 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | urlextract 2 | captcha 3 | apscheduler 4 | ffmpeg-python 5 | opencv-python 6 | vanitas-antispam 7 | aiofiles>=0.6.0 8 | aiohttp[speedups]>=3.7.3 9 | tracemoepy 10 | 11 | dnspython 12 | natsort 13 | 14 | # database 15 | motor 16 | 17 | # telegram clients 18 | git+https://github.com/KurimuzonAkuma/pyrogram.git@v2.1.16 19 | telethon 20 | 21 | emoji 22 | 23 | # scraping 24 | beautifulsoup4 25 | 26 | # image 27 | pillow>=10.0.0 28 | webcolors 29 | 30 | # api 31 | nekos.py 32 | wikipedia 33 | py-carbon 34 | catbox-uploader 35 | groq 36 | 37 | # media metadata 38 | hachoir 39 | 40 | # tts 41 | gtts 42 | mutagen 43 | 44 | # performance 45 | cryptg 46 | TgCrypto 47 | redis>=5.0.0 48 | orjson -------------------------------------------------------------------------------- /Emilia/info/fed_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Federations" 2 | 3 | __sub_mod__ = ["User Commands", "Fed Admin Commands", "Federation Owner Commands"] 4 | 5 | __help__ = """ 6 | Ah, group management. It's all fun and games, until you start getting spammers in, and you need to ban them. Then you need to start banning more, and more, and it gets painful. 7 | But then you have multiple groups, and you don't want these spammers in any of your groups - how can you deal? Do you have to ban them manually, in all your groups? 8 | 9 | No more! With federations, you can make a ban in one chat overlap to all your other chats. 10 | You can even appoint federation admins, so that your trustworthiest admins can ban across all the chats that you want to protect. 11 | """ 12 | -------------------------------------------------------------------------------- /Emilia/info/antichannel_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Anti-Channel" 2 | 3 | __help__ = """ 4 | Anti Channel Mode is a mode to prevent unwanted channel actions. 5 | 6 | **Admin Commands**: 7 | 8 | • /antichannelmode ``: Enables Anti Channel Mode to ban users who chat using channels. 9 | • /antichannelmode ``: Disables Anti Channel Mode. 10 | • /antichannelpin ``: Don't let telegram auto-pin linked channels. If no arguments are given, shows current setting. 11 | • /cleanlinked ``: Delete messages sent by the linked channel. 12 | 13 | **Note**: When using antichannel pins, make sure to use the /unpin command, instead of doing it manually. Otherwise, the old message will get re-pinned when the channel sends any messages. 14 | """ 15 | -------------------------------------------------------------------------------- /Emilia/info/filter_ex_usage.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Example Usage" 2 | 3 | __hidden__ = True 4 | 5 | __help__ = """ 6 | Filters can seem quite complicated; so here are some examples, so you can get some inspiration. 7 | 8 | **Examples**: 9 | 10 | • Set a filter: 11 | -> `/filter hello Hello there! How are you?` 12 | 13 | • Set a filter which uses the user's name through fillings: 14 | -> `/filter hello Hello there {first}! How are you?` 15 | 16 | • Set a filter on a sentence: 17 | -> `/filter "hello friend" Hello back! Long time no see!` 18 | 19 | • Set a filter that replies to the person you replied to: 20 | -> `/filter magic Watch out for wizards! {replytag}` 21 | 22 | • To save a file, image, gif, or any other attachment, simply reply to file with: 23 | -> `/filter trigger` 24 | """ 25 | -------------------------------------------------------------------------------- /Emilia/info/filters_info.py: -------------------------------------------------------------------------------- 1 | from Emilia import BOT_NAME 2 | 3 | __mod_name__ = "Filters" 4 | 5 | __help__ = f""" 6 | Make your chat more lively with filters; The bot will reply to certain words! 7 | 8 | Filters are case insensitive; every time someone says your trigger words, {BOT_NAME} will reply something else! can be used to create your own commands, if desired. 9 | 10 | **Commands**: 11 | 12 | • /filter ` `: Every time someone says "trigger", the bot will reply with "sentence". For multiple word filters, quote the trigger. 13 | • /filters: List all chat filters. 14 | • /stop ``: Stop the bot from replying to "trigger". 15 | • /stopall: Stop ALL filters in the current chat. This cannot be undone. 16 | """ 17 | 18 | __sub_mod__ = ["Example Usage", "Formatting"] 19 | -------------------------------------------------------------------------------- /Emilia/info/stickers_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Stickers" 2 | 3 | __help__ = """ 4 | Sticker module helps you to make your own pack of stickers and even steal other packs in just one click! 5 | 6 | **Commands**: 7 | • /stickerid: reply to a sticker to get it's file ID. 8 | • /gifid: reply to a GIF to get it's file ID. 9 | 10 | • /getsticker: reply to a sticker to upload its raw PNG file. 11 | • /getvideo: reply to a GIF to upload its raw MP4 file. 12 | • /getvidsticker: reply to an animated sticker upload its raw MP4 file. 13 | 14 | • /kang: reply to sticker to kang (steal) into your own pack. 15 | • /unkang: reply to sticker which is in your pack to delete it from your pack. 16 | • /pkang or /packkang: reply to sticker pack to kang (steal) the whole pack into your own pack. 17 | 18 | """ 19 | -------------------------------------------------------------------------------- /Emilia/mongo/user_info.py: -------------------------------------------------------------------------------- 1 | from Emilia import db 2 | 3 | infodb = db.user_info 4 | 5 | 6 | async def set_me(user_id: int, info: str): 7 | return await infodb.update_one( 8 | {"user_id": user_id}, {"$set": {"info": info}}, upsert=True 9 | ) 10 | 11 | 12 | async def get_me(user_id: int): 13 | user = await infodb.find_one({"user_id": user_id}) 14 | if user: 15 | return user.get("info") 16 | return None 17 | 18 | 19 | async def set_bio(user_id: int, bio: str): 20 | return await infodb.update_one( 21 | {"user_id": user_id}, {"$set": {"bio": bio}}, upsert=True 22 | ) 23 | 24 | 25 | async def get_bio(user_id: int): 26 | user = await infodb.find_one({"user_id": user_id}) 27 | if user: 28 | return user.get("bio") 29 | return None 30 | -------------------------------------------------------------------------------- /Emilia/mongo/users_mongo.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | from Emilia import db 4 | from Emilia.utils.write_buffer import WriteBuffer 5 | 6 | users = db.users 7 | chats = db.chats 8 | 9 | WRITE_BUFFER = WriteBuffer() 10 | 11 | 12 | async def add_user( 13 | user_id, username=None, chat_id=None, chat_title=None, Forwared=False, bot_id=None 14 | ): 15 | await WRITE_BUFFER.add_user( 16 | user_id, username, chat_id, chat_title, forwarded=Forwared, bot_id=bot_id 17 | ) 18 | 19 | 20 | async def add_chat(chat_id, chat_title, bot_id=None): 21 | await WRITE_BUFFER.add_chat(chat_id, chat_title, bot_id) 22 | 23 | 24 | async def GetChatName(chat_id): 25 | doc = await chats.find_one({"chat_id": chat_id}, {"_id": 0, "chat_title": 1}) 26 | return doc.get("chat_title") if doc else None 27 | -------------------------------------------------------------------------------- /Emilia/info/approval_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Approval" 2 | 3 | __help__ = """ 4 | Sometimes, you might trust a user not to send unwanted content. 5 | Maybe not enough to make them admin, but you might be ok with locks, blocklists, and antiflood not applying to them. 6 | 7 | That's what approvals are for - approve of trustworthy users to allow them to send 8 | 9 | **User commands**: 10 | • /approval: Check a user's approval status in this chat. 11 | 12 | **Admin commands**: 13 | • /approve: Approve of a user. Locks, blocklists, and antiflood won't apply to them anymore. 14 | • /unapprove: Unapprove of a user. They will now be subject to locks, blocklists, and antiflood again. 15 | • /approved: List all approved users. 16 | • /unapproveall: Unapprove ALL users in a chat. This cannot be undone. 17 | """ 18 | -------------------------------------------------------------------------------- /Emilia/info/topics_info.py: -------------------------------------------------------------------------------- 1 | from Emilia import BOT_NAME 2 | 3 | 4 | __mod_name__ = "Topics" 5 | 6 | __help__ = f""" 7 | Manage your topic settings through {BOT_NAME}! 8 | 9 | Topics introduce lots of small differences to normal supergroups; this could affect how you would usually manage your chat. 10 | 11 | You can use the bot to create, rename, close and delete your topics. 12 | 13 | **Admin commands**: 14 | 15 | • /newtopic : Create a new topic. 16 | • /renametopic : Rename the current topic. (For general topic, please reply to a message in order to rename it.) 17 | • /opentopic : Opens the closed topic of which id was given. 18 | • /closetopic : Closes the desired topic. 19 | • /deletetopic : Delete desired topic, and all the topic messages. Cannot be undone! 20 | """ 21 | -------------------------------------------------------------------------------- /Emilia/pyro/users/forcecachechat.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, enums 2 | 3 | from Emilia import custom_filter 4 | from Emilia.helper.chat_status import isUserAdmin 5 | from Emilia.mongo.users_mongo import add_chat 6 | 7 | 8 | @Client.on_message(custom_filter.command(commands="forcecachechat")) 9 | async def forcecachechat(client, message): 10 | chat_id = message.chat.id 11 | chat_title = message.chat.title 12 | 13 | if message.chat.type == enums.ChatType.PRIVATE: 14 | await message.reply( 15 | "This command is made to be used in group chats, not in pm!" 16 | ) 17 | return 18 | 19 | if not await isUserAdmin(message): 20 | return 21 | 22 | await add_chat(chat_id, chat_title) 23 | await message.reply("I've exported your chat's data to my database.") 24 | -------------------------------------------------------------------------------- /Emilia/pyro/connection/disconnect.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client 2 | from pyrogram.enums import ChatType 3 | 4 | from Emilia import custom_filter 5 | from Emilia.mongo.connection_mongo import disconnectChat 6 | from Emilia.pyro.connection.connection import connection 7 | 8 | 9 | @Client.on_message(custom_filter.command(commands=("disconnect"))) 10 | async def diconnectChat(client, message): 11 | user_id = message.from_user.id 12 | if not (message.chat.type == ChatType.PRIVATE): 13 | await message.reply("You need to be in PM to use this.") 14 | return 15 | if await connection(message) is not None: 16 | await disconnectChat(user_id) 17 | await message.reply("Disconnected from chat.", quote=True) 18 | else: 19 | await message.reply("You aren't connected to any chats :)", quote=True) 20 | -------------------------------------------------------------------------------- /Emilia/pyro/pin/pinned.py: -------------------------------------------------------------------------------- 1 | import html 2 | 3 | from pyrogram import Client 4 | 5 | from Emilia import custom_filter 6 | 7 | 8 | @Client.on_message(custom_filter.command(commands="pinned")) 9 | async def pinned(client, message): 10 | chat_id = message.chat.id 11 | chat_title = message.chat.title 12 | 13 | chat_data = await client.get_chat(chat_id=chat_id) 14 | if chat_data.pinned_message: 15 | pinned_message_id = chat_data.pinned_message.id 16 | message_link = ( 17 | f"http://t.me/c/{str(chat_id).replace(str(-100), '')}/{pinned_message_id}" 18 | ) 19 | await message.reply( 20 | f"The pinned message in {html.escape(chat_title)} is [here]({message_link})." 21 | ) 22 | 23 | else: 24 | await message.reply(f"There is no pinned message in {html.escape(chat_title)}.") 25 | -------------------------------------------------------------------------------- /meow.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | 3 | services: 4 | redis: 5 | image: redis:alpine 6 | container_name: emilia_redis 7 | network_mode: host 8 | volumes: 9 | - redis_data:/data 10 | restart: unless-stopped 11 | 12 | emilia: 13 | build: . 14 | image: emilia:${TAG} 15 | container_name: emilia 16 | network_mode: host # or bridge or whatever your network is 17 | depends_on: 18 | - redis 19 | pull_policy: never 20 | restarter: 21 | image: docker:cli 22 | volumes: ["/var/run/docker.sock:/var/run/docker.sock"] 23 | command: ["/bin/sh", "-c", "while true; do sleep 30000; docker restart emilia; done"] # restart every 4 hours 24 | restart: unless-stopped 25 | network_mode: host 26 | 27 | networks: 28 | default: 29 | external: true 30 | name: host 31 | 32 | volumes: 33 | redis_data: -------------------------------------------------------------------------------- /Emilia/info/notes_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Notes" 2 | 3 | __sub_mod__ = ["Example for usage", "Formatting"] 4 | 5 | __help__ = """ 6 | Save data for future users with notes! 7 | 8 | Notes are great to save random tidbits of information; a phone number, a nice gif, a funny picture - anything! 9 | 10 | **User commands**: 11 | • /get : Get a note. 12 | • #notename: Same as /get. 13 | 14 | **Admin commands**: 15 | • /save : Save a new note called "word". Replying to a message will save that message. Even works on media! 16 | • /clear : Delete the associated note. 17 | • /notes: List all notes in the current chat. 18 | • /saved: Same as /notes. 19 | • /clearall: Delete ALL notes in a chat. This cannot be undone. 20 | • /privatenotes: Whether or not to send notes in PM. Will send a message with a button which users can click to get the note in PM. 21 | """ 22 | -------------------------------------------------------------------------------- /Emilia/mongo/afk_mongo.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from Emilia import db 4 | 5 | afk_collection = db.afk 6 | 7 | 8 | async def set_afk(user_id: int, first_name="User", reason=None): 9 | await afk_collection.update_one( 10 | {"user_id": user_id}, 11 | { 12 | "$set": { 13 | "first_name": first_name, 14 | "reason": reason, 15 | "time": time.time(), 16 | } 17 | }, 18 | upsert=True, 19 | ) 20 | 21 | 22 | async def unset_afk(user_id): 23 | await afk_collection.delete_one({"user_id": user_id}) 24 | 25 | 26 | async def is_afk(user_id): 27 | _afk = await afk_collection.count_documents({"user_id": user_id}) 28 | return _afk > 0 29 | 30 | 31 | async def get_afk_user(user_id): 32 | _afk = await afk_collection.find_one({"user_id": user_id}) 33 | return _afk if _afk else None 34 | -------------------------------------------------------------------------------- /Emilia/info/log_channels_info.py: -------------------------------------------------------------------------------- 1 | from Emilia import BOT_NAME 2 | 3 | __mod_name__ = "Logging" 4 | 5 | __help__ = f""" 6 | Recent actions are nice, but they don't help you log every action taken by the bot. This is why you need log channels! 7 | 8 | Log channels can help you keep track of exactly what the other admins are doing. Bans, Mutes, warns, notes - everything can be moderated. 9 | 10 | Setting a log channel is done by the following steps: 11 | - Add {BOT_NAME} to your channel, as an admin. This is done via the "add administrators" tab. 12 | - Send /setlog to your channel. 13 | - Forward the /setlog command to the group you wish to be logged. 14 | - Congrats! all done :) 15 | 16 | **Admin commands:** 17 | • /logchannel: Get the name of the current log channel. 18 | • /setlog: Set the log channel for the current chat. 19 | • /unsetlog: Unset the log channel for the current chat. 20 | """ 21 | -------------------------------------------------------------------------------- /Emilia/info/antispam_info.py: -------------------------------------------------------------------------------- 1 | __help__ = """ 2 | **Admins only:** 3 | 4 | • /antispam : Will toggle our antispam tech. 5 | 6 | Anti-Spam, used by bot devs to ban spammers across all groups. This helps protect you and your groups by removing spam flooders as quickly as possible. 7 | 8 | **Note**: Users can appeal gbans or report spammers at @SpiralTechDivision 9 | 10 | This also integrates @SpamwatchingBot API to remove Spammers as much as possible from your chatroom! 11 | 12 | **What is @SpamWatchingBot?** 13 | @SpamWatchingBot maintains a large constantly updated ban-list of spambots, trolls, bitcoin spammers and unsavoury characters. 14 | Constantly help banning spammers off from your group automatically So, you wont have to worry about spammers storming your group. 15 | 16 | **Note**: Users can appeal @spamwatchingbot bans at @VanitasSupport""" 17 | 18 | __mod_name__ = "Anti-Spam" 19 | -------------------------------------------------------------------------------- /Emilia/pyro/greetings/utils/random_string_gen.py: -------------------------------------------------------------------------------- 1 | import random 2 | import string 3 | 4 | 5 | def RandomStringGen() -> list: 6 | CaptchaStringList = [] 7 | for x in range(12): 8 | CaptchaString = "".join( 9 | random.SystemRandom().choice(string.ascii_letters + string.digits) 10 | for _ in range(7) 11 | ).lower() 12 | CaptchaStringList.append(CaptchaString) 13 | return CaptchaStringList 14 | 15 | 16 | def mathCaptchaGen(): 17 | mathCaptchaList = [] 18 | num01 = random.randint(1, 40) 19 | num02 = random.randint(41, 80) 20 | answer = num01 + num02 21 | 22 | answer_dict = {"num01": num01, "num02": num02, "answer": answer} 23 | 24 | for _ in range(11): 25 | mathCaptchaList.append(random.randint(1, 130)) 26 | mathCaptchaList.append(answer) 27 | random.shuffle(mathCaptchaList) 28 | return answer_dict, mathCaptchaList 29 | -------------------------------------------------------------------------------- /Emilia/info/admin_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Admin" 2 | 3 | __sub_mod__ = ["Bans"] 4 | 5 | __help__ = """ 6 | These commands are solely made for admins of group chats! 7 | 8 | **Commands**: 9 | 10 | • /promote : Promote a user. 11 | • /demote : Demote a user. 12 | 13 | • /admins: List the admins in the current chat. 14 | 15 | • /cleanblue ``: Will delete messages containing bot commands. 16 | 17 | • /setgpic ``: Set group's profile picture. 18 | • /title ``: Set an admin's custom title. 19 | • /setgtitle ``: Set group's title. 20 | • /setdesc ``: Set a group's description. 21 | • /setsticker ``: Set a group's sticker pack. 22 | 23 | • /anonadmin ``: Allow anonymous admins to use all commands without checking their permissions. Not recommended. 24 | """ 25 | -------------------------------------------------------------------------------- /Emilia/info/connection_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Connections" 2 | 3 | __help__ = """ 4 | Sometimes, you just want to add some notes and filters to a group chat, but you don't want everyone to see; This is where connections come in... 5 | 6 | This allows you to connect to a chat's database, and add things to it without the chat knowing about it! For obvious reasons, you need to be an admin to add things; but any member can view your data. (banned/kicked users can't!) 7 | 8 | **Admin commands**: 9 | • /connect : Connect to the specified chat, allowing you to view/edit contents. 10 | • /disconnect: Disconnect from the current chat. 11 | • /reconnect: Reconnect to the previously connect chat 12 | • /connection: See information about the currently connected chat. 13 | 14 | You can retrieve the chat id by using the /id command in your chat. Don't be surprised if the id is negative; all super groups have negative ids. 15 | """ 16 | -------------------------------------------------------------------------------- /Emilia/mongo/pin_mongo.py: -------------------------------------------------------------------------------- 1 | from Emilia import db 2 | 3 | pin = db.pin 4 | 5 | 6 | async def cleanlinked_db(chat_id: int, cleanlinked: bool) -> None: 7 | # Upsert directly 8 | await pin.update_one( 9 | {"chat_id": chat_id}, {"$set": {"cleanlinked": bool(cleanlinked)}}, upsert=True 10 | ) 11 | 12 | 13 | async def get_cleanlinked(chat_id: int) -> bool: 14 | doc = await pin.find_one({"chat_id": chat_id}, {"cleanlinked": 1}) 15 | return bool(doc.get("cleanlinked")) if doc else False 16 | 17 | 18 | async def antichannelpin_db(chat_id: int, antichannelpin: bool) -> None: 19 | await pin.update_one( 20 | {"chat_id": chat_id}, {"$set": {"antichannelpin": bool(antichannelpin)}}, upsert=True 21 | ) 22 | 23 | 24 | async def get_antichannelpin(chat_id: int) -> bool: 25 | doc = await pin.find_one({"chat_id": chat_id}, {"antichannelpin": 1}) 26 | return bool(doc.get("antichannelpin")) if doc else False 27 | -------------------------------------------------------------------------------- /Emilia/info/fed_user_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "User Commands" 2 | 3 | __hidden__ = True 4 | 5 | __help__ = """ 6 | These commands do not require you to be admin of a federation. These commands are for general commands, such as looking up information on a fed, or checking a user's fbans. 7 | 8 | **Commands**: 9 | • /fedinfo : Information about a federation. 10 | • /fedadmins : List the admins in a federation. 11 | • /fedsubs : List all federations your federation is subscribed to. 12 | • /joinfed : Join the current chat to a federation. A chat can only join one federation. Chat owners only. 13 | • /leavefed: Leave the current federation. Only chat owners can do this. 14 | • /fedstat: List all the federations that you have been banned in. 15 | • /chatfed: Information about the federation the current chat is in. 16 | • /quietfed : Whether or not to send ban notifications when fedbanned users join the chat. 17 | """ 18 | -------------------------------------------------------------------------------- /Emilia/mongo/chats_settings_mongo.py: -------------------------------------------------------------------------------- 1 | from Emilia import db 2 | from Emilia.utils.cache import anonymous_admin_cache 3 | 4 | chats = db.chats 5 | 6 | 7 | async def anonadmin_db(chat_id, arg): 8 | await chats.update_one({"chat_id": chat_id}, {"$set": {"anon_admin": arg}}, upsert=True) 9 | # Update cache 10 | key = f"anon_admin:{chat_id}" 11 | await anonymous_admin_cache.set(key, arg) 12 | 13 | 14 | async def get_anon_setting(chat_id) -> bool: 15 | doc = await chats.find_one({"chat_id": chat_id}, {"_id": 0, "anon_admin": 1}) 16 | return doc.get("anon_admin", False) if doc else False 17 | 18 | 19 | async def get_anon_setting_cached(chat_id) -> bool: 20 | key = f"anon_admin:{chat_id}" 21 | cached = await anonymous_admin_cache.get(key) 22 | if cached is not None: 23 | return cached 24 | 25 | val = await get_anon_setting(chat_id) 26 | await anonymous_admin_cache.set(key, val) 27 | return val 28 | -------------------------------------------------------------------------------- /Emilia/info/warn_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Warnings" 2 | 3 | __help__ = """ 4 | Keep your members in check with warnings; stop them getting out of control! 5 | 6 | If you're looking for automated warnings, go read about the blocklist module. 7 | 8 | **Admin commands**: 9 | 10 | • /warn ``: Warn a user. 11 | • /dwarn ``: Warn a user by reply, and delete their message. 12 | • /swarn ``: Silently warn a user, and delete your message. 13 | • /warns: See a user's warnings. 14 | • /resetwarn: Reset all of a user's warnings to 0. 15 | • /resetallwarns: Delete all the warnings in a chat. All users return to 0 warns. 16 | • /warnings: Get the chat's warning settings. 17 | • /warnmode ``: View or set the chat's warn mode. 18 | • /warnlimit ``: View or set the number of warnings before users are punished. 19 | 20 | **Examples**: 21 | 22 | • Warn a user. 23 | 24 | -> /warn @user For disobeying the rules 25 | """ 26 | -------------------------------------------------------------------------------- /Emilia/pyro/joke.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client 2 | from Emilia.utils.async_http import get 3 | 4 | from Emilia import custom_filter 5 | from Emilia.helper.disable import disable 6 | from Emilia.utils.decorators import * 7 | 8 | 9 | @Client.on_message( 10 | custom_filter.command(commands=["joke", "jokes", "funny"], disable=True) 11 | ) 12 | @rate_limit(RATE_LIMIT_GENERAL) 13 | @disable 14 | async def joke(client, message): 15 | try: 16 | response = await get("https://v2.jokeapi.dev/joke/Any") 17 | joke = response.json() 18 | try: 19 | get1 = joke["setup"] 20 | get2 = joke["delivery"] 21 | await message.reply(f"{get1}\n{get2}") 22 | except BaseException: 23 | get3 = joke["joke"] 24 | await message.reply(get3) 25 | except Exception as e: 26 | return await message.reply( 27 | str(e) + "\nPlease report to support chat @SpiralTechDivision" 28 | ) -------------------------------------------------------------------------------- /Emilia/info/extra_info.py: -------------------------------------------------------------------------------- 1 | from Emilia import BOT_NAME 2 | 3 | __mod_name__ = "Extras" 4 | 5 | __sub_mod__ = ["Misc"] 6 | 7 | __help__ = f""" 8 | Some extra stuff that developers of {BOT_NAME} made in their free time. 9 | 10 | **Commands**: 11 | 12 | React: 13 | • /react: Reacts with a random reaction 14 | 15 | Urban Dictonary: 16 | • /ud ``: Type the word or expression you want to search use 17 | 18 | Define: 19 | • /define ``: Defines the given word properly unlike /ud 20 | 21 | Wikipedia: 22 | • /wiki ``: wikipedia your query 23 | 24 | Wallpapers: 25 | • /wall ``: get a wallpaper from `alphacoders.com` 26 | 27 | Webshot: 28 | • /webss ``: Screenshots the given website url and sends. 29 | 30 | Hand-Write: 31 | • /write ``: Writes the given text on white page with a pen 🖊 32 | 33 | Away from Keyboard: 34 | • /afk ``: This command lets user know that you are not available at the moment. 35 | """ 36 | -------------------------------------------------------------------------------- /Emilia/info/pin_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Pin" 2 | 3 | __help__ = """ 4 | All the pin related commands can be found here; keep your chat up to date on the latest news with a simple pinned message! 5 | 6 | **User commands**: 7 | • /pinned: Get the current pinned message. 8 | 9 | **Admin commands**: 10 | 11 | • /pin: Pin the message you replied to. Add 'loud' or 'notify' to send a notification to group members. 12 | • /unpin: Unpin the current pinned message. If used as a reply, unpins the replied to message. 13 | • /unpinall: Unpins all pinned messages. 14 | • /antichannelpin ``: Don't let telegram auto-pin linked channels. If no arguments are given, shows current setting. 15 | • /cleanlinked ``: Delete messages sent by the linked channel. 16 | 17 | **Note**: When using antichannel pins, make sure to use the /unpin command, instead of doing it manually. Otherwise, the old message will get re-pinned when the channel sends any messages. 18 | """ 19 | -------------------------------------------------------------------------------- /Emilia/pyro/locks/lock_map.py: -------------------------------------------------------------------------------- 1 | from enum import Enum, auto 2 | 3 | 4 | class ExtendedEnum(Enum): 5 | @classmethod 6 | def list(cls): 7 | return list(map(lambda c: c.name, cls)) 8 | 9 | 10 | class LocksMap(ExtendedEnum): 11 | all = auto() 12 | album = auto() 13 | audio = auto() 14 | bot = auto() 15 | button = auto() 16 | command = auto() 17 | comment = auto() 18 | contact = auto() 19 | document = auto() 20 | email = auto() 21 | emojigame = auto() 22 | forward = auto() 23 | forwardbot = auto() 24 | forwardchannel = auto() 25 | forwarduser = auto() 26 | game = auto() 27 | gif = auto() 28 | inline = auto() 29 | invitelink = auto() 30 | location = auto() 31 | phone = auto() 32 | photo = auto() 33 | poll = auto() 34 | rtl = auto() 35 | sticker = auto() 36 | text = auto() 37 | url = auto() 38 | video = auto() 39 | videonote = auto() 40 | voice = auto() 41 | -------------------------------------------------------------------------------- /Emilia/pyro/notes/private_notes.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup 2 | 3 | from Emilia import BOT_USERNAME 4 | from Emilia.helper.note_helper.note_send_message import exceNoteMessageSender 5 | 6 | 7 | async def note_redirect(client, message): 8 | chat_id = int(message.text.split()[1].split("_")[1]) 9 | note_name = message.text.split()[1].split("_")[2] 10 | await exceNoteMessageSender(client, message, note_name, from_chat_id=chat_id) 11 | 12 | 13 | async def PrivateNoteButton(message, chat_id, NoteName): 14 | PrivateNoteButton = InlineKeyboardMarkup( 15 | [ 16 | InlineKeyboardButton( 17 | text="Click me!", 18 | url=f"http://t.me/{BOT_USERNAME}?start=note_{chat_id}_{NoteName}", 19 | ) 20 | ] 21 | ) 22 | await message.reply( 23 | text=f"Tap here to view '{NoteName}' in your private chat.", 24 | reply_markup=PrivateNoteButton, 25 | ) 26 | -------------------------------------------------------------------------------- /Emilia/info/purge_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Purges" 2 | 3 | __help__ = """ 4 | Need to delete lots of messages? That's what purges are for! 5 | 6 | **Admin commands**: 7 | 8 | • /purge: Delete all messages from the replied to message, to the current message. 9 | • /spurge: Same as purge, but doesn't send the final confirmation message. 10 | • /del: Deletes the replied to message. 11 | • /purgefrom: Reply to a message to mark the message as where to purge from • this should be used followed by a /purgeto. 12 | • /purgeto: Delete all messages between the replied to message, and the message marked by the latest /purgefrom. 13 | 14 | **Examples**: 15 | 16 | • Delete all messages from the replied to message, until now. 17 | -> /purge 18 | 19 | • Mark the first message to purge from (as a reply). 20 | -> /purgefrom 21 | 22 | • Mark the message to purge to (as a reply). All messages between the previously marked /purgefrom and the newly marked /purgeto will be deleted. 23 | -> /purgeto 24 | """ 25 | -------------------------------------------------------------------------------- /Emilia/helper/convert.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | 4 | async def convert_time(given_time: int, time_format: str): 5 | week = 518400 # 518400 seconds in a week 6 | day = 86400 # 86400 seconds in a day 7 | hour = 3600 # 3600 seconds in a hour 8 | minute = 60 # 60 seconds in a minute 9 | 10 | if time_format == "w": 11 | cal_time = given_time * week 12 | elif time_format == "d": 13 | cal_time = given_time * day 14 | elif time_format == "h": 15 | cal_time = given_time * hour 16 | elif time_format == "m": 17 | cal_time = given_time * minute 18 | 19 | return cal_time 20 | 21 | 22 | def convert_size(size_bytes): 23 | if size_bytes == 0: 24 | return "0B" 25 | size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB") 26 | i = int(math.floor(math.log(size_bytes, 1024))) 27 | p = math.pow(1024, i) 28 | s = round(size_bytes / p, 2) 29 | return "%s %s" % (s, size_name[i]) 30 | -------------------------------------------------------------------------------- /Emilia/tele/truthdare.py: -------------------------------------------------------------------------------- 1 | from Emilia.custom_filter import register 2 | from Emilia.helper.disable import disable 3 | from Emilia.utils.async_http import get 4 | 5 | 6 | async def fetch_question(url): 7 | r = await get(url) 8 | try: 9 | data = r.json() 10 | except Exception: 11 | return None 12 | return data.get("question") 13 | 14 | 15 | async def get_dare_question(): 16 | return await fetch_question("https://api.truthordarebot.xyz/v1/dare") 17 | 18 | 19 | async def get_truth_question(): 20 | return await fetch_question("https://api.truthordarebot.xyz/v1/truth") 21 | 22 | 23 | @register(pattern="dare", disable=True) 24 | @disable 25 | async def dare(event): 26 | dare = await get_dare_question() 27 | if dare: 28 | await event.reply(f"{dare}") 29 | 30 | 31 | @register(pattern="truth", disable=True) 32 | @disable 33 | async def truth(event): 34 | truth = await get_truth_question() 35 | if truth: 36 | await event.reply(f"{truth}") 37 | -------------------------------------------------------------------------------- /Emilia/info/report_info.py: -------------------------------------------------------------------------------- 1 | from Emilia import BOT_NAME 2 | 3 | __mod_name__ = "Reports" 4 | 5 | __help__ = f""" 6 | We're all busy people who don't have time to monitor our groups 24/7. But how do you react if someone in your group is spamming? 7 | 8 | Presenting reports; if someone in your group thinks someone needs reporting, they now have an easy way to call all admins. 9 | 10 | **User commands**: 11 | 12 | • /report: Reply to a message to report it for admins to review. 13 | • @admins: Same as /report 14 | 15 | **Admin commands**: 16 | • /reports ``: Enable/disable user reports. 17 | 18 | To report a user, simply reply to his message with @admin or /report; {BOT_NAME} will then reply with a message stating that admins have been notified. This message tags all the chat admins; same as if they had been @'ed. 19 | 20 | **Note** that the report commands do not work when admins use them; or when used to report an admin. {BOT_NAME} assumes that admins don't need to report, or be reported! 21 | """ 22 | -------------------------------------------------------------------------------- /Emilia/info/lock_ex_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Example commands" 2 | 3 | __hidden__ = True 4 | 5 | __help__ = """ 6 | Locks are a powerful tool, with lots of different options. So here are a few examples to get you started and familiar on how exactly to use them. 7 | 8 | **Examples**: 9 | • Stop all users from sending stickers with: 10 | -> `/lock sticker` 11 | 12 | • You can lock/unlock multiple items by chaining them: 13 | -> `/lock sticker photo gif video` 14 | 15 | • Want a harsher punishment for certain actions? Set a custom lock action for it! You must separate the types from your reason with ###: 16 | -> `/lock invitelink ### no promoting other chats {ban}` 17 | 18 | • Reset all custom lock actions and reasons; remember to unlock again after: 19 | -> `/lock all ###` 20 | 21 | • To allow forwards from a specific channel, eg @SpiralTechDivision, you can allowlist it. You can also use the ID, or invitelink: 22 | -> `/allowlist @SpiralTechDivision` 23 | 24 | • List all locks at once: 25 | -> `/locks list` 26 | 27 | """ 28 | -------------------------------------------------------------------------------- /Emilia/helper/note_helper/note_misc_helper.py: -------------------------------------------------------------------------------- 1 | from Emilia.helper.chat_status import isUserAdmin 2 | 3 | 4 | async def privateNote_and_admin_checker(message, text: str): 5 | privateNote = True 6 | if "{noprivate}" in text: 7 | text = text.replace("{noprivate}", "") 8 | privateNote = False 9 | elif "{private}" in text: 10 | text = text.replace("{private}", "") 11 | privateNote = True 12 | else: 13 | privateNote = None 14 | 15 | allow = True 16 | if "{admin}" in text: 17 | text = text.replace("{admin}", "") 18 | if not await isUserAdmin(message, silent=True): 19 | allow = False 20 | else: 21 | allow = True 22 | 23 | return (privateNote, allow) 24 | 25 | 26 | async def preview_text_replace(text): 27 | if "{preview}" in text: 28 | text = text.replace("{preview}", "") 29 | preview = False 30 | else: 31 | preview = True 32 | 33 | return (preview, text) 34 | -------------------------------------------------------------------------------- /Emilia/pyro/warnings/reset_warns.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client 2 | 3 | from Emilia import custom_filter 4 | from Emilia.helper.chat_status import isUserAdmin 5 | from Emilia.helper.get_user import get_user_id 6 | from Emilia.mongo.warnings_mongo import count_user_warn, reset_user_warns 7 | 8 | 9 | @Client.on_message(custom_filter.command(commands=["rmwarns", "resetwarn", "resetwarns"])) 10 | async def reset_warn(client, message): 11 | chat_id = message.chat.id 12 | 13 | if not await isUserAdmin(message): 14 | return 15 | 16 | user_info = await get_user_id(message) 17 | user_id = user_info.id 18 | warn_num = await count_user_warn(chat_id, user_id) 19 | 20 | if warn_num is None: 21 | return await message.reply( 22 | f"User {user_info.mention} has no warnings to delete! What are you trying to acheive?" 23 | ) 24 | 25 | await message.reply( 26 | f"User {user_info.mention} has had all their previous warns removed." 27 | ) 28 | await reset_user_warns(chat_id, user_id) 29 | -------------------------------------------------------------------------------- /Emilia/info/greetings_ex_usage.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Example to use" 2 | 3 | __hidden__ = True 4 | 5 | __help__ = """ 6 | Welomes and goodbyes can be customised in many ways - here are some examples! 7 | 8 | **Examples**: 9 | • Turn on welcomes: 10 | -> `/welcome on` 11 | 12 | • Disable welcomes: 13 | -> `/welcome off` 14 | 15 | • Turn on goodbyes (note: goodbye messages won't be sent in groups with over 50 members): 16 | -> `/goodbye on` 17 | 18 | • Set a simple custom welcome message: 19 | -> `/setwelcome Hi there, welcome to the chat! Remember to be respectful and follow the rules.` 20 | 21 | • Set a custom welcome message, using fillings to automatically: 22 | - use the new user's name 23 | - use the current group name 24 | - create a button to the group rules 25 | -> /setwelcome Hi {first}, welcome to {chatname}! Remember to be respectful and follow the rules. {rules} 26 | 27 | • Automatically delete old welcome messages: 28 | -> `/cleanwelcome on` 29 | 30 | • Get the welcome message without any formatting: 31 | -> `/welcome noformat` 32 | """ 33 | -------------------------------------------------------------------------------- /Emilia/mongo/disable_mongo.py: -------------------------------------------------------------------------------- 1 | from Emilia import db 2 | 3 | disable = db.disable 4 | 5 | 6 | async def disable_db(chat_id, disable_arg): 7 | await disable.update_one( 8 | {"chat_id": chat_id}, {"$addToSet": {"disabled_items": disable_arg}}, upsert=True 9 | ) 10 | 11 | 12 | async def enable_db(chat_id, enable_arg): 13 | await disable.update_one( 14 | {"chat_id": chat_id}, {"$pull": {"disabled_items": enable_arg}}, upsert=True 15 | ) 16 | 17 | 18 | async def get_disabled(chat_id) -> list: 19 | doc = await disable.find_one({"chat_id": chat_id}, {"disabled_items": 1}) 20 | return doc.get("disabled_items", []) if doc else [] 21 | 22 | 23 | async def disabledel_db(chat_id, disabledel): 24 | await disable.update_one( 25 | {"chat_id": chat_id}, {"$set": {"disabledel": bool(disabledel)}}, upsert=True 26 | ) 27 | 28 | 29 | async def get_disabledel(chat_id) -> bool: 30 | doc = await disable.find_one({"chat_id": chat_id}, {"disabledel": 1}) 31 | return bool(doc.get("disabledel")) if doc else False 32 | -------------------------------------------------------------------------------- /Emilia/info/formatting.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Markdown Formatting" 2 | __hidden__ = True 3 | 4 | __help__ = """ 5 | You can format your message using bold, italics, underline, and much more. Go ahead and experiment! 6 | 7 | **Supported markdown:** 8 | 9 | • _italic words_: Underscores are used for italic fonts. Shows as: italic words. 10 | • *bold words*: Asterisks are used for bold fonts. Shows as: bold words. 11 | • ~strikethrough~: Tildes are used for strikethrough. Shows as: strikethrough. 12 | • [hyperlink] (sempai.me): This is the formatting used for hyperlinks. Shows as: hyperlink. 13 | 14 | • [My button] (buttonurl://sempai.me): This is the formatting used for creating buttons. This example will create a button named "My button" which opens `sempai.me` when clicked. 15 | If you would like to send buttons on the same row, use the :same formatting. EG: 16 | [button 1] (buttonurl://example.com) 17 | [button 2] (buttonurl://example.com:same) 18 | [button 3] (buttonurl://example.com) 19 | This will show button 1 and 2 on the same line, with 3 underneath. 20 | """ 21 | -------------------------------------------------------------------------------- /Emilia/mongo/log_channels_mongo.py: -------------------------------------------------------------------------------- 1 | from Emilia import db 2 | 3 | log_channels = db.logchannels 4 | 5 | 6 | async def set_log_db(chat_id, channel_id, channel_title): 7 | await log_channels.update_one( 8 | {"chat_id": chat_id}, 9 | { 10 | "$set": { 11 | "channel_id": channel_id, 12 | "channel_title": channel_title, 13 | "categories": { 14 | "settings": True, 15 | "admin": True, 16 | "user": True, 17 | "automated": True, 18 | "reports": True, 19 | "other": True, 20 | }, 21 | } 22 | }, 23 | upsert=True, 24 | ) 25 | 26 | 27 | async def unset_log_db(chat_id): 28 | await log_channels.delete_one({"chat_id": chat_id}) 29 | 30 | 31 | async def get_set_channel(chat_id): 32 | doc = await log_channels.find_one({"chat_id": chat_id}, {"_id": 0, "channel_title": 1}) 33 | return doc.get("channel_title") if doc else None 34 | -------------------------------------------------------------------------------- /Emilia/utils/executors.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import functools 3 | from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor 4 | from multiprocessing import cpu_count 5 | 6 | thread_pool = ThreadPoolExecutor(max_workers=min(32, cpu_count() + 4)) 7 | 8 | 9 | async def run_in_process(func, *args, **kwargs): 10 | """ 11 | Runs a blocking function in a separate process. 12 | """ 13 | loop = asyncio.get_running_loop() 14 | # functools.partial is needed to pass kwargs if any, 15 | # though Executor.submit/run_in_executor usually handles *args. 16 | # For run_in_executor, we need to partial the function if we have kwargs. 17 | call = functools.partial(func, *args, **kwargs) 18 | return await loop.run_in_executor(process_pool, call) 19 | 20 | 21 | async def run_in_thread(func, *args, **kwargs): 22 | """ 23 | Runs a blocking function in a separate thread. 24 | """ 25 | loop = asyncio.get_running_loop() 26 | call = functools.partial(func, *args, **kwargs) 27 | return await loop.run_in_executor(thread_pool, call) -------------------------------------------------------------------------------- /Emilia/pyro/greetings/reset_goodbye.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, enums 2 | 3 | import Emilia.strings as strings 4 | from Emilia import custom_filter 5 | from Emilia.helper.chat_status import isUserCan 6 | from Emilia.mongo.welcome_mongo import UnSetGoodbye 7 | from Emilia.pyro.connection.connection import connection 8 | from Emilia.utils.decorators import * 9 | 10 | 11 | @Client.on_message(custom_filter.command(commands="resetgoodbye")) 12 | @anonadmin_checker 13 | async def ResetGoodbye(client, message): 14 | if await connection(message) is not None: 15 | chat_id = await connection(message) 16 | else: 17 | chat_id = message.chat.id 18 | 19 | if ( 20 | not str(chat_id).startswith("-100") 21 | and message.chat.type == enums.ChatType.PRIVATE 22 | ): 23 | return await message.reply(strings.is_pvt) 24 | 25 | if not await isUserCan(message, privileges="can_change_info"): 26 | return 27 | await UnSetGoodbye(chat_id) 28 | await message.reply("The Goodbye message has been reset to default!", quote=True) 29 | -------------------------------------------------------------------------------- /Emilia/pyro/greetings/reset_welcome.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, enums 2 | 3 | import Emilia.strings as strings 4 | from Emilia import custom_filter 5 | from Emilia.helper.chat_status import isUserCan 6 | from Emilia.mongo.welcome_mongo import UnSetWelcome 7 | from Emilia.pyro.connection.connection import connection 8 | from Emilia.utils.decorators import * 9 | 10 | 11 | @Client.on_message(custom_filter.command(commands="resetwelcome")) 12 | @anonadmin_checker 13 | async def ResetWelcome(client, message): 14 | if await connection(message) is not None: 15 | chat_id = await connection(message) 16 | else: 17 | chat_id = message.chat.id 18 | 19 | if ( 20 | not str(chat_id).startswith("-100") 21 | and message.chat.type == enums.ChatType.PRIVATE 22 | ): 23 | return await message.reply(strings.is_pvt) 24 | 25 | if not await isUserCan(message, privileges="can_change_info"): 26 | return 27 | await UnSetWelcome(chat_id) 28 | await message.reply("The welcome message has been reset to default!", quote=True) 29 | -------------------------------------------------------------------------------- /Emilia/info/disable_info.py: -------------------------------------------------------------------------------- 1 | from Emilia import BOT_NAME 2 | 3 | __mod_name__ = "Disabling" 4 | 5 | __help__ = f""" 6 | Not everyone wants every feature that {BOT_NAME} offers. Some commands are best left unused; to avoid spam and abuse. 7 | 8 | This allows you to disable some commonly used commands, so no one can use them. It'll also allow you to autodelete them, stopping people from bluetexting. 9 | 10 | **Admin commands**: 11 | • /disable ``: Stop users from using "commandname" in this group. 12 | • /enable ``: Allow users from using "commandname" in this group. 13 | • /disableable: List all disableable commands. 14 | • /disabledel ``: Delete disabled commands when used by non-admins. 15 | • /disabled: List the disabled commands in this chat. 16 | 17 | **Note**: 18 | When disabling a command, the command only gets disabled for non-admins. All admins can still use those commands. 19 | Disabled commands are still accessible through the /connect feature. If you would be interested to see this disabled too, let me know in the support chat. 20 | """ 21 | -------------------------------------------------------------------------------- /Emilia/pyro/rules/reset_rules_button.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, enums 2 | 3 | import Emilia.strings as strings 4 | from Emilia import custom_filter 5 | from Emilia.helper.chat_status import isUserCan 6 | from Emilia.mongo.rules_mongo import set_rule_button 7 | from Emilia.pyro.connection.connection import connection 8 | from Emilia.utils.decorators import * 9 | 10 | 11 | @Client.on_message(custom_filter.command(commands="resetrulesbutton")) 12 | @anonadmin_checker 13 | async def reset_rules(client, message): 14 | if await connection(message) is not None: 15 | chat_id = await connection(message) 16 | else: 17 | chat_id = message.chat.id 18 | 19 | if ( 20 | not str(chat_id).startswith("-100") 21 | and message.chat.type == enums.ChatType.PRIVATE 22 | ): 23 | return await message.reply(strings.is_pvt) 24 | 25 | if not await isUserCan(message, privileges="can_change_info"): 26 | return 27 | 28 | await set_rule_button(chat_id, "Rules") 29 | await message.reply("Reset the rules button name to default", quote=True) 30 | -------------------------------------------------------------------------------- /Emilia/info/greetings_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Greetings" 2 | 3 | __sub_mod__ = ["Example to use", "CAPTCHA", "Formatting"] 4 | 5 | __help__ = """ 6 | Give your members a warm welcome with the greetings module! Or a sad goodbye... Depends! 7 | 8 | **Admin commands**: 9 | 10 | • /welcome ``: Enable/disable welcome messages. 11 | • /goodbye ``: Enable/disable goodbye messages. 12 | • /setwelcome ``: Set a new welcome message. Supports markdown and buttons. 13 | • /resetwelcome: Reset the welcome message. 14 | • /setgoodbye ``: Set a new goodbye message. Supports markdown and buttons. 15 | • /resetgoodbye: Reset the goodbye message. 16 | • /cleanservice ``: Delete all service messages. Those are the annoying 'x joined the group' notifications you see when people join. 17 | • /cleanwelcome ``: Delete old welcome messages. When a new person joins, or after 5 minutes, the previous message will get deleted. 18 | 19 | **Examples**: 20 | 21 | • Get the welcome message without any formatting 22 | -> `/welcome noformat` 23 | """ 24 | -------------------------------------------------------------------------------- /Emilia/info/info_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Info" 2 | 3 | __help__ = """ 4 | This module allows user to check own's or other's certain information. 5 | 6 | **ID**: 7 | • /id: get the current group id. If used by replying to a message, gets that user's id. 8 | • /gifid: reply to a gif to me to tell you its file ID. 9 | • /stickerid: reply to a sticker to me to tell you its file ID. 10 | 11 | 12 | **Self addded information**: 13 | • /setme : will set your info 14 | • /me: will get your or another user's info. 15 | 16 | Examples: 17 | - `/setme I am a cat.` 18 | - `/me @username(defaults to yours if no user specified)` 19 | 20 | 21 | **Information others add on you**: 22 | • /bio: will get your or another user's bio. This cannot be set by yourself. 23 | • /setbio : while replying, will save another user's bio 24 | 25 | Examples: 26 | - `/bio @username(defaults to yours if not specified).` 27 | - `/setbio This user is a cat` (reply to the user) 28 | 29 | 30 | **Overall Information**: 31 | • /info: get information about a user. 32 | • /ginfo: get information about a chat. 33 | """ 34 | -------------------------------------------------------------------------------- /Emilia/utils/db.py: -------------------------------------------------------------------------------- 1 | __all__ = ["get_collection"] 2 | 3 | from motor.core import AgnosticClient, AgnosticCollection, AgnosticDatabase 4 | from typing import Dict, Any, Optional 5 | from Emilia import db as _DATABASE 6 | from Emilia.utils.constants import COLL, normalize_filter 7 | 8 | 9 | COLLECTIONS = COLL 10 | 11 | def get_collection(name: str) -> AgnosticCollection: 12 | """Create or Get Collection from your database""" 13 | return _DATABASE[name] 14 | 15 | def coll(name: str) -> AgnosticCollection: 16 | return get_collection(name) 17 | 18 | def find_one(name: str, flt: Dict[str, Any], projection: Optional[Dict[str, int]] = None): 19 | flt = normalize_filter(flt) 20 | return _DATABASE[name].find_one(flt, projection) 21 | 22 | def find(name: str, flt: Dict[str, Any], projection: Optional[Dict[str, int]] = None, *, batch_size: int = 200, limit: Optional[int] = None): 23 | flt = normalize_filter(flt) 24 | cursor = _DATABASE[name].find(flt, projection, batch_size=batch_size) 25 | if limit: 26 | cursor = cursor.limit(int(limit)) 27 | return cursor 28 | -------------------------------------------------------------------------------- /Emilia/info/notes_ex.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Example for usage" 2 | 3 | __hidden__ = True 4 | 5 | __help__ = """ 6 | Notes can seem quite complicated; so here are some examples, so you can get some inspiration. 7 | 8 | **Examples**: 9 | 10 | • Saving a note. Now, anyone using #test or /get test will see this message. To save an image, gif, sticker, or any other kind of data, simply reply to that message 11 | -> /save test This is a fancy note! 12 | 13 | • You can also link notes through notebuttons. To do this, simply use the notename as the URL: 14 | -> /save note This is a note [With a button](buttonurl://#anothernote) 15 | 16 | • To save an admin-only note: 17 | -> /save example This note will only be opened by admins {admin} 18 | 19 | • To send all notes to the user's PM: 20 | -> /privatenotes on 21 | 22 | • To send a single note to user's PM, add a {private} tag to your note: 23 | -> /save test This is a note that always goes to PM {private} 24 | 25 | • If you've enabled privatenotes, but have one note that you don't want to go to PM: 26 | -> /save test This is a note that always goes to groups {noprivate} 27 | """ 28 | -------------------------------------------------------------------------------- /Emilia/pyro/blocklists/resetblocklistreason.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, enums 2 | 3 | import Emilia.strings as strings 4 | from Emilia import custom_filter 5 | from Emilia.helper.chat_status import isUserCan 6 | from Emilia.mongo.blocklists_mongo import setblocklistreason_db 7 | from Emilia.pyro.connection.connection import connection 8 | from Emilia.utils.decorators import * 9 | 10 | 11 | @Client.on_message(custom_filter.command(commands="resetblocklistreason")) 12 | @anonadmin_checker 13 | async def resetblocklistreason(client, message): 14 | if await connection(message) is not None: 15 | chat_id = await connection(message) 16 | else: 17 | chat_id = message.chat.id 18 | 19 | if ( 20 | not str(chat_id).startswith("-100") 21 | and message.chat.type == enums.ChatType.PRIVATE 22 | ): 23 | return await message.reply(strings.is_pvt) 24 | 25 | if not await isUserCan(message, chat_id=chat_id, privileges="can_change_info"): 26 | return 27 | 28 | await setblocklistreason_db(chat_id, None) 29 | await message.reply("The default blocklist reason has been reset.") 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Arsh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Emilia/pyro/mute/unmute.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client 2 | from pyrogram.types import ChatPermissions 3 | 4 | from Emilia import custom_filter 5 | from Emilia.helper.chat_status import CheckAllAdminsStuffs 6 | from Emilia.helper.get_user import get_user_id 7 | from Emilia.utils.decorators import * 8 | from Emilia.utils.decorators import logging 9 | 10 | UNMUTE_PERMISSIONS = ChatPermissions( 11 | can_send_messages=True, 12 | can_send_media_messages=True, 13 | can_send_other_messages=True, 14 | can_add_web_page_previews=True, 15 | can_send_polls=True, 16 | ) 17 | 18 | 19 | @Client.on_message(custom_filter.command(commands="unmute")) 20 | @logging 21 | @anonadmin_checker 22 | async def ban(client, message): 23 | chat_id = message.chat.id 24 | 25 | if not await CheckAllAdminsStuffs(message, privileges="can_restrict_members"): 26 | return 27 | 28 | user_info = await get_user_id(message) 29 | user_id = user_info.id 30 | 31 | await client.restrict_chat_member(chat_id, user_id, UNMUTE_PERMISSIONS) 32 | 33 | await message.reply("Alright, they can speak again.") 34 | return "UNMUTE", user_id, user_info.first_name 35 | -------------------------------------------------------------------------------- /Emilia/info/fillings.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Fillings" 2 | 3 | __hidden__ = True 4 | 5 | __help__ = """ 6 | You can also customise the contents of your message with contextual data. For example, you could mention a user by name in the welcome message, or mention them in a filter! 7 | 8 | **Supported fillings**: 9 | • {first}: The user's first name. 10 | • {last}: The user's last name. 11 | • {fullname}: The user's full name. 12 | • {username}: The user's username. If they don't have one, mentions the user instead. 13 | • {mention}: Mentions the user with their firstname. 14 | • {id}: The user's ID. 15 | • {count}: Shows member count of a chat. 16 | • {chatname}: The chat's name. 17 | • {rules}: Create a button to the chat's rules. 18 | • {preview}: Enables link previews for this message. Useful when using links to Instant View pages. 19 | 20 | **Example usages**: 21 | • Save a filter using the user's name. 22 | -> /filter test {first} triggered this filter. 23 | 24 | • Add a rules button to a note. 25 | -> /save info Press the button to read the chat rules! {rules} 26 | 27 | • Mention a user in the welcome message 28 | -> /setwelcome Welcome {mention} to {chatname}!""" 29 | -------------------------------------------------------------------------------- /Emilia/pyro/log_channels/logchannel.py: -------------------------------------------------------------------------------- 1 | import html 2 | 3 | from pyrogram import Client 4 | 5 | from Emilia import custom_filter 6 | from Emilia.helper.chat_status import isUserAdmin 7 | from Emilia.mongo.log_channels_mongo import get_set_channel 8 | from Emilia.pyro.connection.connection import connection 9 | from Emilia.utils.decorators import * 10 | 11 | 12 | @Client.on_message(custom_filter.command(commands=("logchannel"))) 13 | @anonadmin_checker 14 | async def logcategories(client, message): 15 | 16 | if await connection(message) is not None: 17 | chat_id = await connection(message) 18 | else: 19 | chat_id = message.chat.id 20 | 21 | if not await isUserAdmin(message, pm_mode=True): 22 | return 23 | 24 | if await get_set_channel(chat_id) is not None: 25 | channel_title = await get_set_channel(chat_id) 26 | await message.reply( 27 | f"I am currently logging admin actions in '{html.escape(channel_title)}'.", 28 | quote=True, 29 | ) 30 | else: 31 | await message.reply( 32 | "There are no log channels assigned to this chat.", quote=True 33 | ) 34 | -------------------------------------------------------------------------------- /Emilia/pyro/log_channels/unsetlog.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, enums 2 | 3 | import Emilia.strings as strings 4 | from Emilia import custom_filter 5 | from Emilia.helper.chat_status import isUserCan 6 | from Emilia.mongo.log_channels_mongo import unset_log_db 7 | from Emilia.pyro.connection.connection import connection 8 | from Emilia.utils.decorators import * 9 | 10 | 11 | @Client.on_message(custom_filter.command(commands=("unsetlog"))) 12 | @anonadmin_checker 13 | async def unset_log(client, message): 14 | 15 | if await connection(message) is not None: 16 | chat_id = await connection(message) 17 | else: 18 | chat_id = message.chat.id 19 | 20 | if ( 21 | not str(chat_id).startswith("-100") 22 | and message.chat.type == enums.ChatType.PRIVATE 23 | ): 24 | return await message.reply(strings.is_pvt) 25 | 26 | if not await isUserCan(message, chat_id=chat_id, privileges="can_change_info"): 27 | return 28 | 29 | await unset_log_db(chat_id) 30 | 31 | await message.reply( 32 | "Successfully unset log channel. Admin actions will no longer be logged.", 33 | quote=True, 34 | ) 35 | -------------------------------------------------------------------------------- /Emilia/pyro/filters/filters.py: -------------------------------------------------------------------------------- 1 | import html 2 | 3 | from pyrogram import Client 4 | from pyrogram.enums import ChatType 5 | 6 | from Emilia import custom_filter 7 | from Emilia.helper.get_data import GetChat 8 | from Emilia.mongo.filters_mongo import get_filters_list 9 | from Emilia.pyro.connection.connection import connection 10 | 11 | 12 | @Client.on_message(custom_filter.command("filters")) 13 | async def filters(client, message): 14 | if await connection(message) is not None: 15 | chat_id = await connection(message) 16 | chat_title = await GetChat(chat_id, client) 17 | else: 18 | chat_id = message.chat.id 19 | chat_title = message.chat.title 20 | 21 | if message.chat.type == ChatType.PRIVATE: 22 | chat_title = "local" 23 | FILTERS = await get_filters_list(chat_id) 24 | 25 | if len(FILTERS) == 0: 26 | await message.reply(f"No filters in {html.escape(chat_title)}.") 27 | return 28 | 29 | filters_list = f"List of filters in {html.escape(chat_title)}:\n" 30 | 31 | for filter_ in FILTERS: 32 | filters_list += f"• `{filter_}`\n" 33 | 34 | await message.reply(filters_list) 35 | -------------------------------------------------------------------------------- /Emilia/info/sfw_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "SFW" 2 | 3 | __help__ = """ 4 | This module is safe for work (for real!) 5 | 6 | **Commands**: 7 | 8 | • /neko: Sends Random SFW Neko source Images. 9 | • /ngif: Sends Random Neko GIFs. 10 | • /tickle: Sends Random Tickle GIFs. 11 | • /feed: Sends Random Feeding GIFs. 12 | • /gasm: Sends Random Orgasm Stickers. 13 | • /avatar: Sends Random Avatar Stickers. 14 | • /waifu: Sends Random Waifu Stickers. 15 | • /kiss: Sends Random Kissing GIFs. 16 | • /cuddle: Sends Random Cuddle GIFs. 17 | • /foxgirl: Sends Random FoxGirl source Images. 18 | • /smug: Sends Random Smug GIFs. 19 | • /gecg: IDK 20 | • /slap: Sends Random Slap GIFs. 21 | 22 | **Some more SFW commands**: 23 | 24 | • /shinobu 25 | • /hug 26 | • /megumin 27 | • /bully 28 | • /cry 29 | • /awoo 30 | • /woof 31 | • /lick 32 | • /pat 33 | • /bonk 34 | • /yeet 35 | • /blush 36 | • /smile 37 | • /wave 38 | • /highfive 39 | • /handhold 40 | • /nom 41 | • /bite 42 | • /glomp 43 | • /slapgif 44 | • /kill 45 | • /kicks 46 | • /happy 47 | • /wink 48 | • /poke 49 | • /dance 50 | • /cringe 51 | • /wallpaper 52 | • /goose 53 | 54 | Please report to our support chat if some command is not working :) 55 | """ 56 | -------------------------------------------------------------------------------- /Emilia/info/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | from os.path import basename, dirname, isfile 3 | from Emilia import LOGGER 4 | 5 | 6 | def getListOfFiles(dirName): 7 | listOfFile = os.listdir(dirName) 8 | allFiles = list() 9 | for entry in listOfFile: 10 | fullPath = os.path.join(dirName, entry) 11 | if "__pycache__" not in fullPath: 12 | if os.path.isdir(fullPath): 13 | allFiles = allFiles + getListOfFiles(fullPath) 14 | else: 15 | allFiles.append(fullPath) 16 | 17 | return allFiles 18 | 19 | 20 | mod_paths = getListOfFiles(dirName=dirname(__file__)) + getListOfFiles( 21 | dirName=dirname(os.getcwd() + "/Emilia/tele/__init__.py") 22 | ) 23 | 24 | all_modules = [ 25 | f[:-3] 26 | for f in mod_paths 27 | if isfile(f) and f.endswith(".py") and not f.endswith("__init__.py") 28 | ] 29 | 30 | module_names = [ 31 | basename(f)[:-3] 32 | for f in mod_paths 33 | if isfile(f) and f.endswith(".py") and not f.endswith("__init__.py") 34 | ] 35 | 36 | LOGGER.error(("INFO - " f"{', '.join(module_names)} - MODULES LOADED")) 37 | ALL_MODULES = sorted(all_modules) 38 | __all__ = ALL_MODULES + ["ALL_MODULES"] 39 | -------------------------------------------------------------------------------- /Emilia/helper/note_helper/note_fillings.py: -------------------------------------------------------------------------------- 1 | async def NoteFillings(message, message_text): 2 | if message is not None and message.from_user: 3 | user_id = message.from_user.id 4 | first_name = message.from_user.first_name 5 | last_name = message.from_user.last_name 6 | if last_name is None: 7 | last_name = "" 8 | full_name = f"{first_name} {last_name}" 9 | username = ( 10 | message.from_user.username 11 | if message.from_user.username 12 | else message.from_user.mention 13 | ) 14 | mention = message.from_user.mention 15 | chat_title = message.chat.title 16 | 17 | try: 18 | FillingText = message_text.format( 19 | id=user_id, 20 | first=first_name, 21 | last=last_name, 22 | fullname=full_name, 23 | username=username, 24 | mention=mention, 25 | chatname=chat_title, 26 | ) 27 | except KeyError: 28 | FillingText = message_text 29 | 30 | else: 31 | FillingText = message_text 32 | 33 | return FillingText 34 | -------------------------------------------------------------------------------- /Emilia/pyro/connection/reconnect.py: -------------------------------------------------------------------------------- 1 | import html 2 | 3 | from pyrogram import Client 4 | from pyrogram.enums import ChatType 5 | 6 | from Emilia import custom_filter 7 | from Emilia.helper.get_data import GetChat 8 | from Emilia.mongo.connection_mongo import GetConnectedChat, reconnectChat 9 | from Emilia.pyro.connection.connection import connection 10 | 11 | 12 | @Client.on_message(custom_filter.command(commands=("reconnect"))) 13 | async def reconnectC(client, message): 14 | user_id = message.from_user.id 15 | if not (message.chat.type == ChatType.PRIVATE): 16 | await message.reply("You need to be in PM to use this.") 17 | return 18 | if await GetConnectedChat(user_id) is not None: 19 | chat_id = await GetConnectedChat(user_id) 20 | chat_title = await GetChat(chat_id, client) 21 | chat_title = html.escape(chat_title) 22 | if await connection(message) is None: 23 | await reconnectChat(user_id) 24 | await message.reply(f"You're now reconnected to {chat_title}.", quote=True) 25 | else: 26 | await message.reply( 27 | "You haven't made a connection to any chats yet.", quote=True 28 | ) 29 | -------------------------------------------------------------------------------- /Emilia/pyro/filters/stop.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client 2 | 3 | from Emilia import custom_filter 4 | from Emilia.helper.chat_status import isUserAdmin 5 | from Emilia.mongo.filters_mongo import get_filters_list, stop_db 6 | from Emilia.pyro.connection.connection import connection 7 | from Emilia.utils.decorators import * 8 | 9 | 10 | @usage("/stop [filter name]") 11 | @example("/stop meow") 12 | @description("Use this command to stop the active filter in chat.") 13 | @Client.on_message(custom_filter.command("stop")) 14 | async def stop(client, message): 15 | if await connection(message) is not None: 16 | chat_id = await connection(message) 17 | else: 18 | chat_id = message.chat.id 19 | 20 | if not await isUserAdmin(message): 21 | return 22 | 23 | if not (len(message.text.split()) >= 2): 24 | await usage_string(message, stop) 25 | return 26 | 27 | filter_name = message.text.split()[1] 28 | if filter_name not in (await get_filters_list(chat_id)): 29 | await message.reply("You haven't saved any filters on this word yet!") 30 | return 31 | 32 | await stop_db(chat_id, filter_name) 33 | await message.reply(f"I've stopped `{filter_name}`.") 34 | -------------------------------------------------------------------------------- /Emilia/pyro/disabling/disabled.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, enums 2 | 3 | import Emilia.strings as strings 4 | from Emilia import custom_filter 5 | from Emilia.helper.chat_status import isUserAdmin 6 | from Emilia.mongo.disable_mongo import get_disabled 7 | from Emilia.pyro.connection.connection import connection 8 | 9 | 10 | @Client.on_message(custom_filter.command(commands="disabled")) 11 | async def disable(client, message): 12 | if await connection(message) is not None: 13 | chat_id = await connection(message) 14 | else: 15 | chat_id = message.chat.id 16 | 17 | if ( 18 | not str(chat_id).startswith("-100") 19 | and message.chat.type == enums.ChatType.PRIVATE 20 | ): 21 | return await message.reply(strings.is_pvt) 22 | 23 | if not await isUserAdmin(message, pm_mode=True): 24 | return 25 | 26 | DISABLE_LIST = await get_disabled(chat_id) 27 | 28 | if len(DISABLE_LIST) == 0: 29 | await message.reply("There are no disabled commands in this chat.") 30 | return 31 | 32 | text = "The following commands are disabled in this chat:\n" 33 | for item in DISABLE_LIST: 34 | text += f"- `{item}`\n" 35 | 36 | await message.reply(text) 37 | -------------------------------------------------------------------------------- /Emilia/info/fun_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Fun" 2 | 3 | __sub_mod__ = ["Memes"] 4 | 5 | __help__ = """ 6 | Sometimes we all want to get out of that specific serious mood and do something fun instead, don't we? 7 | 8 | **Commands**: 9 | 10 | • /pokedex ``: Works like a real pokedex and gives you information about pokemons!\ 11 | 12 | • /joke: Sends random joke. 13 | 14 | • /couples: Works in a group chat, randomly selects two chosen couples for 24 hours. 15 | 16 | • /cosplay: Gives you random anime-cosplay pictures. 17 | 18 | • /lewd: Works same as above cosplay command but gives 18+ results. 19 | 20 | 21 | • /gif `` : Get your favourite GIF(s) 22 | 23 | • /gif ; (limit) : Get desirable number of GIF(s) 24 | 25 | **Example**: /gif cats ; 5 This will return 5 cat GIFs 26 | **NOTE**: Maximum limit is 50 27 | 28 | 29 | • /logo ``: Makes a logo for the given text. 30 | 31 | • /q ``: Will make a quotly sticker of replied text, you can also use `/q r`, `/q 3` and `/q white` to see blek megik happening. 32 | 33 | • /react: Reacts with a random reaction. 34 | 35 | • /truth or /dare: Play famous truth and dare game. 36 | 37 | • /tts ``: Text to speech. 38 | **Example**: `/tts ja meow meow` 39 | """ 40 | -------------------------------------------------------------------------------- /Emilia/pyro/rules/reset_rules.py: -------------------------------------------------------------------------------- 1 | import html 2 | 3 | from pyrogram import Client, enums 4 | 5 | import Emilia.strings as strings 6 | from Emilia import custom_filter 7 | from Emilia.helper.chat_status import isUserCan 8 | from Emilia.helper.get_data import GetChat 9 | from Emilia.mongo.rules_mongo import set_rules_db 10 | from Emilia.pyro.connection.connection import connection 11 | from Emilia.utils.decorators import * 12 | 13 | 14 | @Client.on_message(custom_filter.command(commands=["resetrules", "clearrules"])) 15 | @anonadmin_checker 16 | async def reset_rules(client, message): 17 | if await connection(message) is not None: 18 | chat_id = await connection(message) 19 | chat_title = await GetChat(chat_id, client) 20 | else: 21 | chat_id = message.chat.id 22 | chat_title = message.chat.title 23 | 24 | if ( 25 | not str(chat_id).startswith("-100") 26 | and message.chat.type == enums.ChatType.PRIVATE 27 | ): 28 | return await message.reply(strings.is_pvt) 29 | 30 | if not await isUserCan(message, privileges="can_change_info"): 31 | return 32 | 33 | await set_rules_db(chat_id, None) 34 | await message.reply( 35 | f"Rules for {html.escape(chat_title)} were successfully cleared!" 36 | ) -------------------------------------------------------------------------------- /Emilia/tele/mentionall.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from telethon import events 3 | import Emilia.strings as strings 4 | from Emilia import telethn 5 | from Emilia.custom_filter import register 6 | from Emilia.functions.admins import is_admin 7 | 8 | 9 | @register(pattern="all") 10 | @telethn.on(events.NewMessage(pattern=r"@all")) 11 | async def mentionall(event): 12 | if not event.is_group: 13 | return await event.reply(strings.is_pvt) 14 | 15 | if not await is_admin(event, event.sender_id): 16 | return await event.reply(strings.NOT_ADMIN) 17 | 18 | text = " " 19 | reply = await event.get_reply_message() 20 | 21 | if reply: 22 | text = reply.text or reply.caption or " " 23 | 24 | elif event.pattern_match and event.pattern_match.group(1): 25 | text = event.text.split(None, 1)[1] 26 | 27 | usrnum = 0 28 | usrtxt = "" 29 | async for usr in telethn.iter_participants(event.chat_id): 30 | usrnum += 1 31 | first_name = (usr.first_name).replace("[", "").replace("]", "") 32 | usrtxt += f"[{first_name}](tg://user?id={usr.id}) " 33 | if usrnum == 5: 34 | await telethn.send_message(event.chat_id, f"{usrtxt}\n\n{text}") 35 | await asyncio.sleep(3) 36 | usrnum = 0 37 | usrtxt = "" 38 | -------------------------------------------------------------------------------- /Emilia/info/lock_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Locks" 2 | 3 | __help__ = """ 4 | Do stickers annoy you? or want to avoid people sharing links? or pictures? You're in the right place! 5 | 6 | The locks module allows you to lock away some common items in the Telegram world; the bot will automatically delete them! 7 | 8 | **Admin commands**: 9 | 10 | • /lock : Lock one or more items. Now, only admins can use this type! 11 | • /unlock : Unlock one or more items. Everyone can use this type again! 12 | • /locks: List currently locked items. 13 | • /lockwarns : Enabled or disable whether a user should be warned when using a locked item. 14 | • /locktypes: Show the list of all lockable items. 15 | • /allowlist : Allowlist a URL, group ID, channel @, or bot @ to stop them being deleted by URL, forward, invitelink, and inline locks. Separate with a space to add multiple items at once. If no arguments are given, returns the current allowlist. 16 | • /rmallowlist : Remove an item from the allowlist - url, invitelink, and forward locking will now take effect on messages containing it again. Separate with a space to remove multiple items. 17 | • /rmallowlistall: Remove all allowlisted items. 18 | """ 19 | 20 | __sub_mod__ = ["Example commands", "Lock descriptions"] 21 | -------------------------------------------------------------------------------- /Emilia/pyro/pin/cleanlinked_checker.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, enums, filters 2 | 3 | 4 | from Emilia.helper.chat_status import isBotCan 5 | from Emilia.mongo.pin_mongo import get_cleanlinked 6 | 7 | 8 | @Client.on_message(filters.all & filters.group, group=6) 9 | async def cleanlinkedChecker(client, message): 10 | chat_id = message.chat.id 11 | if not (await get_cleanlinked(chat_id)): 12 | return 13 | 14 | channel_id = await GetLinkedChannel(client, chat_id) 15 | if channel_id is not None: 16 | if ( 17 | message.forward_from_chat 18 | and message.forward_from_chat.type == enums.ChatType.CHANNEL 19 | and message.forward_from_chat.id == channel_id 20 | ): 21 | if await isBotCan(message, privileges="can_delete_messages", silent=True): 22 | await message.delete() 23 | else: 24 | await message.reply( 25 | "I don't have the right to delete messages in the linked channel.\nError: `not_enough_permissions`" 26 | ) 27 | 28 | 29 | async def GetLinkedChannel(client, chat_id: int) -> str: 30 | chat_data = await client.get_chat(chat_id=chat_id) 31 | if chat_data.linked_chat: 32 | return chat_data.linked_chat.id 33 | else: 34 | return None 35 | -------------------------------------------------------------------------------- /Emilia/info/antiflood_info.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Antiflood" 2 | 3 | __help__ = """ 4 | You know how sometimes, people join, send 100 messages, and ruin your chat? With antiflood, that happens no more! 5 | 6 | Antiflood allows you to take action on users that send more than x messages in a row. Actions are: ban/mute/kick/tban/tmute 7 | 8 | **Admin commands**: 9 | 10 | • /flood: Get the current antiflood settings 11 | • /setflood : Set the number of messages after which to take action on a user. Set to '0', 'off', or 'no' to disable. 12 | • /setfloodtimer : Set the number of messages and time required for timed antiflood to take action on a user. Set to just 'off' or 'no' to disable. 13 | • /setfloodmode : Choose which action to take on a user who has been flooding. Possible actions: ban/mute/kick/tban/tmute 14 | 15 | • /clearflood : Whether to delete the messages that triggered the flood. 16 | 17 | **Examples**: 18 | 19 | • Set antiflood to trigger after 7 messages: 20 | -> /setflood 7 21 | 22 | • Disable antiflood: 23 | -> /setflood off 24 | 25 | • Set timed antiflood to trigger after 10 messages in 30 seconds: 26 | -> /setfloodtimer 10 30s 27 | 28 | • Set the antiflood action to mute: 29 | -> /setfloodmode mute 30 | 31 | • Set the antiflood action to a 3 day ban: 32 | -> /setfloodmode tban 3d 33 | """ 34 | -------------------------------------------------------------------------------- /Emilia/pyro/webshot.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client 2 | from pyrogram.errors import WebpageCurlFailed 3 | from pyrogram.types import Message 4 | 5 | from Emilia import custom_filter 6 | from Emilia.helper.disable import disable 7 | from Emilia.utils.decorators import * 8 | 9 | 10 | @usage("/webss [website link]") 11 | @example("/webss google.com") 12 | @description("Screenshots given website.") 13 | @Client.on_message(custom_filter.command(commands="webss", disable=True)) 14 | @disable 15 | @rate_limit(RATE_LIMIT_HEAVY) 16 | async def take_ss(_, message: Message): 17 | try: 18 | if len(message.text.split()) != 2: 19 | await usage_string(message, take_ss) 20 | return 21 | url = message.text.split(None, 1)[1] 22 | try: 23 | await message.reply_photo( 24 | photo=f"https://service.headless-render-api.com/screenshot/{url}", 25 | quote=False, 26 | ) 27 | except WebpageCurlFailed: 28 | url = "https://" + url 29 | await message.reply_photo( 30 | photo=f"https://service.headless-render-api.com/screenshot/{url}", 31 | quote=False, 32 | ) 33 | except TypeError: 34 | return await message.reply("No Such Website.") 35 | except Exception as e: 36 | await message.reply_text(str(e)) -------------------------------------------------------------------------------- /Emilia/pyro/users/logging.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, enums, filters 2 | 3 | from Emilia.mongo.users_mongo import add_chat, add_user 4 | 5 | 6 | @Client.on_message(filters.all & filters.group & ~filters.user(777000), group=1) 7 | async def logger(client, message): 8 | chat_id = message.chat.id 9 | chat_title = message.chat.title 10 | await add_chat(chat_id, chat_title) 11 | 12 | if message.from_user: 13 | user_id = message.from_user.id 14 | username = message.from_user.username 15 | await add_user(user_id, username, chat_id, chat_title) 16 | 17 | if message.reply_to_message and message.reply_to_message.from_user: 18 | user_id = message.reply_to_message.from_user.id 19 | username = message.reply_to_message.from_user.username 20 | 21 | await add_user(user_id, username, chat_id, chat_title) 22 | 23 | if message.forward_from: 24 | user_id = message.forward_from.id 25 | username = message.forward_from.username 26 | 27 | await add_user(user_id, username, Forwared=True) 28 | 29 | 30 | @Client.on_message(filters.all & ~filters.group & ~filters.user(777000)) 31 | async def pvtlogger(client, message): 32 | if message.chat.type == enums.ChatType.PRIVATE: 33 | username = message.from_user.username or None 34 | await add_user(message.from_user.id, username, Forwared=True) 35 | -------------------------------------------------------------------------------- /Emilia/pyro/locks/locks.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, enums 2 | 3 | import Emilia.strings as strings 4 | from Emilia import custom_filter 5 | from Emilia.helper.chat_status import isUserAdmin 6 | from Emilia.mongo.locks_mongo import get_locks 7 | from Emilia.pyro.connection.connection import connection 8 | from Emilia.pyro.locks import lock_map 9 | 10 | 11 | @Client.on_message(custom_filter.command(commands="locks")) 12 | async def locks(client, message): 13 | if await connection(message) is not None: 14 | chat_id = await connection(message) 15 | else: 16 | chat_id = message.chat.id 17 | 18 | if ( 19 | not str(chat_id).startswith("-100") 20 | and message.chat.type == enums.ChatType.PRIVATE 21 | ): 22 | return await message.reply(strings.is_pvt) 23 | 24 | if not await isUserAdmin(message, pm_mode=True): 25 | return 26 | 27 | LOCKS_LIST = await get_locks(chat_id) 28 | 29 | if len(LOCKS_LIST) == 0: 30 | return await message.reply("No items locked in this chat.") 31 | 32 | if 1 in LOCKS_LIST: 33 | return await message.reply("Jokes on you, everything's locked.") 34 | 35 | text = "These are the currently locked items:\n" 36 | for item in LOCKS_LIST: 37 | lock_name = lock_map.LocksMap(item).name 38 | text += f"• `{lock_name}`\n" 39 | 40 | await message.reply(text) 41 | -------------------------------------------------------------------------------- /Emilia/pyro/pin/antichannelpin_checker.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, enums, filters 2 | 3 | 4 | from Emilia.helper.chat_status import isBotCan 5 | from Emilia.mongo.pin_mongo import get_antichannelpin 6 | 7 | 8 | @Client.on_message(filters.all & filters.group, group=7) 9 | async def cleanlinkedChecker(client, message): 10 | chat_id = message.chat.id 11 | message_id = message.id 12 | if not (await get_antichannelpin(chat_id)): 13 | return 14 | 15 | channel_id = await GetLinkedChannel(client, chat_id) 16 | if channel_id is not None: 17 | if ( 18 | message.forward_from_chat 19 | and message.forward_from_chat.type == enums.ChatType.CHANNEL 20 | and message.forward_from_chat.id == channel_id 21 | ): 22 | if not await isBotCan(message, privileges="can_pin_messages", silent=True): 23 | return await message.reply( 24 | "I don't have the right to pin or unpin messages in this chat.\nError: `could_not_unpin`" 25 | ) 26 | 27 | await client.unpin_chat_message(chat_id=chat_id, message_id=message_id) 28 | 29 | 30 | async def GetLinkedChannel(client, chat_id: int) -> str: 31 | chat_data = await client.get_chat(chat_id=chat_id) 32 | if chat_data.linked_chat: 33 | return chat_data.linked_chat.id 34 | else: 35 | return None 36 | -------------------------------------------------------------------------------- /Emilia/pyro/greetings/set_welcome.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, enums 2 | 3 | import Emilia.strings as strings 4 | from Emilia import custom_filter 5 | from Emilia.helper.chat_status import isUserCan 6 | from Emilia.helper.welcome_helper.get_welcome_message import GetWelcomeMessage 7 | from Emilia.mongo.welcome_mongo import SetWelcome 8 | from Emilia.pyro.connection.connection import connection 9 | from Emilia.utils.decorators import * 10 | 11 | 12 | @Client.on_message(custom_filter.command(commands="setwelcome")) 13 | @anonadmin_checker 14 | async def set_welcome(client, message): 15 | if await connection(message) is not None: 16 | ChatID = await connection(message) 17 | else: 18 | ChatID = message.chat.id 19 | 20 | if ( 21 | not str(ChatID).startswith("-100") 22 | and message.chat.type == enums.ChatType.PRIVATE 23 | ): 24 | return await message.reply(strings.is_pvt) 25 | 26 | if not await isUserCan(message, chat_id=ChatID, privileges="can_change_info"): 27 | return 28 | 29 | if not message.reply_to_message or len(message.text.split()) > 1: 30 | return await message.reply("You need to give the welcome message some content!") 31 | 32 | CONTENT, TEXT, DATATYPE = GetWelcomeMessage(message) 33 | await SetWelcome(ChatID, CONTENT, TEXT, DATATYPE) 34 | await message.reply("The new welcome message has been saved!", quote=True) 35 | -------------------------------------------------------------------------------- /Emilia/pyro/notes/notes.py: -------------------------------------------------------------------------------- 1 | import html 2 | 3 | from pyrogram import Client 4 | from pyrogram.enums import ChatType 5 | 6 | from Emilia import custom_filter 7 | from Emilia.helper.disable import disable 8 | from Emilia.helper.get_data import GetChat 9 | from Emilia.mongo.notes_mongo import NoteList 10 | from Emilia.pyro.connection.connection import connection 11 | 12 | 13 | @Client.on_message(custom_filter.command(commands=(["notes", "saved"]), disable=True)) 14 | @disable 15 | async def Notes(client, message): 16 | if await connection(message) is not None: 17 | chat_id = await connection(message) 18 | chat_title = await GetChat(chat_id, client) 19 | else: 20 | chat_id = message.chat.id 21 | chat_title = message.chat.title 22 | 23 | if message.chat.type == ChatType.PRIVATE: 24 | chat_title = "local" 25 | 26 | Notes_list = await NoteList(chat_id) 27 | 28 | NoteHeader = f"List of notes in {html.escape(chat_title)}:\n" 29 | if len(Notes_list) != 0: 30 | for notes in Notes_list: 31 | NoteName = f" • `{notes}`\n" 32 | NoteHeader += NoteName 33 | await message.reply( 34 | f"{NoteHeader}\nYou can retrieve these notes by using `/get notename`, or `#notename`", 35 | quote=True, 36 | ) 37 | 38 | else: 39 | await message.reply(f"No notes in {chat_title}.", quote=True) 40 | -------------------------------------------------------------------------------- /Emilia/pyro/pin/unpin.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client 2 | 3 | from Emilia import custom_filter 4 | from Emilia.helper.chat_status import CheckAllAdminsStuffs 5 | from Emilia.utils.decorators import * 6 | 7 | 8 | @Client.on_message(custom_filter.command(commands="unpin")) 9 | @anonadmin_checker 10 | async def unpin(client, message): 11 | chat_id = message.chat.id 12 | if not await CheckAllAdminsStuffs(message, privileges="can_pin_messages"): 13 | return 14 | 15 | if message.reply_to_message: 16 | pinned_message_id = message.reply_to_message.id 17 | message_link = ( 18 | f"http://t.me/c/{str(chat_id).replace(str(-100), '')}/{pinned_message_id}" 19 | ) 20 | await message.reply(f"Unpinned [this message]({message_link}).") 21 | await client.unpin_chat_message(chat_id=chat_id, message_id=pinned_message_id) 22 | 23 | else: 24 | chat_data = await client.get_chat(chat_id=chat_id) 25 | if chat_data.pinned_message: 26 | pinned_message_id = chat_data.pinned_message.id 27 | await message.reply(f"Unpinned the last pinned message.") 28 | await client.unpin_chat_message( 29 | chat_id=chat_id, message_id=pinned_message_id 30 | ) 31 | else: 32 | await message.reply( 33 | "There are no pinned messages. What are you trying to unpin?" 34 | ) 35 | -------------------------------------------------------------------------------- /Emilia/info/chatlevels_info.py: -------------------------------------------------------------------------------- 1 | from Emilia import BOT_NAME 2 | 3 | __mod_name__ = "Rankings" 4 | 5 | __sub_mod__ = ["Karma"] 6 | 7 | __help__ = f""" 8 | **Leveling System** 9 | 10 | The Leveling System rewards active participation in group chats. Users earn Experience Points (XP) by chatting, which unlocks new Ranks and features. 11 | 12 | **Core Commands:** 13 | • `/register [name]` - Create your profile to start earning XP. 14 | • `/rank` - View your Rank Card, current stats, and progress. 15 | • `/leaderboard` - Display the top users in the current chat. 16 | • `/daily` - Claim your daily XP bonus. Consecutive claims build a **Streak Bonus**. 17 | • `/weekly` - Claim your weekly XP bonus (available every 7 days). 18 | • `/rankings` - View detailed information about Ranks and requirements. 19 | 20 | **Advanced Features:** 21 | • **Prestige**: Upon reaching the maximum rank, use `/prestige` to reset your level in exchange for a **Prestige Badge** and a permanent **XP Multiplier**. 22 | • **Reputation**: Reply to a helpful user with `/thanks` or `+rep` to increase their Reputation score. Use `/info` to view a user's Reputation. 23 | • **Events**: Administrators may activate global XP multipliers during special events. 24 | 25 | **Admin:** 26 | • `/level [on/off]` - Enable or disable the leveling system in the current chat. 27 | 28 | Note: You can link your Leveling profile with the Karma system using `/karma`. 29 | """ 30 | -------------------------------------------------------------------------------- /Emilia/pyro/warnings/add_warn.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client 2 | 3 | from Emilia import custom_filter 4 | from Emilia.helper.chat_status import isBotCan, isUserCan 5 | from Emilia.helper.get_user import get_text 6 | from Emilia.pyro.warnings.warn import warn 7 | from Emilia.utils.decorators import * 8 | 9 | 10 | @Client.on_message(custom_filter.command(commands=["warn", "swarn", "dwarn"])) 11 | @anonadmin_checker 12 | @logging 13 | async def addwarn(client, message): 14 | chat_id = message.chat.id 15 | message_id = None 16 | silent = False 17 | 18 | if not await isUserCan(message, privileges="can_restrict_members"): 19 | return 20 | 21 | if not await isBotCan(message, privileges="can_restrict_members"): 22 | return 23 | 24 | reason = await get_text(message) 25 | if not reason: 26 | reason = None 27 | 28 | if message.text.split()[0].find("dwarn") >= 0: 29 | if message.reply_to_message: 30 | message_id = message.reply_to_message.id 31 | 32 | elif message.text.split()[0].find("swarn") >= 0: 33 | message_id = message.id 34 | silent = True 35 | 36 | warn_r, log_msg, info = await warn(client, message, reason, silent, warn_user=None) 37 | 38 | if warn_r: 39 | if message_id is not None: 40 | await client.delete_messages(chat_id=chat_id, message_ids=message_id) 41 | return log_msg, info.id, info.first_name -------------------------------------------------------------------------------- /Emilia/pyro/greetings/set_goodbye.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, enums 2 | 3 | import Emilia.strings as strings 4 | from Emilia import custom_filter 5 | from Emilia.helper.chat_status import isUserCan 6 | from Emilia.helper.welcome_helper.get_welcome_message import GetWelcomeMessage 7 | from Emilia.mongo.welcome_mongo import SetGoodBye 8 | from Emilia.pyro.connection.connection import connection 9 | from Emilia.utils.decorators import * 10 | 11 | 12 | @Client.on_message(custom_filter.command(commands="setgoodbye")) 13 | @anonadmin_checker 14 | async def set_goodbye(client, message): 15 | if await connection(message) is not None: 16 | ChatID = await connection(message) 17 | else: 18 | ChatID = message.chat.id 19 | 20 | if ( 21 | not str(ChatID).startswith("-100") 22 | and message.chat.type == enums.ChatType.PRIVATE 23 | ): 24 | return await message.reply(strings.is_pvt) 25 | 26 | if not await isUserCan(message, privileges="can_change_info"): 27 | return 28 | 29 | command = message.text.split(" ") 30 | if not message.reply_to_message and len(command) == 1: 31 | return await message.reply("You need to give the goodbye message some content!") 32 | 33 | CONTENT, TEXT, DATATYPE = GetWelcomeMessage(message) 34 | await SetGoodBye(ChatID, CONTENT, TEXT, DATATYPE) 35 | await message.reply("The new goodbye message has been saved!", quote=True) 36 | -------------------------------------------------------------------------------- /Emilia/helper/button_gen.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from pyrogram.types import InlineKeyboardButton 4 | 5 | BTN_URL_REGEX = re.compile(r"(\[([^\[]+?)\]\(buttonurl:(?:/{0,2})(.+?)(:same)?\))") 6 | 7 | 8 | def button_markdown_parser(text): 9 | markdown_note = None 10 | markdown_note = text 11 | text_data = "" 12 | buttons = [] 13 | if markdown_note is None: 14 | return text_data, buttons 15 | prev = 0 16 | for match in BTN_URL_REGEX.finditer(markdown_note): 17 | n_escapes = 0 18 | to_check = match.start(1) - 1 19 | while to_check > 0 and markdown_note[to_check] == "\\": 20 | n_escapes += 1 21 | to_check -= 1 22 | 23 | if n_escapes % 2 == 0: 24 | if bool(match.group(4)) and buttons: 25 | buttons[-1].append( 26 | [InlineKeyboardButton(text=match.group(2), url=match.group(3))] 27 | ) 28 | else: 29 | buttons.append( 30 | [InlineKeyboardButton(text=match.group(2), url=match.group(3))] 31 | ) 32 | text_data += markdown_note[prev : match.start(1)] 33 | prev = match.end(1) 34 | else: 35 | text_data += markdown_note[prev:to_check] 36 | prev = match.start(1) - 1 37 | else: 38 | text_data += markdown_note[prev:] 39 | 40 | return text_data, buttons 41 | -------------------------------------------------------------------------------- /Emilia/info/captcha_info.py: -------------------------------------------------------------------------------- 1 | from Emilia import BOT_NAME 2 | 3 | __mod_name__ = "CAPTCHA" 4 | 5 | __hidden__ = True 6 | 7 | __help__ = f""" 8 | Some chats get a lot of users joining just to spam. This could be because they're trolls, or part of a spam network. 9 | To slow them down, you could try enabling CAPTCHAs. New users joining your chat will be required to complete a test to confirm that they're real people.' 10 | 11 | **Admin commands**: 12 | 13 | • /captcha ``: All users that join will need to solve a CAPTCHA. This proves they aren't a bot! 14 | • /captchamode `