├── Dockerfile ├── Git_Pull.bat ├── Git_Push.bat ├── LICENSE ├── LaylaRobot ├── __init__.py ├── __main__.py ├── bsdk │ ├── extras │ │ └── lol.txt │ └── fonts │ │ ├── 1.ttf │ │ ├── 10.ttf │ │ ├── 2.ttf │ │ ├── 4.ttf │ │ ├── 5.ttf │ │ ├── 6.ttf │ │ ├── 7.ttf │ │ ├── 8.ttf │ │ └── 9.ttf ├── conf.py ├── events.py ├── helper_extra │ ├── admin_rights.py │ ├── aichat.py │ └── badmedia.py ├── modules │ ├── __aimultilanguage.py │ ├── __core.py │ ├── __country.py │ ├── __encrypt.py │ ├── __forcesubs.py │ ├── __google.py │ ├── __gps.py │ ├── __heroku.py │ ├── __imdb.py │ ├── __init__.py │ ├── __nightmode.py │ ├── __shield.py │ ├── __songs.py │ ├── __speachtotext.py │ ├── __telegraph.py │ ├── __texttospeech.py │ ├── __tools.py │ ├── __weather.py │ ├── __zip.py │ ├── _pyrogithub.py │ ├── admin.py │ ├── afk.py │ ├── anime.py │ ├── antiflood.py │ ├── approve.py │ ├── backups.py │ ├── bans.py │ ├── blacklist.py │ ├── blacklist_stickers.py │ ├── blacklistusers.py │ ├── cleaner.py │ ├── connection.py │ ├── cricketscore.py │ ├── currency_converter.py │ ├── cust_filters.py │ ├── dbcleanup.py │ ├── debug.py │ ├── dev.py │ ├── disable.py │ ├── disasters.py │ ├── error_handler.py │ ├── eval.py │ ├── fakeit.py │ ├── feds.py │ ├── fun.py │ ├── fun_strings.py │ ├── games.py │ ├── get_common_chats.py │ ├── gettime.py │ ├── global_bans.py │ ├── gtranslator.py │ ├── helper_funcs │ │ ├── __init__.py │ │ ├── alternate.py │ │ ├── chat_status.py │ │ ├── extraction.py │ │ ├── filters.py │ │ ├── handlers.py │ │ ├── misc.py │ │ ├── msg_types.py │ │ ├── regex_helper.py │ │ ├── string_handling.py │ │ ├── string_store.py │ │ └── telethn │ │ │ ├── __init__.py │ │ │ └── chatstatus.py │ ├── locks.py │ ├── log_channel.py │ ├── logomaker.py │ ├── math.py │ ├── misc.py │ ├── modules.py │ ├── music.py │ ├── musicplayer.py │ ├── muting.py │ ├── notes.py │ ├── nsfw.py │ ├── paste.py │ ├── ping.py │ ├── purge.py │ ├── reactions.py │ ├── remote_cmds.py │ ├── reporting.py │ ├── rules.py │ ├── shell.py │ ├── speed_test.py │ ├── sql │ │ ├── __init__.py │ │ ├── afk_sql.py │ │ ├── aihelp_sql.py │ │ ├── antiflood_sql.py │ │ ├── approve_sql.py │ │ ├── blacklist_sql.py │ │ ├── blacklistusers_sql.py │ │ ├── blsticker_sql.py │ │ ├── chatbot_sql.py │ │ ├── cleaner_sql.py │ │ ├── connection_sql.py │ │ ├── cust_filters_sql.py │ │ ├── disable_sql.py │ │ ├── feds_sql.py │ │ ├── global_bans_sql.py │ │ ├── locks_sql.py │ │ ├── log_channel_sql.py │ │ ├── notes_sql.py │ │ ├── nsfw_sql.py │ │ ├── reporting_sql.py │ │ ├── rss_sql.py │ │ ├── rules_sql.py │ │ ├── userinfo_sql.py │ │ ├── users_sql.py │ │ ├── warns_sql.py │ │ └── welcome_sql.py │ ├── sql_extended │ │ ├── forceSubscribe_sql.py │ │ ├── night_mode_sql.py │ │ └── nsfw_watch_sql.py │ ├── stickers.py │ ├── tagall.py │ ├── truth_and_dare.py │ ├── truth_and_dare_string.py │ ├── ud.py │ ├── userinfo.py │ ├── users.py │ ├── wallpaper.py │ ├── warns.py │ ├── welcome.py │ ├── wiki.py │ └── zombies.py ├── mongo.py ├── pyrogramee │ ├── dark.py │ ├── errors.py │ ├── pluginshelper.py │ └── telethonbasics.py ├── resources │ ├── Chopsic.otf │ ├── Maghrib.ttf │ ├── blackbg.jpg │ ├── hero.png │ └── images.jpeg ├── sample_config.py └── utils │ ├── X │ ├── __init__.py │ ├── dbfunc.py │ ├── errors.py │ ├── exceptions.py │ ├── my.py │ ├── progress.py │ └── tools.py ├── Procfile ├── README.md ├── Setup venv.bat ├── _config.yml ├── app.json ├── exp.sh ├── heroku.yml ├── profanity_wordlist.txt ├── requirements.txt ├── restart.bat ├── runtime.txt ├── start.bat └── start_service.bat /Dockerfile: -------------------------------------------------------------------------------- 1 | # We're using Debian Slim Buster image 2 | FROM python:3.8.5-slim-buster 3 | 4 | ENV PIP_NO_CACHE_DIR 1 5 | 6 | RUN sed -i.bak 's/us-west-2\.ec2\.//' /etc/apt/sources.list 7 | 8 | # Installing Required Packages 9 | RUN apt update && apt upgrade -y && \ 10 | apt install --no-install-recommends -y \ 11 | debian-keyring \ 12 | debian-archive-keyring \ 13 | bash \ 14 | bzip2 \ 15 | curl \ 16 | figlet \ 17 | git \ 18 | util-linux \ 19 | libffi-dev \ 20 | libjpeg-dev \ 21 | libjpeg62-turbo-dev \ 22 | libwebp-dev \ 23 | linux-headers-amd64 \ 24 | musl-dev \ 25 | musl \ 26 | neofetch \ 27 | php-pgsql \ 28 | python3-lxml \ 29 | postgresql \ 30 | postgresql-client \ 31 | python3-psycopg2 \ 32 | libpq-dev \ 33 | libcurl4-openssl-dev \ 34 | libxml2-dev \ 35 | libxslt1-dev \ 36 | python3-pip \ 37 | python3-requests \ 38 | python3-sqlalchemy \ 39 | python3-tz \ 40 | python3-aiohttp \ 41 | openssl \ 42 | pv \ 43 | jq \ 44 | wget \ 45 | python3 \ 46 | python3-dev \ 47 | libreadline-dev \ 48 | libyaml-dev \ 49 | gcc \ 50 | sqlite3 \ 51 | libsqlite3-dev \ 52 | sudo \ 53 | zlib1g \ 54 | ffmpeg \ 55 | libssl-dev \ 56 | libgconf-2-4 \ 57 | libxi6 \ 58 | xvfb \ 59 | unzip \ 60 | libopus0 \ 61 | libopus-dev \ 62 | && rm -rf /var/lib/apt/lists /var/cache/apt/archives /tmp 63 | 64 | # Pypi package Repo upgrade 65 | RUN pip3 install --upgrade pip setuptools 66 | 67 | # Copy Python Requirements to /root/LaylaRobot 68 | RUN git clone -b shiken https://github.com/QueenArzoo/LaylaRobot /root/LaylaRobot 69 | WORKDIR /root/LaylaRobot 70 | 71 | #Copy config file to /root/LaylaRobot/LaylaRobot 72 | COPY ./LaylaRobot/sample_config.py ./LaylaRobot/config.py* /root/LaylaRobot/LaylaRobot/ 73 | 74 | ENV PATH="/home/bot/bin:$PATH" 75 | 76 | # Install requirements 77 | RUN pip3 install -U -r requirements.txt 78 | 79 | # Starting Worker 80 | CMD ["python3","-m","LaylaRobot"] 81 | -------------------------------------------------------------------------------- /Git_Pull.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | TITLE Github Quick-Pull 3 | 4 | :: Print the branch cause ..oooooo fancy! 5 | echo Pulling from branch: 6 | git branch 7 | echo. 8 | git pull 9 | -------------------------------------------------------------------------------- /Git_Push.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | TITLE Github Quick-pushing 3 | 4 | :: Print the branch cause people like me push to wrong branches and cry about it later. 5 | echo Pushing to branch: 6 | git branch 7 | echo. 8 | :: Take input for comment and thats about it 9 | set /p commit_title="Enter Commit title (pushes with you as author): " 10 | 11 | :: If you are reading comments to understand this part then you can go back stab yourself. 12 | echo. 13 | git pull 14 | git add * 15 | git commit -m "%commit_title%" 16 | git push 17 | 18 | 19 | :: Hail Hydra -------------------------------------------------------------------------------- /LaylaRobot/bsdk/extras/lol.txt: -------------------------------------------------------------------------------- 1 | @HEROGAMERS1 2 | -------------------------------------------------------------------------------- /LaylaRobot/bsdk/fonts/1.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shiv-x/LaylaRobot/a899ec54e1fa4048a1a71fdaedba14f9e679d8fb/LaylaRobot/bsdk/fonts/1.ttf -------------------------------------------------------------------------------- /LaylaRobot/bsdk/fonts/10.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shiv-x/LaylaRobot/a899ec54e1fa4048a1a71fdaedba14f9e679d8fb/LaylaRobot/bsdk/fonts/10.ttf -------------------------------------------------------------------------------- /LaylaRobot/bsdk/fonts/2.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shiv-x/LaylaRobot/a899ec54e1fa4048a1a71fdaedba14f9e679d8fb/LaylaRobot/bsdk/fonts/2.ttf -------------------------------------------------------------------------------- /LaylaRobot/bsdk/fonts/4.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shiv-x/LaylaRobot/a899ec54e1fa4048a1a71fdaedba14f9e679d8fb/LaylaRobot/bsdk/fonts/4.ttf -------------------------------------------------------------------------------- /LaylaRobot/bsdk/fonts/5.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shiv-x/LaylaRobot/a899ec54e1fa4048a1a71fdaedba14f9e679d8fb/LaylaRobot/bsdk/fonts/5.ttf -------------------------------------------------------------------------------- /LaylaRobot/bsdk/fonts/6.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shiv-x/LaylaRobot/a899ec54e1fa4048a1a71fdaedba14f9e679d8fb/LaylaRobot/bsdk/fonts/6.ttf -------------------------------------------------------------------------------- /LaylaRobot/bsdk/fonts/7.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shiv-x/LaylaRobot/a899ec54e1fa4048a1a71fdaedba14f9e679d8fb/LaylaRobot/bsdk/fonts/7.ttf -------------------------------------------------------------------------------- /LaylaRobot/bsdk/fonts/8.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shiv-x/LaylaRobot/a899ec54e1fa4048a1a71fdaedba14f9e679d8fb/LaylaRobot/bsdk/fonts/8.ttf -------------------------------------------------------------------------------- /LaylaRobot/bsdk/fonts/9.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shiv-x/LaylaRobot/a899ec54e1fa4048a1a71fdaedba14f9e679d8fb/LaylaRobot/bsdk/fonts/9.ttf -------------------------------------------------------------------------------- /LaylaRobot/conf.py: -------------------------------------------------------------------------------- 1 | from envparse import env 2 | from LaylaRobot import LOGGER 3 | 4 | DEFAULTS = { 5 | "LOAD_MODULES": True, 6 | } 7 | 8 | def get_str_key(name, required=False): 9 | if name in DEFAULTS: 10 | default = DEFAULTS[name] 11 | else: 12 | default = None 13 | if not (data := env.str(name, default=default)) and not required: 14 | LOGGER.warn("No str key: " + name) 15 | return None 16 | elif not data: 17 | LOGGER.critical("No str key: " + name) 18 | sys.exit(2) 19 | else: 20 | return data 21 | 22 | def get_int_key(name, required=False): 23 | if name in DEFAULTS: 24 | default = DEFAULTS[name] 25 | else: 26 | default = None 27 | if not (data := env.int(name, default=default)) and not required: 28 | LOGGER.warn("No int key: " + name) 29 | return None 30 | elif not data: 31 | LOGGER.critical("No int key: " + name) 32 | sys.exit(2) 33 | else: 34 | return data -------------------------------------------------------------------------------- /LaylaRobot/events.py: -------------------------------------------------------------------------------- 1 | from telethon import events 2 | from LaylaRobot import telethn 3 | 4 | 5 | def register(**args): 6 | """ Registers a new message. """ 7 | pattern = args.get("pattern", None) 8 | 9 | r_pattern = r"^[/!]" 10 | 11 | if pattern is not None and not pattern.startswith("(?i)"): 12 | args["pattern"] = "(?i)" + pattern 13 | 14 | args["pattern"] = pattern.replace("^/", r_pattern, 1) 15 | 16 | def decorator(func): 17 | telethn.add_event_handler(func, events.NewMessage(**args)) 18 | return func 19 | 20 | return decorator 21 | 22 | 23 | def chataction(**args): 24 | """ Registers chat actions. """ 25 | 26 | def decorator(func): 27 | telethn.add_event_handler(func, events.ChatAction(**args)) 28 | return func 29 | 30 | return decorator 31 | 32 | 33 | def userupdate(**args): 34 | """ Registers user updates. """ 35 | 36 | def decorator(func): 37 | telethn.add_event_handler(func, events.UserUpdate(**args)) 38 | return func 39 | 40 | return decorator 41 | 42 | 43 | def inlinequery(**args): 44 | """ Registers inline query. """ 45 | pattern = args.get("pattern", None) 46 | 47 | if pattern is not None and not pattern.startswith("(?i)"): 48 | args["pattern"] = "(?i)" + pattern 49 | 50 | def decorator(func): 51 | telethn.add_event_handler(func, events.InlineQuery(**args)) 52 | return func 53 | 54 | return decorator 55 | 56 | 57 | def callbackquery(**args): 58 | """ Registers inline query. """ 59 | 60 | def decorator(func): 61 | telethn.add_event_handler(func, events.CallbackQuery(**args)) 62 | return func 63 | 64 | return decorator 65 | 66 | -------------------------------------------------------------------------------- /LaylaRobot/helper_extra/admin_rights.py: -------------------------------------------------------------------------------- 1 | from telegram import User, Chat 2 | 3 | 4 | def user_can_promote(chat: Chat, user: User, bot_id: int) -> bool: 5 | return chat.get_member(user.id).can_promote_members 6 | 7 | 8 | def user_can_ban(chat: Chat, user: User, bot_id: int) -> bool: 9 | return chat.get_member(user.id).can_restrict_members 10 | 11 | 12 | def user_can_pin(chat: Chat, user: User, bot_id: int) -> bool: 13 | return chat.get_member(user.id).can_pin_messages 14 | 15 | 16 | def user_can_changeinfo(chat: Chat, user: User, bot_id: int) -> bool: 17 | return chat.get_member(user.id).can_change_info 18 | -------------------------------------------------------------------------------- /LaylaRobot/helper_extra/aichat.py: -------------------------------------------------------------------------------- 1 | from LaylaRobot.mongo import client as db_x 2 | 3 | lydia = db_x["CAHTBOT"] 4 | 5 | 6 | def add_chat(chat_id): 7 | stark = lydia.find_one({"chat_id": chat_id}) 8 | if stark: 9 | return False 10 | else: 11 | lydia.insert_one({"chat_id": chat_id}) 12 | return True 13 | 14 | 15 | def remove_chat(chat_id): 16 | stark = lydia.find_one({"chat_id": chat_id}) 17 | if not stark: 18 | return False 19 | else: 20 | lydia.delete_one({"chat_id": chat_id}) 21 | return True 22 | 23 | 24 | def get_all_chats(): 25 | r = list(lydia.find()) 26 | if r: 27 | return r 28 | else: 29 | return False 30 | 31 | 32 | def get_session(chat_id): 33 | stark = lydia.find_one({"chat_id": chat_id}) 34 | if not stark: 35 | return False 36 | else: 37 | return stark -------------------------------------------------------------------------------- /LaylaRobot/helper_extra/badmedia.py: -------------------------------------------------------------------------------- 1 | from LaylaRobot import telethn as tbot 2 | import requests 3 | import time 4 | 5 | 6 | 7 | async def is_nsfw(event): 8 | lmao = event 9 | if not ( 10 | lmao.gif 11 | or lmao.video 12 | or lmao.video_note 13 | or lmao.photo 14 | or lmao.sticker 15 | or lmao.media 16 | ): 17 | return False 18 | if lmao.video or lmao.video_note or lmao.sticker or lmao.gif: 19 | try: 20 | starkstark = event.client.download_media(lmao.media, thumb=-1) 21 | except: 22 | return False 23 | elif lmao.photo or lmao.sticker: 24 | try: 25 | starkstark = event.client.download_media(lmao.media) 26 | except: 27 | return False 28 | img = starkstark 29 | f = {"file": (img, open(img, "rb"))} 30 | 31 | r = requests.post("https://starkapi.herokuapp.com/nsfw/", files = f).json() 32 | if r.get("success") is False: 33 | is_nsfw = False 34 | elif r.get("is_nsfw") is True: 35 | is_nsfw = True 36 | elif r.get("is_nsfw") is False: 37 | is_nsfw = False 38 | return is_nsfw 39 | -------------------------------------------------------------------------------- /LaylaRobot/modules/__core.py: -------------------------------------------------------------------------------- 1 | from LaylaRobot import telethn as tbot 2 | from LaylaRobot.events import register 3 | import os 4 | import asyncio 5 | import os 6 | import time 7 | from datetime import datetime 8 | from LaylaRobot import OWNER_ID, DEV_USERS 9 | from LaylaRobot import TEMP_DOWNLOAD_DIRECTORY as path 10 | from LaylaRobot import TEMP_DOWNLOAD_DIRECTORY 11 | from datetime import datetime 12 | water = './LaylaRobot/resources/yone.jpg' 13 | client = tbot 14 | 15 | @register(pattern=r"^/send ?(.*)") 16 | async def Prof(event): 17 | if event.sender_id == OWNER_ID or event.sender_id == DEV_USERS: 18 | pass 19 | else: 20 | return 21 | thumb = water 22 | message_id = event.message.id 23 | input_str = event.pattern_match.group(1) 24 | the_plugin_file = "./LaylaRobot/modules/{}.py".format(input_str) 25 | if os.path.exists(the_plugin_file): 26 | message_id = event.message.id 27 | await event.client.send_file( 28 | event.chat_id, 29 | the_plugin_file, 30 | force_document=True, 31 | allow_cache=False, 32 | thumb=thumb, 33 | reply_to=message_id, 34 | ) 35 | else: 36 | await event.reply("No File Found!") 37 | 38 | 39 | -------------------------------------------------------------------------------- /LaylaRobot/modules/__country.py: -------------------------------------------------------------------------------- 1 | from telethon.tl.functions.photos import GetUserPhotosRequest 2 | from telethon.tl.functions.users import GetFullUserRequest 3 | from telethon.tl.types import MessageEntityMentionName 4 | from telethon.utils import get_input_location 5 | import flag 6 | import html, os 7 | from countryinfo import CountryInfo 8 | from LaylaRobot import telethn as borg 9 | from LaylaRobot.events import register 10 | 11 | 12 | @register(pattern="^/country (.*)") 13 | async def msg(event): 14 | if event.fwd_from: 15 | return 16 | input_str = event.pattern_match.group(1) 17 | lol = input_str 18 | country = CountryInfo(lol) 19 | try: 20 | a = country.info() 21 | except: 22 | await event.reply("Country Not Avaiable Currently") 23 | name = a.get("name") 24 | bb= a.get("altSpellings") 25 | hu = '' 26 | for p in bb: 27 | hu += p+", " 28 | 29 | area = a.get("area") 30 | borders = "" 31 | hell = a.get("borders") 32 | for fk in hell: 33 | borders += fk+", " 34 | 35 | call = "" 36 | WhAt = a.get("callingCodes") 37 | for what in WhAt: 38 | call+= what+" " 39 | 40 | capital = a.get("capital") 41 | currencies = "" 42 | fker = a.get("currencies") 43 | for FKer in fker: 44 | currencies += FKer+", " 45 | 46 | HmM = a.get("demonym") 47 | geo = a.get("geoJSON") 48 | pablo = geo.get("features") 49 | Pablo = pablo[0] 50 | PAblo = Pablo.get("geometry") 51 | EsCoBaR= PAblo.get("type") 52 | iso = "" 53 | iSo = a.get("ISO") 54 | for hitler in iSo: 55 | po = iSo.get(hitler) 56 | iso += po+", " 57 | fla = iSo.get("alpha2") 58 | nox = fla.upper() 59 | okie = flag.flag(nox) 60 | 61 | languages = a.get("languages") 62 | lMAO="" 63 | for lmao in languages: 64 | lMAO += lmao+", " 65 | 66 | nonive = a.get("nativeName") 67 | waste = a.get("population") 68 | reg = a.get("region") 69 | sub = a.get("subregion") 70 | tik = a.get("timezones") 71 | tom ="" 72 | for jerry in tik: 73 | tom+=jerry+", " 74 | 75 | GOT = a.get("tld") 76 | lanester = "" 77 | for targaryen in GOT: 78 | lanester+=targaryen+", " 79 | 80 | wiki = a.get("wiki") 81 | 82 | caption = f"""Information Gathered Successfully 83 | 84 | Country Name:- {name} 85 | Alternative Spellings:- {hu} 86 | Country Area:- {area} square kilometers 87 | Borders:- {borders} 88 | Calling Codes:- {call} 89 | Country's Capital:- {capital} 90 | Country's currency:- {currencies} 91 | Country's Flag:- {okie} 92 | Demonym:- {HmM} 93 | Country Type:- {EsCoBaR} 94 | ISO Names:- {iso} 95 | Languages:- {lMAO} 96 | Native Name:- {nonive} 97 | population:- {waste} 98 | Region:- {reg} 99 | Sub Region:- {sub} 100 | Time Zones:- {tom} 101 | Top Level Domain:- {lanester} 102 | wikipedia:- {wiki} 103 | 104 | Gathered By Layla. 105 | """ 106 | 107 | 108 | await borg.send_message( 109 | event.chat_id, 110 | caption, 111 | parse_mode="HTML", 112 | ) 113 | 114 | await event.delete() 115 | -------------------------------------------------------------------------------- /LaylaRobot/modules/__encrypt.py: -------------------------------------------------------------------------------- 1 | from LaylaRobot import telethn as tbot 2 | import os 3 | from LaylaRobot.events import register 4 | import secureme 5 | 6 | @register(pattern="^/encrypt ?(.*)") 7 | async def hmm(event): 8 | if event.reply_to_msg_id: 9 | lel = await event.get_reply_message() 10 | cmd = lel.text 11 | else: 12 | cmd = event.pattern_match.group(1) 13 | Text = cmd 14 | k = secureme.encrypt(Text) 15 | await event.reply(k) 16 | 17 | @register(pattern="^/decrypt ?(.*)") 18 | async def hmm(event): 19 | if event.reply_to_msg_id: 20 | lel = await event.get_reply_message() 21 | ok = lel.text 22 | else: 23 | ok = event.pattern_match.group(1) 24 | Text = ok 25 | k = secureme.decrypt(Text) 26 | await event.reply(k) 27 | -------------------------------------------------------------------------------- /LaylaRobot/modules/__gps.py: -------------------------------------------------------------------------------- 1 | import os 2 | from LaylaRobot import telethn as tbot 3 | from geopy.geocoders import Nominatim 4 | from LaylaRobot.events import register 5 | from LaylaRobot import * 6 | from telethon import * 7 | from telethon.tl import * 8 | 9 | GMAPS_LOC = "https://maps.googleapis.com/maps/api/geocode/json" 10 | 11 | 12 | @register(pattern="^/gps (.*)") 13 | async def _(event): 14 | args = event.pattern_match.group(1) 15 | 16 | try: 17 | geolocator = Nominatim(user_agent="SkittBot") 18 | location = args 19 | geoloc = geolocator.geocode(location) 20 | longitude = geoloc.longitude 21 | latitude = geoloc.latitude 22 | gm = "https://www.google.com/maps/search/{},{}".format(latitude, longitude) 23 | await tbot.send_file( 24 | event.chat_id, 25 | file=types.InputMediaGeoPoint( 26 | types.InputGeoPoint(float(latitude), float(longitude)) 27 | ), 28 | ) 29 | await event.reply( 30 | "Open with: [🌏Google Maps]({})".format(gm), 31 | link_preview=False, 32 | ) 33 | except Exception as e: 34 | print(e) 35 | await event.reply("I can't find that") 36 | 37 | -------------------------------------------------------------------------------- /LaylaRobot/modules/__imdb.py: -------------------------------------------------------------------------------- 1 | from LaylaRobot import telethn as tbot 2 | import os 3 | import re 4 | import bs4 5 | import requests 6 | from telethon import types 7 | from telethon.tl import functions 8 | from LaylaRobot.events import register 9 | 10 | langi = "en" 11 | 12 | 13 | @register(pattern="^/imdb (.*)") 14 | async def imdb(e): 15 | if e.fwd_from: 16 | return 17 | try: 18 | movie_name = e.pattern_match.group(1) 19 | remove_space = movie_name.split(" ") 20 | final_name = "+".join(remove_space) 21 | page = requests.get( 22 | "https://www.imdb.com/find?ref_=nv_sr_fn&q=" + final_name + "&s=all" 23 | ) 24 | str(page.status_code) 25 | soup = bs4.BeautifulSoup(page.content, "html.parser") 26 | odds = soup.findAll("tr", "odd") 27 | mov_title = odds[0].findNext("td").findNext("td").text 28 | mov_link = ( 29 | "http://www.imdb.com/" + odds[0].findNext("td").findNext("td").a["href"] 30 | ) 31 | page1 = requests.get(mov_link) 32 | soup = bs4.BeautifulSoup(page1.content, "lxml") 33 | if soup.find("div", "poster"): 34 | poster = soup.find("div", "poster").img["src"] 35 | else: 36 | poster = "" 37 | if soup.find("div", "title_wrapper"): 38 | pg = soup.find("div", "title_wrapper").findNext("div").text 39 | mov_details = re.sub(r"\s+", " ", pg) 40 | else: 41 | mov_details = "" 42 | credits = soup.findAll("div", "credit_summary_item") 43 | if len(credits) == 1: 44 | director = credits[0].a.text 45 | writer = "Not available" 46 | stars = "Not available" 47 | elif len(credits) > 2: 48 | director = credits[0].a.text 49 | writer = credits[1].a.text 50 | actors = [] 51 | for x in credits[2].findAll("a"): 52 | actors.append(x.text) 53 | actors.pop() 54 | stars = actors[0] + "," + actors[1] + "," + actors[2] 55 | else: 56 | director = credits[0].a.text 57 | writer = "Not available" 58 | actors = [] 59 | for x in credits[1].findAll("a"): 60 | actors.append(x.text) 61 | actors.pop() 62 | stars = actors[0] + "," + actors[1] + "," + actors[2] 63 | if soup.find("div", "inline canwrap"): 64 | story_line = soup.find("div", "inline canwrap").findAll("p")[0].text 65 | else: 66 | story_line = "Not available" 67 | info = soup.findAll("div", "txt-block") 68 | if info: 69 | mov_country = [] 70 | mov_language = [] 71 | for node in info: 72 | a = node.findAll("a") 73 | for i in a: 74 | if "country_of_origin" in i["href"]: 75 | mov_country.append(i.text) 76 | elif "primary_language" in i["href"]: 77 | mov_language.append(i.text) 78 | if soup.findAll("div", "ratingValue"): 79 | for r in soup.findAll("div", "ratingValue"): 80 | mov_rating = r.strong["title"] 81 | else: 82 | mov_rating = "Not available" 83 | await e.reply( 84 | "" 85 | "Title : " 86 | + mov_title 87 | + "\n" 88 | + mov_details 89 | + "\nRating : " 90 | + mov_rating 91 | + "\nCountry : " 92 | + mov_country[0] 93 | + "\nLanguage : " 94 | + mov_language[0] 95 | + "\nDirector : " 96 | + director 97 | + "\nWriter : " 98 | + writer 99 | + "\nStars : " 100 | + stars 101 | + "\nIMDB Url : " 102 | + mov_link 103 | + "\nStory Line : " 104 | + story_line, 105 | link_preview=True, 106 | parse_mode="HTML", 107 | ) 108 | except IndexError: 109 | await e.reply("Plox enter **Valid movie name** kthx") 110 | -------------------------------------------------------------------------------- /LaylaRobot/modules/__init__.py: -------------------------------------------------------------------------------- 1 | from LaylaRobot import LOAD, LOGGER, NO_LOAD 2 | 3 | 4 | def __list_all_modules(): 5 | import glob 6 | from os.path import basename, dirname, isfile 7 | 8 | # This generates a list of modules in this folder for the * in __main__ to work. 9 | mod_paths = glob.glob(dirname(__file__) + "/*.py") 10 | all_modules = [ 11 | basename(f)[:-3] 12 | for f in mod_paths 13 | if isfile(f) and f.endswith(".py") and not f.endswith("__init__.py") 14 | ] 15 | 16 | if LOAD or NO_LOAD: 17 | to_load = LOAD 18 | if to_load: 19 | if not all( 20 | any(mod == module_name for module_name in all_modules) 21 | for mod in to_load 22 | ): 23 | LOGGER.error("Invalid loadorder names. Quitting.") 24 | quit(1) 25 | 26 | all_modules = sorted(set(all_modules) - set(to_load)) 27 | to_load = list(all_modules) + to_load 28 | 29 | else: 30 | to_load = all_modules 31 | 32 | if NO_LOAD: 33 | LOGGER.info("Not loading: {}".format(NO_LOAD)) 34 | return [item for item in to_load if item not in NO_LOAD] 35 | 36 | return to_load 37 | 38 | return all_modules 39 | 40 | 41 | ALL_MODULES = __list_all_modules() 42 | LOGGER.info("Modules to load: %s", str(ALL_MODULES)) 43 | __all__ = ALL_MODULES + ["ALL_MODULES"] 44 | -------------------------------------------------------------------------------- /LaylaRobot/modules/__songs.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | #Saavn 4 | 5 | import requests 6 | import wget 7 | from pyrogram import filters 8 | 9 | from LaylaRobot import pbot as Jebot 10 | from LaylaRobot.pyrogramee.dark import get_arg 11 | 12 | 13 | @Jebot.on_message(filters.command("saavn")) 14 | async def song(client, message): 15 | message.chat.id 16 | message.from_user["id"] 17 | args = get_arg(message) + " " + "song" 18 | if args.startswith(" "): 19 | await message.reply("Enter song name❗") 20 | return "" 21 | m = await message.reply_text( 22 | "Downloading your song,\nPlz wait ⏳️" 23 | ) 24 | try: 25 | r = requests.get(f"https://jostapi.herokuapp.com/saavn?query={args}") 26 | except Exception as e: 27 | await m.edit(str(e)) 28 | return 29 | sname = r.json()[0]["song"] 30 | slink = r.json()[0]["media_url"] 31 | ssingers = r.json()[0]["singers"] 32 | file = wget.download(slink) 33 | ffile = file.replace("mp4", "m4a") 34 | os.rename(file, ffile) 35 | await message.reply_audio(audio=ffile, title=sname, performer=ssingers) 36 | os.remove(ffile) 37 | await m.delete() 38 | 39 | 40 | #deezer# 41 | # Credits for @TheHamkerCat 42 | 43 | import os 44 | import aiofiles 45 | import aiohttp 46 | from pyrogram import filters 47 | from LaylaRobot import pbot as Layla 48 | 49 | ARQ = "https://thearq.tech/" 50 | 51 | async def fetch(url): 52 | async with aiohttp.ClientSession() as session: 53 | async with session.get(url) as resp: 54 | try: 55 | data = await resp.json() 56 | except: 57 | data = await resp.text() 58 | return data 59 | 60 | async def download_song(url): 61 | song_name = f"asuna.mp3" 62 | async with aiohttp.ClientSession() as session: 63 | async with session.get(url) as resp: 64 | if resp.status == 200: 65 | f = await aiofiles.open(song_name, mode="wb") 66 | await f.write(await resp.read()) 67 | await f.close() 68 | return song_name 69 | 70 | 71 | @Layla.on_message(filters.command("deezer")) 72 | async def deezer(_, message): 73 | if len(message.command) < 2: 74 | await message.reply_text("Download Now Deezer") 75 | return 76 | text = message.text.split(None, 1)[1] 77 | query = text.replace(" ", "%20") 78 | m = await message.reply_text("Searching...") 79 | try: 80 | r = await fetch(f"{ARQ}deezer?query={query}&count=1") 81 | title = r[0]["title"] 82 | url = r[0]["url"] 83 | artist = r[0]["artist"] 84 | except Exception as e: 85 | await m.edit(str(e)) 86 | return 87 | await m.edit("Downloading...") 88 | song = await download_song(url) 89 | await m.edit("Uploading...") 90 | await message.reply_audio(audio=song, title=title, performer=artist) 91 | os.remove(song) 92 | await m.delete() 93 | 94 | #Deezer 95 | # Credits for @TheHamkerCat 96 | 97 | import os 98 | import aiofiles 99 | import aiohttp 100 | from pyrogram import filters 101 | from LaylaRobot import pbot as ASUNA 102 | 103 | ARQ = "https://thearq.tech/" 104 | 105 | async def fetch(url): 106 | async with aiohttp.ClientSession() as session: 107 | async with session.get(url) as resp: 108 | try: 109 | data = await resp.json() 110 | except: 111 | data = await resp.text() 112 | return data 113 | 114 | async def download_song(url): 115 | song_name = f"asuna.mp3" 116 | async with aiohttp.ClientSession() as session: 117 | async with session.get(url) as resp: 118 | if resp.status == 200: 119 | f = await aiofiles.open(song_name, mode="wb") 120 | await f.write(await resp.read()) 121 | await f.close() 122 | return song_name 123 | 124 | 125 | @Layla.on_message(filters.command("deezer")) 126 | async def deezer(_, message): 127 | if len(message.command) < 2: 128 | await message.reply_text("Download Now Deezer") 129 | return 130 | text = message.text.split(None, 1)[1] 131 | query = text.replace(" ", "%20") 132 | m = await message.reply_text("Searching...") 133 | try: 134 | r = await fetch(f"{ARQ}deezer?query={query}&count=1") 135 | title = r[0]["title"] 136 | url = r[0]["url"] 137 | artist = r[0]["artist"] 138 | except Exception as e: 139 | await m.edit(str(e)) 140 | return 141 | await m.edit("Downloading...") 142 | song = await download_song(url) 143 | await m.edit("Uploading...") 144 | await message.reply_audio(audio=song, title=title, performer=artist) 145 | os.remove(song) 146 | await m.delete() 147 | 148 | 149 | __mod_name__ = "◎Music" 150 | 151 | __help__ = """ 152 | • `/song`** : download the song in it's best quality available.(API BASED) 153 | • `/video`** : download the video song in it's best quality available. 154 | • `/deezer`** : download from deezer 155 | • `/lyrics`** : sends the complete lyrics of the song provided as input 156 | • `/glyrics`** song name : This plugin searches for song lyrics with song name and artist. 157 | """ 158 | 159 | -------------------------------------------------------------------------------- /LaylaRobot/modules/__speachtotext.py: -------------------------------------------------------------------------------- 1 | from LaylaRobot import telethn as tbot 2 | import os 3 | import urllib.request 4 | from datetime import datetime 5 | from typing import List 6 | from typing import Optional 7 | import requests 8 | from telethon import * 9 | from telethon import events 10 | from telethon.tl import functions 11 | from telethon.tl import types 12 | from telethon.tl.types import * 13 | 14 | from LaylaRobot import * 15 | from LaylaRobot.events import register 16 | 17 | 18 | async def is_register_admin(chat, user): 19 | if isinstance(chat, (types.InputPeerChannel, types.InputChannel)): 20 | return isinstance( 21 | ( 22 | await tbot(functions.channels.GetParticipantRequest(chat, user)) 23 | ).participant, 24 | (types.ChannelParticipantAdmin, types.ChannelParticipantCreator), 25 | ) 26 | if isinstance(chat, types.InputPeerUser): 27 | return True 28 | 29 | 30 | @register(pattern="^/stt$") 31 | async def _(event): 32 | if event.fwd_from: 33 | return 34 | if event.is_group: 35 | if not (await is_register_admin(event.input_chat, event.message.sender_id)): 36 | await event.reply("🚨 Need Admin Pewer.. You can't use this command.. But you can use in my pm") 37 | return 38 | 39 | start = datetime.now() 40 | if not os.path.isdir(TEMP_DOWNLOAD_DIRECTORY): 41 | os.makedirs(TEMP_DOWNLOAD_DIRECTORY) 42 | 43 | if event.reply_to_msg_id: 44 | previous_message = await event.get_reply_message() 45 | required_file_name = await event.client.download_media( 46 | previous_message, TEMP_DOWNLOAD_DIRECTORY 47 | ) 48 | if IBM_WATSON_CRED_URL is None or IBM_WATSON_CRED_PASSWORD is None: 49 | await event.reply( 50 | "You need to set the required ENV variables for this module. \nModule stopping" 51 | ) 52 | else: 53 | # await event.reply("Starting analysis") 54 | headers = { 55 | "Content-Type": previous_message.media.document.mime_type, 56 | } 57 | data = open(required_file_name, "rb").read() 58 | response = requests.post( 59 | IBM_WATSON_CRED_URL + "/v1/recognize", 60 | headers=headers, 61 | data=data, 62 | auth=("apikey", IBM_WATSON_CRED_PASSWORD), 63 | ) 64 | r = response.json() 65 | if "results" in r: 66 | # process the json to appropriate string format 67 | results = r["results"] 68 | transcript_response = "" 69 | transcript_confidence = "" 70 | for alternative in results: 71 | alternatives = alternative["alternatives"][0] 72 | transcript_response += " " + str(alternatives["transcript"]) 73 | transcript_confidence += ( 74 | " " + str(alternatives["confidence"]) + " + " 75 | ) 76 | end = datetime.now() 77 | ms = (end - start).seconds 78 | if transcript_response != "": 79 | string_to_show = "TRANSCRIPT: `{}`\nTime Taken: {} seconds\nConfidence: `{}`".format( 80 | transcript_response, ms, transcript_confidence 81 | ) 82 | else: 83 | string_to_show = "TRANSCRIPT: `Nil`\nTime Taken: {} seconds\n\n**No Results Found**".format( 84 | ms 85 | ) 86 | await event.reply(string_to_show) 87 | else: 88 | await event.reply(r["error"]) 89 | # now, remove the temporary file 90 | os.remove(required_file_name) 91 | else: 92 | await event.reply("Reply to a voice message, to get the text out of it.") 93 | 94 | 95 | __help__ = """ 96 | I can convert text to voice and voice to text.. 97 | ❍ /tts *:* Reply to any message to get text to speech output 98 | ❍ /stt*:* Type in reply to a voice message(support english only) to extract text from it. 99 | *Language Codes* 100 | `af,am,ar,az,be,bg,bn,bs,ca,ceb,co,cs,cy,da,de,el,en,eo,es, 101 | et,eu,fa,fi,fr,fy,ga,gd,gl,gu,ha,haw,hi,hmn,hr,ht,hu,hy, 102 | id,ig,is,it,iw,ja,jw,ka,kk,km,kn,ko,ku,ky,la,lb,lo,lt,lv,mg,mi,mk, 103 | ml,mn,mr,ms,mt,my,ne,nl,no,ny,pa,pl,ps,pt,ro,ru,sd,si,sk,sl, 104 | sm,sn,so,sq,sr,st,su,sv,sw,ta,te,tg,th,tl,tr,uk,ur,uz, 105 | vi,xh,yi,yo,zh,zh_CN,zh_TW,zu` 106 | """ 107 | 108 | __mod_name__ = "TTS/STT" -------------------------------------------------------------------------------- /LaylaRobot/modules/__telegraph.py: -------------------------------------------------------------------------------- 1 | from LaylaRobot.events import register 2 | from LaylaRobot import telethn as tbot 3 | TMP_DOWNLOAD_DIRECTORY = "./" 4 | from telethon import events 5 | import os 6 | from PIL import Image 7 | from datetime import datetime 8 | from telegraph import Telegraph, upload_file, exceptions 9 | Hero = "Layla" 10 | telegraph = Telegraph() 11 | r = telegraph.create_account(short_name=Hero) 12 | auth_url = r["auth_url"] 13 | 14 | 15 | @register(pattern="^/t(m|xt) ?(.*)") 16 | async def _(event): 17 | if event.fwd_from: 18 | return 19 | optional_title = event.pattern_match.group(2) 20 | if event.reply_to_msg_id: 21 | start = datetime.now() 22 | r_message = await event.get_reply_message() 23 | input_str = event.pattern_match.group(1) 24 | if input_str == "m": 25 | downloaded_file_name = await tbot.download_media( 26 | r_message, 27 | TMP_DOWNLOAD_DIRECTORY 28 | ) 29 | end = datetime.now() 30 | ms = (end - start).seconds 31 | h = await event.reply("Downloaded to {} in {} seconds.".format(downloaded_file_name, ms)) 32 | if downloaded_file_name.endswith((".webp")): 33 | resize_image(downloaded_file_name) 34 | try: 35 | start = datetime.now() 36 | media_urls = upload_file(downloaded_file_name) 37 | except exceptions.TelegraphException as exc: 38 | await h.edit("ERROR: " + str(exc)) 39 | os.remove(downloaded_file_name) 40 | else: 41 | end = datetime.now() 42 | ms_two = (end - start).seconds 43 | os.remove(downloaded_file_name) 44 | await h.edit("Uploaded to https://telegra.ph{})".format(media_urls[0]), link_preview=True) 45 | elif input_str == "xt": 46 | user_object = await tbot.get_entity(r_message.sender_id) 47 | title_of_page = user_object.first_name # + " " + user_object.last_name 48 | # apparently, all Users do not have last_name field 49 | if optional_title: 50 | title_of_page = optional_title 51 | page_content = r_message.message 52 | if r_message.media: 53 | if page_content != "": 54 | title_of_page = page_content 55 | downloaded_file_name = await tbot.download_media( 56 | r_message, 57 | TMP_DOWNLOAD_DIRECTORY 58 | ) 59 | m_list = None 60 | with open(downloaded_file_name, "rb") as fd: 61 | m_list = fd.readlines() 62 | for m in m_list: 63 | page_content += m.decode("UTF-8") + "\n" 64 | os.remove(downloaded_file_name) 65 | page_content = page_content.replace("\n", "
") 66 | response = telegraph.create_page( 67 | title_of_page, 68 | html_content=page_content 69 | ) 70 | end = datetime.now() 71 | ms = (end - start).seconds 72 | await event.reply("Pasted to https://telegra.ph/{} in {} seconds.".format(response["path"], ms), link_preview=True) 73 | else: 74 | await event.reply("Reply to a message to get a permanent telegra.ph link.") 75 | 76 | 77 | def resize_image(image): 78 | im = Image.open(image) 79 | im.save(image, "PNG") 80 | 81 | 82 | __help__ = """ 83 | I can upload files to Telegraph 84 | ❍ /tm :Get Telegraph Link Of Replied Media 85 | ❍ /txt :Get Telegraph Link of Replied Text 86 | """ 87 | 88 | __mod_name__ = "Telegraph" 89 | -------------------------------------------------------------------------------- /LaylaRobot/modules/__texttospeech.py: -------------------------------------------------------------------------------- 1 | from LaylaRobot import telethn as tbot 2 | import os 3 | 4 | from gtts import gTTS 5 | from gtts import gTTSError 6 | from telethon import * 7 | from telethon.tl import functions 8 | from telethon.tl import types 9 | from telethon.tl.types import * 10 | 11 | from LaylaRobot import * 12 | 13 | from LaylaRobot.events import register 14 | 15 | 16 | async def is_register_admin(chat, user): 17 | if isinstance(chat, (types.InputPeerChannel, types.InputChannel)): 18 | return isinstance( 19 | ( 20 | await tbot(functions.channels.GetParticipantRequest(chat, user)) 21 | ).participant, 22 | (types.ChannelParticipantAdmin, types.ChannelParticipantCreator), 23 | ) 24 | if isinstance(chat, types.InputPeerUser): 25 | return True 26 | 27 | 28 | @register(pattern="^/tts (.*)") 29 | async def _(event): 30 | if event.fwd_from: 31 | return 32 | if event.is_group: 33 | if not (await is_register_admin(event.input_chat, event.message.sender_id)): 34 | await event.reply("🚨 Need Admin Pewer.. You can't use this command.. But you can use in my pm") 35 | return 36 | 37 | input_str = event.pattern_match.group(1) 38 | reply_to_id = event.message.id 39 | if event.reply_to_msg_id: 40 | previous_message = await event.get_reply_message() 41 | text = previous_message.message 42 | lan = input_str 43 | elif "|" in input_str: 44 | lan, text = input_str.split("|") 45 | else: 46 | await event.reply( 47 | "Invalid Syntax\nFormat `/tts lang | text`\nFor eg: `/tts en | hello`" 48 | ) 49 | return 50 | text = text.strip() 51 | lan = lan.strip() 52 | try: 53 | tts = gTTS(text, tld="com", lang=lan) 54 | tts.save("k.mp3") 55 | except AssertionError: 56 | await event.reply( 57 | "The text is empty.\n" 58 | "Nothing left to speak after pre-precessing, " 59 | "tokenizing and cleaning." 60 | ) 61 | return 62 | except ValueError: 63 | await event.reply("Language is not supported.") 64 | return 65 | except RuntimeError: 66 | await event.reply("Error loading the languages dictionary.") 67 | return 68 | except gTTSError: 69 | await event.reply("Error in Google Text-to-Speech API request !") 70 | return 71 | with open("k.mp3", "r"): 72 | await tbot.send_file( 73 | event.chat_id, "k.mp3", voice_note=True, reply_to=reply_to_id 74 | ) 75 | os.remove("k.mp3") -------------------------------------------------------------------------------- /LaylaRobot/modules/__tools.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "◎Tools" 2 | 3 | __help__ = """ 4 | *Fake Info* 5 | ❍ /fakegen*:* Generates Fake Information 6 | ❍ /picgen*:* Generate a fake pic 7 | 8 | *Date-time-Weather* 9 | ❍ /time *:* Gives information about a timezone. 10 | ❍ /weather *:* Get weather info in a particular place. 11 | ❍ /wttr *:* Advanced weather module, usage same as /weather 12 | ❍ /wttr moon*:* Get the current status of moon 13 | 14 | *Quotly* 15 | - /q : reply any message with this command to create a sticker. 16 | 17 | *Converts* 18 | ❍ /encrypt*:* Encrypts The Given Text 19 | ❍ /decrypt*:* Decrypts Previously Ecrypted Text 20 | ❍ /zip*:* reply to a telegram file to compress it in .zip format 21 | ❍ /unzip*:* reply to a telegram file to decompress it from the .zip format 22 | """ 23 | -------------------------------------------------------------------------------- /LaylaRobot/modules/__weather.py: -------------------------------------------------------------------------------- 1 | from LaylaRobot import telethn as tbot 2 | import io 3 | import os 4 | import time 5 | 6 | import aiohttp 7 | from telethon import * 8 | from telethon.tl import functions 9 | from telethon.tl import types 10 | from telethon.tl.types import * 11 | 12 | from LaylaRobot import * 13 | 14 | from LaylaRobot.events import register 15 | 16 | 17 | async def is_register_admin(chat, user): 18 | if isinstance(chat, (types.InputPeerChannel, types.InputChannel)): 19 | return isinstance( 20 | ( 21 | await tbot(functions.channels.GetParticipantRequest(chat, user)) 22 | ).participant, 23 | (types.ChannelParticipantAdmin, types.ChannelParticipantCreator), 24 | ) 25 | if isinstance(chat, types.InputPeerUser): 26 | return True 27 | 28 | 29 | @register(pattern="^/weather (.*)") 30 | async def _(event): 31 | if event.fwd_from: 32 | return 33 | 34 | sample_url = ( 35 | "https://api.openweathermap.org/data/2.5/weather?q={}&APPID={}&units=metric" 36 | ) 37 | input_str = event.pattern_match.group(1) 38 | async with aiohttp.ClientSession() as session: 39 | response_api_zero = await session.get( 40 | sample_url.format(input_str, OPENWEATHERMAP_ID) 41 | ) 42 | response_api = await response_api_zero.json() 43 | if response_api["cod"] == 200: 44 | country_code = response_api["sys"]["country"] 45 | country_time_zone = int(response_api["timezone"]) 46 | sun_rise_time = int(response_api["sys"]["sunrise"]) + country_time_zone 47 | sun_set_time = int(response_api["sys"]["sunset"]) + country_time_zone 48 | await event.reply( 49 | """**Location**: {} 50 | **Temperature**: {}°С 51 | __minimium__: {}°С 52 | __maximum__ : {}°С 53 | **Humidity**: {}% 54 | **Wind**: {}m/s 55 | **Clouds**: {}hpa 56 | **Sunrise**: {} {} 57 | **Sunset**: {} {}""".format( 58 | input_str, 59 | response_api["main"]["temp"], 60 | response_api["main"]["temp_min"], 61 | response_api["main"]["temp_max"], 62 | response_api["main"]["humidity"], 63 | response_api["wind"]["speed"], 64 | response_api["clouds"]["all"], 65 | # response_api["main"]["pressure"], 66 | time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(sun_rise_time)), 67 | country_code, 68 | time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(sun_set_time)), 69 | country_code, 70 | ) 71 | ) 72 | else: 73 | await event.reply(response_api["message"]) 74 | 75 | 76 | @register(pattern="^/wttr (.*)") 77 | async def _(event): 78 | if event.fwd_from: 79 | return 80 | 81 | sample_url = "https://wttr.in/{}.png" 82 | # logger.info(sample_url) 83 | input_str = event.pattern_match.group(1) 84 | async with aiohttp.ClientSession() as session: 85 | response_api_zero = await session.get(sample_url.format(input_str)) 86 | # logger.info(response_api_zero) 87 | response_api = await response_api_zero.read() 88 | with io.BytesIO(response_api) as out_file: 89 | await event.reply(file=out_file) 90 | -------------------------------------------------------------------------------- /LaylaRobot/modules/_pyrogithub.py: -------------------------------------------------------------------------------- 1 | # © @Mr_Dark_Prince 2 | import aiohttp 3 | from pyrogram import filters 4 | from LaylaRobot import pbot 5 | from LaylaRobot.pyrogramee.errors import capture_err 6 | 7 | 8 | __mod_name__ = "Github" 9 | 10 | 11 | @pbot.on_message(filters.command('github')) 12 | @capture_err 13 | async def github(_, message): 14 | if len(message.command) != 2: 15 | await message.reply_text("/git Username") 16 | return 17 | username = message.text.split(None, 1)[1] 18 | URL = f'https://api.github.com/users/{username}' 19 | async with aiohttp.ClientSession() as session: 20 | async with session.get(URL) as request: 21 | if request.status == 404: 22 | return await message.reply_text("404") 23 | 24 | result = await request.json() 25 | try: 26 | url = result['html_url'] 27 | name = result['name'] 28 | company = result['company'] 29 | bio = result['bio'] 30 | created_at = result['created_at'] 31 | avatar_url = result['avatar_url'] 32 | blog = result['blog'] 33 | location = result['location'] 34 | repositories = result['public_repos'] 35 | followers = result['followers'] 36 | following = result['following'] 37 | caption = f"""**Info Of {name}** 38 | **Username:** `{username}` 39 | **Bio:** `{bio}` 40 | **Profile Link:** [Here]({url}) 41 | **Company:** `{company}` 42 | **Created On:** `{created_at}` 43 | **Repositories:** `{repositories}` 44 | **Blog:** `{blog}` 45 | **Location:** `{location}` 46 | **Followers:** `{followers}` 47 | **Following:** `{following}`""" 48 | except Exception as e: 49 | print(str(e)) 50 | pass 51 | await message.reply_photo(photo=avatar_url, caption=caption) 52 | -------------------------------------------------------------------------------- /LaylaRobot/modules/afk.py: -------------------------------------------------------------------------------- 1 | import random, html 2 | 3 | from LaylaRobot import dispatcher 4 | from LaylaRobot.modules.disable import ( 5 | DisableAbleCommandHandler, 6 | DisableAbleMessageHandler, 7 | ) 8 | from LaylaRobot.modules.sql import afk_sql as sql 9 | from LaylaRobot.modules.users import get_user_id 10 | from telegram import MessageEntity, Update 11 | from telegram.error import BadRequest 12 | from telegram.ext import CallbackContext, Filters, MessageHandler, run_async 13 | 14 | AFK_GROUP = 7 15 | AFK_REPLY_GROUP = 8 16 | 17 | 18 | @run_async 19 | def afk(update: Update, context: CallbackContext): 20 | args = update.effective_message.text.split(None, 1) 21 | user = update.effective_user 22 | 23 | if not user: # ignore channels 24 | return 25 | 26 | if user.id in [777000, 1087968824]: 27 | return 28 | 29 | notice = "" 30 | if len(args) >= 2: 31 | reason = args[1] 32 | if len(reason) > 100: 33 | reason = reason[:100] 34 | notice = "\nYour afk reason was shortened to 100 characters." 35 | else: 36 | reason = "" 37 | 38 | sql.set_afk(update.effective_user.id, reason) 39 | fname = update.effective_user.first_name 40 | try: 41 | update.effective_message.reply_text("{} is now away!{}".format(fname, notice)) 42 | except BadRequest: 43 | pass 44 | 45 | 46 | @run_async 47 | def no_longer_afk(update: Update, context: CallbackContext): 48 | user = update.effective_user 49 | message = update.effective_message 50 | 51 | if not user: # ignore channels 52 | return 53 | 54 | res = sql.rm_afk(user.id) 55 | if res: 56 | if message.new_chat_members: # dont say msg 57 | return 58 | firstname = update.effective_user.first_name 59 | try: 60 | options = [ 61 | "{} is here!", 62 | "{} is back!", 63 | "{} is now in the chat!", 64 | "{} is awake!", 65 | "{} is back online!", 66 | "{} is finally here!", 67 | "Welcome back! {}", 68 | "Where is {}?\nIn the chat!", 69 | ] 70 | chosen_option = random.choice(options) 71 | update.effective_message.reply_text(chosen_option.format(firstname)) 72 | except: 73 | return 74 | 75 | 76 | @run_async 77 | def reply_afk(update: Update, context: CallbackContext): 78 | bot = context.bot 79 | message = update.effective_message 80 | userc = update.effective_user 81 | userc_id = userc.id 82 | if message.entities and message.parse_entities( 83 | [MessageEntity.TEXT_MENTION, MessageEntity.MENTION] 84 | ): 85 | entities = message.parse_entities( 86 | [MessageEntity.TEXT_MENTION, MessageEntity.MENTION] 87 | ) 88 | 89 | chk_users = [] 90 | for ent in entities: 91 | if ent.type == MessageEntity.TEXT_MENTION: 92 | user_id = ent.user.id 93 | fst_name = ent.user.first_name 94 | 95 | if user_id in chk_users: 96 | return 97 | chk_users.append(user_id) 98 | 99 | if ent.type != MessageEntity.MENTION: 100 | return 101 | 102 | user_id = get_user_id(message.text[ent.offset : ent.offset + ent.length]) 103 | if not user_id: 104 | # Should never happen, since for a user to become AFK they must have spoken. Maybe changed username? 105 | return 106 | 107 | if user_id in chk_users: 108 | return 109 | chk_users.append(user_id) 110 | 111 | try: 112 | chat = bot.get_chat(user_id) 113 | except BadRequest: 114 | print("Error: Could not fetch userid {} for AFK module".format(user_id)) 115 | return 116 | fst_name = chat.first_name 117 | 118 | check_afk(update, context, user_id, fst_name, userc_id) 119 | 120 | elif message.reply_to_message: 121 | user_id = message.reply_to_message.from_user.id 122 | fst_name = message.reply_to_message.from_user.first_name 123 | check_afk(update, context, user_id, fst_name, userc_id) 124 | 125 | 126 | def check_afk(update, context, user_id, fst_name, userc_id): 127 | if sql.is_afk(user_id): 128 | user = sql.check_afk_status(user_id) 129 | if int(userc_id) == int(user_id): 130 | return 131 | if not user.reason: 132 | res = "{} is afk".format(fst_name) 133 | update.effective_message.reply_text(res) 134 | else: 135 | res = "{} is afk.\nReason: {}".format( 136 | html.escape(fst_name), html.escape(user.reason) 137 | ) 138 | update.effective_message.reply_text(res, parse_mode="html") 139 | 140 | 141 | 142 | AFK_HANDLER = DisableAbleCommandHandler("afk", afk) 143 | AFK_REGEX_HANDLER = DisableAbleMessageHandler( 144 | Filters.regex(r"^(?i)brb(.*)$"), afk, friendly="afk" 145 | ) 146 | NO_AFK_HANDLER = MessageHandler(Filters.all & Filters.group, no_longer_afk) 147 | AFK_REPLY_HANDLER = MessageHandler(Filters.all & Filters.group, reply_afk) 148 | 149 | dispatcher.add_handler(AFK_HANDLER, AFK_GROUP) 150 | dispatcher.add_handler(AFK_REGEX_HANDLER, AFK_GROUP) 151 | dispatcher.add_handler(NO_AFK_HANDLER, AFK_GROUP) 152 | dispatcher.add_handler(AFK_REPLY_HANDLER, AFK_REPLY_GROUP) 153 | 154 | __mod_name__ = "AFK" 155 | __command_list__ = ["afk"] 156 | __handlers__ = [ 157 | (AFK_HANDLER, AFK_GROUP), 158 | (AFK_REGEX_HANDLER, AFK_GROUP), 159 | (NO_AFK_HANDLER, AFK_GROUP), 160 | (AFK_REPLY_HANDLER, AFK_REPLY_GROUP), 161 | ] 162 | -------------------------------------------------------------------------------- /LaylaRobot/modules/blacklistusers.py: -------------------------------------------------------------------------------- 1 | # Module to blacklist users and prevent them from using commands by @TheRealPhoenix 2 | import html 3 | import LaylaRobot.modules.sql.blacklistusers_sql as sql 4 | from LaylaRobot import ( 5 | DEV_USERS, 6 | OWNER_ID, 7 | DRAGONS, 8 | DEMONS, 9 | TIGERS, 10 | WOLVES, 11 | dispatcher, 12 | ) 13 | from LaylaRobot.modules.helper_funcs.chat_status import dev_plus 14 | from LaylaRobot.modules.helper_funcs.extraction import ( 15 | extract_user, 16 | extract_user_and_text, 17 | ) 18 | from LaylaRobot.modules.log_channel import gloggable 19 | from telegram import ParseMode, Update 20 | from telegram.error import BadRequest 21 | from telegram.ext import CallbackContext, CommandHandler, run_async 22 | from telegram.utils.helpers import mention_html 23 | 24 | BLACKLISTWHITELIST = [OWNER_ID] + DEV_USERS + DRAGONS + WOLVES + DEMONS 25 | BLABLEUSERS = [OWNER_ID] + DEV_USERS 26 | 27 | 28 | @run_async 29 | @dev_plus 30 | @gloggable 31 | def bl_user(update: Update, context: CallbackContext) -> str: 32 | message = update.effective_message 33 | user = update.effective_user 34 | bot, args = context.bot, context.args 35 | user_id, reason = extract_user_and_text(message, args) 36 | 37 | if not user_id: 38 | message.reply_text("I doubt that's a user.") 39 | return "" 40 | 41 | if user_id == bot.id: 42 | message.reply_text("How am I supposed to do my work if I am ignoring myself?") 43 | return "" 44 | 45 | if user_id in BLACKLISTWHITELIST: 46 | message.reply_text("No!\nNoticing Disasters is my job.") 47 | return "" 48 | 49 | try: 50 | target_user = bot.get_chat(user_id) 51 | except BadRequest as excp: 52 | if excp.message == "User not found": 53 | message.reply_text("I can't seem to find this user.") 54 | return "" 55 | else: 56 | raise 57 | 58 | sql.blacklist_user(user_id, reason) 59 | message.reply_text("I shall ignore the existence of this user!") 60 | log_message = ( 61 | f"#BLACKLIST\n" 62 | f"Admin: {mention_html(user.id, html.escape(user.first_name))}\n" 63 | f"User: {mention_html(target_user.id, html.escape(target_user.first_name))}" 64 | ) 65 | if reason: 66 | log_message += f"\nReason: {reason}" 67 | 68 | return log_message 69 | 70 | 71 | @run_async 72 | @dev_plus 73 | @gloggable 74 | def unbl_user(update: Update, context: CallbackContext) -> str: 75 | message = update.effective_message 76 | user = update.effective_user 77 | bot, args = context.bot, context.args 78 | user_id = extract_user(message, args) 79 | 80 | if not user_id: 81 | message.reply_text("I doubt that's a user.") 82 | return "" 83 | 84 | if user_id == bot.id: 85 | message.reply_text("I always notice myself.") 86 | return "" 87 | 88 | try: 89 | target_user = bot.get_chat(user_id) 90 | except BadRequest as excp: 91 | if excp.message == "User not found": 92 | message.reply_text("I can't seem to find this user.") 93 | return "" 94 | else: 95 | raise 96 | 97 | if sql.is_user_blacklisted(user_id): 98 | 99 | sql.unblacklist_user(user_id) 100 | message.reply_text("*notices user*") 101 | log_message = ( 102 | f"#UNBLACKLIST\n" 103 | f"Admin: {mention_html(user.id, html.escape(user.first_name))}\n" 104 | f"User: {mention_html(target_user.id, html.escape(target_user.first_name))}" 105 | ) 106 | 107 | return log_message 108 | 109 | else: 110 | message.reply_text("I am not ignoring them at all though!") 111 | return "" 112 | 113 | 114 | @run_async 115 | @dev_plus 116 | def bl_users(update: Update, context: CallbackContext): 117 | users = [] 118 | bot = context.bot 119 | for each_user in sql.BLACKLIST_USERS: 120 | user = bot.get_chat(each_user) 121 | reason = sql.get_reason(each_user) 122 | 123 | if reason: 124 | users.append( 125 | f"• {mention_html(user.id, html.escape(user.first_name))} :- {reason}" 126 | ) 127 | else: 128 | users.append(f"• {mention_html(user.id, html.escape(user.first_name))}") 129 | 130 | message = "Blacklisted Users\n" 131 | if not users: 132 | message += "Noone is being ignored as of yet." 133 | else: 134 | message += "\n".join(users) 135 | 136 | update.effective_message.reply_text(message, parse_mode=ParseMode.HTML) 137 | 138 | 139 | def __user_info__(user_id): 140 | is_blacklisted = sql.is_user_blacklisted(user_id) 141 | 142 | text = "Blacklisted: {}" 143 | if user_id in [777000, 1087968824]: 144 | return "" 145 | if user_id == dispatcher.bot.id: 146 | return "" 147 | if int(user_id) in DRAGONS + TIGERS + WOLVES: 148 | return "" 149 | if is_blacklisted: 150 | text = text.format("Yes") 151 | reason = sql.get_reason(user_id) 152 | if reason: 153 | text += f"\nReason: {reason}" 154 | else: 155 | text = text.format("No") 156 | 157 | return text 158 | 159 | 160 | BL_HANDLER = CommandHandler("ignore", bl_user) 161 | UNBL_HANDLER = CommandHandler("notice", unbl_user) 162 | BLUSERS_HANDLER = CommandHandler("ignoredlist", bl_users) 163 | 164 | dispatcher.add_handler(BL_HANDLER) 165 | dispatcher.add_handler(UNBL_HANDLER) 166 | dispatcher.add_handler(BLUSERS_HANDLER) 167 | 168 | __mod_name__ = "Blacklisting Users" 169 | __handlers__ = [BL_HANDLER, UNBL_HANDLER, BLUSERS_HANDLER] 170 | -------------------------------------------------------------------------------- /LaylaRobot/modules/cricketscore.py: -------------------------------------------------------------------------------- 1 | import urllib.request 2 | 3 | from bs4 import BeautifulSoup 4 | from telethon import events 5 | from LaylaRobot import telethn as tbot 6 | from telethon.tl import functions, types 7 | from telethon.tl.types import * 8 | 9 | 10 | async def is_register_admin(chat, user): 11 | if isinstance(chat, (types.InputPeerChannel, types.InputChannel)): 12 | return isinstance( 13 | ( 14 | await tbot(functions.channels.GetParticipantRequest(chat, user)) 15 | ).participant, 16 | (types.ChannelParticipantAdmin, types.ChannelParticipantCreator), 17 | ) 18 | if isinstance(chat, types.InputPeerUser): 19 | return True 20 | 21 | 22 | @tbot.on(events.NewMessage(pattern="/cs$")) 23 | async def _(event): 24 | if event.fwd_from: 25 | return 26 | if event.is_group: 27 | if not (await is_register_admin(event.input_chat, event.message.sender_id)): 28 | await event.reply("🚨 Need Admin Pewer.. You can't use this command.. But you can use in my pm") 29 | return 30 | 31 | score_page = "http://static.cricinfo.com/rss/livescores.xml" 32 | page = urllib.request.urlopen(score_page) 33 | soup = BeautifulSoup(page, "html.parser") 34 | result = soup.find_all("description") 35 | Sed = "" 36 | for match in result: 37 | Sed += match.get_text() + "\n\n" 38 | await event.reply( 39 | f"Match information gathered successful\n\n\n{Sed}", 40 | parse_mode="HTML", 41 | ) 42 | -------------------------------------------------------------------------------- /LaylaRobot/modules/currency_converter.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from LaylaRobot import CASH_API_KEY, dispatcher 3 | from telegram import Update, ParseMode 4 | from telegram.ext import CallbackContext, CommandHandler, run_async 5 | 6 | 7 | @run_async 8 | def convert(update: Update, context: CallbackContext): 9 | args = update.effective_message.text.split(" ") 10 | 11 | if len(args) == 4: 12 | try: 13 | orig_cur_amount = float(args[1]) 14 | 15 | except ValueError: 16 | update.effective_message.reply_text("Invalid Amount Of Currency") 17 | return 18 | 19 | orig_cur = args[2].upper() 20 | 21 | new_cur = args[3].upper() 22 | 23 | request_url = ( 24 | f"https://www.alphavantage.co/query" 25 | f"?function=CURRENCY_EXCHANGE_RATE" 26 | f"&from_currency={orig_cur}" 27 | f"&to_currency={new_cur}" 28 | f"&apikey={CASH_API_KEY}" 29 | ) 30 | response = requests.get(request_url).json() 31 | try: 32 | current_rate = float( 33 | response["Realtime Currency Exchange Rate"]["5. Exchange Rate"] 34 | ) 35 | except KeyError: 36 | update.effective_message.reply_text("Currency Not Supported.") 37 | return 38 | new_cur_amount = round(orig_cur_amount * current_rate, 5) 39 | update.effective_message.reply_text( 40 | f"{orig_cur_amount} {orig_cur} = {new_cur_amount} {new_cur}" 41 | ) 42 | 43 | elif len(args) == 1: 44 | update.effective_message.reply_text(__help__, parse_mode=ParseMode.MARKDOWN) 45 | 46 | else: 47 | update.effective_message.reply_text( 48 | f"*Invalid Args!!:* Required 3 But Passed {len(args) -1}", 49 | parse_mode=ParseMode.MARKDOWN, 50 | ) 51 | 52 | 53 | CONVERTER_HANDLER = CommandHandler("cash", convert) 54 | 55 | dispatcher.add_handler(CONVERTER_HANDLER) 56 | 57 | __command_list__ = ["cash"] 58 | __handlers__ = [CONVERTER_HANDLER] 59 | -------------------------------------------------------------------------------- /LaylaRobot/modules/dbcleanup.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | 3 | import LaylaRobot.modules.sql.global_bans_sql as gban_sql 4 | import LaylaRobot.modules.sql.users_sql as user_sql 5 | from LaylaRobot import DEV_USERS, OWNER_ID, dispatcher 6 | from LaylaRobot.modules.helper_funcs.chat_status import dev_plus 7 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update 8 | from telegram.error import BadRequest, Unauthorized 9 | from telegram.ext import ( 10 | CallbackContext, 11 | CallbackQueryHandler, 12 | CommandHandler, 13 | run_async, 14 | ) 15 | 16 | 17 | def get_invalid_chats(update: Update, context: CallbackContext, remove: bool = False): 18 | bot = context.bot 19 | chat_id = update.effective_chat.id 20 | chats = user_sql.get_all_chats() 21 | kicked_chats, progress = 0, 0 22 | chat_list = [] 23 | progress_message = None 24 | 25 | for chat in chats: 26 | 27 | if ((100 * chats.index(chat)) / len(chats)) > progress: 28 | progress_bar = f"{progress}% completed in getting invalid chats." 29 | if progress_message: 30 | try: 31 | bot.editMessageText( 32 | progress_bar, chat_id, progress_message.message_id 33 | ) 34 | except: 35 | pass 36 | else: 37 | progress_message = bot.sendMessage(chat_id, progress_bar) 38 | progress += 5 39 | 40 | cid = chat.chat_id 41 | sleep(0.1) 42 | try: 43 | bot.get_chat(cid, timeout=60) 44 | except (BadRequest, Unauthorized): 45 | kicked_chats += 1 46 | chat_list.append(cid) 47 | except: 48 | pass 49 | 50 | try: 51 | progress_message.delete() 52 | except: 53 | pass 54 | 55 | if not remove: 56 | return kicked_chats 57 | else: 58 | for muted_chat in chat_list: 59 | sleep(0.1) 60 | user_sql.rem_chat(muted_chat) 61 | return kicked_chats 62 | 63 | 64 | def get_invalid_gban(update: Update, context: CallbackContext, remove: bool = False): 65 | bot = context.bot 66 | banned = gban_sql.get_gban_list() 67 | ungbanned_users = 0 68 | ungban_list = [] 69 | 70 | for user in banned: 71 | user_id = user["user_id"] 72 | sleep(0.1) 73 | try: 74 | bot.get_chat(user_id) 75 | except BadRequest: 76 | ungbanned_users += 1 77 | ungban_list.append(user_id) 78 | except: 79 | pass 80 | 81 | if not remove: 82 | return ungbanned_users 83 | else: 84 | for user_id in ungban_list: 85 | sleep(0.1) 86 | gban_sql.ungban_user(user_id) 87 | return ungbanned_users 88 | 89 | 90 | @run_async 91 | @dev_plus 92 | def dbcleanup(update: Update, context: CallbackContext): 93 | msg = update.effective_message 94 | 95 | msg.reply_text("Getting invalid chat count ...") 96 | invalid_chat_count = get_invalid_chats(update, context) 97 | 98 | msg.reply_text("Getting invalid gbanned count ...") 99 | invalid_gban_count = get_invalid_gban(update, context) 100 | 101 | reply = f"Total invalid chats - {invalid_chat_count}\n" 102 | reply += f"Total invalid gbanned users - {invalid_gban_count}" 103 | 104 | buttons = [[InlineKeyboardButton("Cleanup DB", callback_data="db_cleanup")]] 105 | 106 | update.effective_message.reply_text( 107 | reply, reply_markup=InlineKeyboardMarkup(buttons) 108 | ) 109 | 110 | 111 | @run_async 112 | def callback_button(update: Update, context: CallbackContext): 113 | bot = context.bot 114 | query = update.callback_query 115 | message = query.message 116 | chat_id = update.effective_chat.id 117 | query_type = query.data 118 | 119 | admin_list = [OWNER_ID] + DEV_USERS 120 | 121 | bot.answer_callback_query(query.id) 122 | 123 | if query_type == "db_leave_chat": 124 | if query.from_user.id in admin_list: 125 | bot.editMessageText("Leaving chats ...", chat_id, message.message_id) 126 | chat_count = get_muted_chats(update, context, True) 127 | bot.sendMessage(chat_id, f"Left {chat_count} chats.") 128 | else: 129 | query.answer("You are not allowed to use this.") 130 | elif query_type == "db_cleanup": 131 | if query.from_user.id in admin_list: 132 | bot.editMessageText("Cleaning up DB ...", chat_id, message.message_id) 133 | invalid_chat_count = get_invalid_chats(update, context, True) 134 | invalid_gban_count = get_invalid_gban(update, context, True) 135 | reply = "Cleaned up {} chats and {} gbanned users from db.".format( 136 | invalid_chat_count, invalid_gban_count 137 | ) 138 | bot.sendMessage(chat_id, reply) 139 | else: 140 | query.answer("You are not allowed to use this.") 141 | 142 | 143 | DB_CLEANUP_HANDLER = CommandHandler("dbcleanup", dbcleanup) 144 | BUTTON_HANDLER = CallbackQueryHandler(callback_button, pattern="db_.*") 145 | 146 | dispatcher.add_handler(DB_CLEANUP_HANDLER) 147 | dispatcher.add_handler(BUTTON_HANDLER) 148 | 149 | __mod_name__ = "DB Cleanup" 150 | __handlers__ = [DB_CLEANUP_HANDLER, BUTTON_HANDLER] 151 | -------------------------------------------------------------------------------- /LaylaRobot/modules/debug.py: -------------------------------------------------------------------------------- 1 | import os 2 | import datetime 3 | 4 | from telethon import events 5 | from telegram import Update 6 | from telegram.ext import CallbackContext, CommandHandler, run_async 7 | 8 | from LaylaRobot import telethn, dispatcher 9 | from LaylaRobot.modules.helper_funcs.chat_status import dev_plus 10 | 11 | DEBUG_MODE = False 12 | 13 | 14 | @run_async 15 | @dev_plus 16 | def debug(update: Update, context: CallbackContext): 17 | global DEBUG_MODE 18 | args = update.effective_message.text.split(None, 1) 19 | message = update.effective_message 20 | print(DEBUG_MODE) 21 | if len(args) > 1: 22 | if args[1] in ("yes", "on"): 23 | DEBUG_MODE = True 24 | message.reply_text("Debug mode is now on.") 25 | elif args[1] in ("no", "off"): 26 | DEBUG_MODE = False 27 | message.reply_text("Debug mode is now off.") 28 | else: 29 | if DEBUG_MODE: 30 | message.reply_text("Debug mode is currently on.") 31 | else: 32 | message.reply_text("Debug mode is currently off.") 33 | 34 | 35 | @telethn.on(events.NewMessage(pattern="[/!].*")) 36 | async def i_do_nothing_yes(event): 37 | global DEBUG_MODE 38 | if DEBUG_MODE: 39 | print(f"-{event.from_id} ({event.chat_id}) : {event.text}") 40 | if os.path.exists("updates.txt"): 41 | with open("updates.txt", "r") as f: 42 | text = f.read() 43 | with open("updates.txt", "w+") as f: 44 | f.write(text + f"\n-{event.from_id} ({event.chat_id}) : {event.text}") 45 | else: 46 | with open("updates.txt", "w+") as f: 47 | f.write( 48 | f"- {event.from_id} ({event.chat_id}) : {event.text} | {datetime.datetime.now()}" 49 | ) 50 | 51 | 52 | support_chat = os.getenv("SUPPORT_CHAT") 53 | 54 | 55 | @run_async 56 | @dev_plus 57 | def logs(update: Update, context: CallbackContext): 58 | user = update.effective_user 59 | with open("log.txt", "rb") as f: 60 | context.bot.send_document(document=f, filename=f.name, chat_id=user.id) 61 | 62 | 63 | LOG_HANDLER = CommandHandler("logs", logs) 64 | dispatcher.add_handler(LOG_HANDLER) 65 | 66 | DEBUG_HANDLER = CommandHandler("debug", debug) 67 | dispatcher.add_handler(DEBUG_HANDLER) 68 | 69 | __mod_name__ = "Debug" 70 | __command_list__ = ["debug"] 71 | __handlers__ = [DEBUG_HANDLER] 72 | -------------------------------------------------------------------------------- /LaylaRobot/modules/dev.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | import sys 4 | 5 | from contextlib import suppress 6 | from time import sleep 7 | 8 | import LaylaRobot 9 | 10 | from LaylaRobot import dispatcher 11 | from LaylaRobot.modules.helper_funcs.chat_status import dev_plus 12 | from telegram import TelegramError, Update 13 | from telegram.error import Unauthorized 14 | from telegram.ext import CallbackContext, CommandHandler, run_async 15 | 16 | @run_async 17 | @dev_plus 18 | def allow_groups(update: Update, context: CallbackContext): 19 | args = context.args 20 | if not args: 21 | update.effective_message.reply_text(f"Current state: {LaylaRobot.ALLOW_CHATS}") 22 | return 23 | if args[0].lower() in ["off", "no"]: 24 | LaylaRobot.ALLOW_CHATS = True 25 | elif args[0].lower() in ["yes", "on"]: 26 | LaylaRobot.ALLOW_CHATS = False 27 | else: 28 | update.effective_message.reply_text("Format: /lockdown Yes/No or Off/On") 29 | return 30 | update.effective_message.reply_text("Done! Lockdown value toggled.") 31 | 32 | @run_async 33 | @dev_plus 34 | def leave(update: Update, context: CallbackContext): 35 | bot = context.bot 36 | args = context.args 37 | if args: 38 | chat_id = str(args[0]) 39 | try: 40 | bot.leave_chat(int(chat_id)) 41 | except TelegramError: 42 | update.effective_message.reply_text( 43 | "Beep boop, I could not leave that group(dunno why tho)." 44 | ) 45 | return 46 | with suppress(Unauthorized): 47 | update.effective_message.reply_text("Beep boop, I left that soup!.") 48 | else: 49 | update.effective_message.reply_text("Send a valid chat ID") 50 | 51 | 52 | @run_async 53 | @dev_plus 54 | def gitpull(update: Update, context: CallbackContext): 55 | sent_msg = update.effective_message.reply_text( 56 | "Pulling all changes from remote and then attempting to restart." 57 | ) 58 | subprocess.Popen("git pull", stdout=subprocess.PIPE, shell=True) 59 | 60 | sent_msg_text = sent_msg.text + "\n\nChanges pulled...I guess.. Restarting in " 61 | 62 | for i in reversed(range(5)): 63 | sent_msg.edit_text(sent_msg_text + str(i + 1)) 64 | sleep(1) 65 | 66 | sent_msg.edit_text("Restarted.") 67 | 68 | os.system("restart.bat") 69 | os.execv("start.bat", sys.argv) 70 | 71 | 72 | @run_async 73 | @dev_plus 74 | def restart(update: Update, context: CallbackContext): 75 | update.effective_message.reply_text( 76 | "Starting a new instance and shutting down this one" 77 | ) 78 | 79 | os.system("restart.bat") 80 | os.execv("start.bat", sys.argv) 81 | 82 | 83 | LEAVE_HANDLER = CommandHandler("leave", leave) 84 | GITPULL_HANDLER = CommandHandler("gitpull", gitpull) 85 | RESTART_HANDLER = CommandHandler("reboot", restart) 86 | ALLOWGROUPS_HANDLER = CommandHandler("lockdown", allow_groups) 87 | 88 | dispatcher.add_handler(ALLOWGROUPS_HANDLER) 89 | dispatcher.add_handler(LEAVE_HANDLER) 90 | dispatcher.add_handler(GITPULL_HANDLER) 91 | dispatcher.add_handler(RESTART_HANDLER) 92 | 93 | __mod_name__ = "Devs" 94 | __handlers__ = [LEAVE_HANDLER, GITPULL_HANDLER, RESTART_HANDLER, ALLOWGROUPS_HANDLER] 95 | -------------------------------------------------------------------------------- /LaylaRobot/modules/error_handler.py: -------------------------------------------------------------------------------- 1 | import traceback 2 | 3 | import requests 4 | import html 5 | import random 6 | import traceback 7 | import sys 8 | import pretty_errors 9 | import io 10 | from telegram import Update, InlineKeyboardMarkup, InlineKeyboardButton 11 | from telegram.ext import CallbackContext, CommandHandler 12 | from LaylaRobot import dispatcher, DEV_USERS, OWNER_ID 13 | 14 | pretty_errors.mono() 15 | 16 | 17 | class ErrorsDict(dict): 18 | "A custom dict to store errors and their count" 19 | 20 | def __init__(self, *args, **kwargs): 21 | self.raw = [] 22 | super().__init__(*args, **kwargs) 23 | 24 | def __contains__(self, error): 25 | self.raw.append(error) 26 | error.identifier = "".join(random.choices("ABCDEFGHIJKLMNOPQRSTUVWXYZ", k=5)) 27 | for e in self: 28 | if type(e) is type(error) and e.args == error.args: 29 | self[e] += 1 30 | return True 31 | self[error] = 0 32 | return False 33 | 34 | def __len__(self): 35 | return len(self.raw) 36 | 37 | 38 | errors = ErrorsDict() 39 | 40 | 41 | def error_callback(update: Update, context: CallbackContext): 42 | if not update: 43 | return 44 | if context.error in errors: 45 | return 46 | try: 47 | stringio = io.StringIO() 48 | pretty_errors.output_stderr = stringio 49 | output = pretty_errors.excepthook( 50 | type(context.error), context.error, context.error.__traceback__ 51 | ) 52 | pretty_errors.output_stderr = sys.stderr 53 | pretty_error = stringio.getvalue() 54 | stringio.close() 55 | except: 56 | pretty_error = "Failed to create pretty error." 57 | tb_list = traceback.format_exception( 58 | None, context.error, context.error.__traceback__ 59 | ) 60 | tb = "".join(tb_list) 61 | pretty_message = ( 62 | "{}\n" 63 | "-------------------------------------------------------------------------------\n" 64 | "An exception was raised while handling an update\n" 65 | "User: {}\n" 66 | "Chat: {} {}\n" 67 | "Callback data: {}\n" 68 | "Message: {}\n\n" 69 | "Full Traceback: {}" 70 | ).format( 71 | pretty_error, 72 | update.effective_user.id, 73 | update.effective_chat.title if update.effective_chat else "", 74 | update.effective_chat.id if update.effective_chat else "", 75 | update.callback_query.data if update.callback_query else "None", 76 | update.effective_message.text if update.effective_message else "No message", 77 | tb, 78 | ) 79 | key = requests.post( 80 | "https://nekobin.com/api/documents", json={"content": pretty_message} 81 | ).json() 82 | e = html.escape(f"{context.error}") 83 | if not key.get("result", {}).get("key"): 84 | with open("error.txt", "w+") as f: 85 | f.write(pretty_message) 86 | context.bot.send_document( 87 | OWNER_ID, 88 | open("error.txt", "rb"), 89 | caption=f"#{context.error.identifier}\nAn unknown error occured:\n{e}", 90 | parse_mode="html", 91 | ) 92 | return 93 | key = key.get("result").get("key") 94 | url = f"https://nekobin.com/{key}.py" 95 | context.bot.send_message( 96 | OWNER_ID, 97 | text=f"#{context.error.identifier}\nAn unknown error occured:\n{e}", 98 | reply_markup=InlineKeyboardMarkup( 99 | [[InlineKeyboardButton("Nekobin", url=url)]] 100 | ), 101 | parse_mode="html", 102 | ) 103 | 104 | 105 | def list_errors(update: Update, context: CallbackContext): 106 | if update.effective_user.id not in DEV_USERS: 107 | return 108 | e = { 109 | k: v for k, v in sorted(errors.items(), key=lambda item: item[1], reverse=True) 110 | } 111 | msg = "Errors List:\n" 112 | for x in e: 113 | msg += f"• {x}: {e[x]} #{x.identifier}\n" 114 | msg += f"{len(errors)} have occurred since startup." 115 | if len(msg) > 4096: 116 | with open("errors_msg.txt", "w+") as f: 117 | f.write(msg) 118 | context.bot.send_document( 119 | update.effective_chat.id, 120 | open("errors_msg.txt", "rb"), 121 | caption=f"Too many errors have occured..", 122 | parse_mode="html", 123 | ) 124 | return 125 | update.effective_message.reply_text(msg, parse_mode="html") 126 | 127 | 128 | dispatcher.add_error_handler(error_callback) 129 | dispatcher.add_handler(CommandHandler("errors", list_errors)) 130 | -------------------------------------------------------------------------------- /LaylaRobot/modules/eval.py: -------------------------------------------------------------------------------- 1 | import io 2 | import os 3 | 4 | # Common imports for eval 5 | import textwrap 6 | import traceback 7 | from contextlib import redirect_stdout 8 | 9 | from LaylaRobot import LOGGER, dispatcher 10 | from LaylaRobot.modules.helper_funcs.chat_status import dev_plus 11 | from telegram import ParseMode, Update 12 | from telegram.ext import CallbackContext, CommandHandler, run_async 13 | 14 | namespaces = {} 15 | 16 | 17 | def namespace_of(chat, update, bot): 18 | if chat not in namespaces: 19 | namespaces[chat] = { 20 | "__builtins__": globals()["__builtins__"], 21 | "bot": bot, 22 | "effective_message": update.effective_message, 23 | "effective_user": update.effective_user, 24 | "effective_chat": update.effective_chat, 25 | "update": update, 26 | } 27 | 28 | return namespaces[chat] 29 | 30 | 31 | def log_input(update): 32 | user = update.effective_user.id 33 | chat = update.effective_chat.id 34 | LOGGER.info(f"IN: {update.effective_message.text} (user={user}, chat={chat})") 35 | 36 | 37 | def send(msg, bot, update): 38 | if len(str(msg)) > 2000: 39 | with io.BytesIO(str.encode(msg)) as out_file: 40 | out_file.name = "output.txt" 41 | bot.send_document(chat_id=update.effective_chat.id, document=out_file) 42 | else: 43 | LOGGER.info(f"OUT: '{msg}'") 44 | bot.send_message( 45 | chat_id=update.effective_chat.id, 46 | text=f"`{msg}`", 47 | parse_mode=ParseMode.MARKDOWN, 48 | ) 49 | 50 | 51 | @dev_plus 52 | @run_async 53 | def evaluate(update: Update, context: CallbackContext): 54 | bot = context.bot 55 | send(do(eval, bot, update), bot, update) 56 | 57 | 58 | @dev_plus 59 | @run_async 60 | def execute(update: Update, context: CallbackContext): 61 | bot = context.bot 62 | send(do(exec, bot, update), bot, update) 63 | 64 | 65 | def cleanup_code(code): 66 | if code.startswith("```") and code.endswith("```"): 67 | return "\n".join(code.split("\n")[1:-1]) 68 | return code.strip("` \n") 69 | 70 | 71 | def do(func, bot, update): 72 | log_input(update) 73 | content = update.message.text.split(" ", 1)[-1] 74 | body = cleanup_code(content) 75 | env = namespace_of(update.message.chat_id, update, bot) 76 | 77 | os.chdir(os.getcwd()) 78 | with open( 79 | os.path.join(os.getcwd(), "LaylaRobot/modules/helper_funcs/temp.txt"), "w" 80 | ) as temp: 81 | temp.write(body) 82 | 83 | stdout = io.StringIO() 84 | 85 | to_compile = f'def func():\n{textwrap.indent(body, " ")}' 86 | 87 | try: 88 | exec(to_compile, env) 89 | except Exception as e: 90 | return f"{e.__class__.__name__}: {e}" 91 | 92 | func = env["func"] 93 | 94 | try: 95 | with redirect_stdout(stdout): 96 | func_return = func() 97 | except Exception as e: 98 | value = stdout.getvalue() 99 | return f"{value}{traceback.format_exc()}" 100 | else: 101 | value = stdout.getvalue() 102 | result = None 103 | if func_return is None: 104 | if value: 105 | result = f"{value}" 106 | else: 107 | try: 108 | result = f"{repr(eval(body, env))}" 109 | except: 110 | pass 111 | else: 112 | result = f"{value}{func_return}" 113 | if result: 114 | return result 115 | 116 | 117 | @dev_plus 118 | @run_async 119 | def clear(update: Update, context: CallbackContext): 120 | bot = context.bot 121 | log_input(update) 122 | global namespaces 123 | if update.message.chat_id in namespaces: 124 | del namespaces[update.message.chat_id] 125 | send("Cleared locals.", bot, update) 126 | 127 | 128 | EVAL_HANDLER = CommandHandler(("e", "ev", "eva", "eval"), evaluate) 129 | EXEC_HANDLER = CommandHandler(("x", "ex", "exe", "exec", "py"), execute) 130 | CLEAR_HANDLER = CommandHandler("clearlocals", clear) 131 | 132 | dispatcher.add_handler(EVAL_HANDLER) 133 | dispatcher.add_handler(EXEC_HANDLER) 134 | dispatcher.add_handler(CLEAR_HANDLER) 135 | 136 | __mod_name__ = "Eval Module" 137 | -------------------------------------------------------------------------------- /LaylaRobot/modules/fakeit.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import requests 4 | from faker import Faker 5 | from faker.providers import internet 6 | from telethon import events 7 | 8 | from LaylaRobot.pyrogramee.telethonbasics import is_admin 9 | from LaylaRobot import telethn as tbot 10 | 11 | @tbot.on(events.NewMessage(pattern="/fakegen$")) 12 | async def hi(event): 13 | if event.fwd_from: 14 | return 15 | if event.is_group: 16 | if not await is_admin(event, event.message.sender_id): 17 | await event.reply("`You Should Be Admin To Do This!`") 18 | return 19 | fake = Faker() 20 | print("FAKE DETAILS GENERATED\n") 21 | name = str(fake.name()) 22 | fake.add_provider(internet) 23 | address = str(fake.address()) 24 | ip = fake.ipv4_private() 25 | cc = fake.credit_card_full() 26 | email = fake.ascii_free_email() 27 | job = fake.job() 28 | android = fake.android_platform_token() 29 | pc = fake.chrome() 30 | await event.reply( 31 | f" Fake Information Generated\nName :-{name}\n\nAddress:-{address}\n\nIP ADDRESS:-{ip}\n\ncredit card:-{cc}\n\nEmail Id:-{email}\n\nJob:-{job}\n\nandroid user agent:-{android}\n\nPc user agent:-{pc}", 32 | parse_mode="HTML", 33 | ) 34 | 35 | 36 | @tbot.on(events.NewMessage(pattern="/picgen$")) 37 | async def _(event): 38 | if event.fwd_from: 39 | return 40 | if await is_admin(event, event.message.sender_id): 41 | url = "https://thispersondoesnotexist.com/image" 42 | response = requests.get(url) 43 | if response.status_code == 200: 44 | with open("FRIDAYOT.jpg", "wb") as f: 45 | f.write(response.content) 46 | 47 | captin = f"Fake Image powered by @AwesomeSupport." 48 | fole = "FRIDAYOT.jpg" 49 | await tbot.send_file(event.chat_id, fole, caption=captin) 50 | await event.delete() 51 | os.system("rm ./FRIDAYOT.jpg ") 52 | -------------------------------------------------------------------------------- /LaylaRobot/modules/games.py: -------------------------------------------------------------------------------- 1 | from telethon.tl.types import InputMediaDice 2 | 3 | from LaylaRobot.events import register 4 | 5 | 6 | @register(pattern="^/dice(?: |$)(.*)") 7 | async def _(event): 8 | if event.fwd_from: 9 | return 10 | input_str = event.pattern_match.group(1) 11 | r = await event.reply(file=InputMediaDice("")) 12 | input_int = int(input_str) 13 | if input_int > 6: 14 | await event.reply("hey nigga use number 1 to 6 only") 15 | 16 | else: 17 | try: 18 | required_number = input_int 19 | while r.media.value != required_number: 20 | await r.delete() 21 | r = await event.reply(file=InputMediaDice("")) 22 | except BaseException: 23 | pass 24 | 25 | 26 | @register(pattern="^/dart(?: |$)(.*)") 27 | async def _(event): 28 | if event.fwd_from: 29 | return 30 | input_str = event.pattern_match.group(1) 31 | r = await event.reply(file=InputMediaDice("🎯")) 32 | input_int = int(input_str) 33 | if input_int > 6: 34 | await event.reply("hey nigga use number 1 to 6 only") 35 | 36 | else: 37 | try: 38 | required_number = input_int 39 | while r.media.value != required_number: 40 | await r.delete() 41 | r = await event.reply(file=InputMediaDice("🎯")) 42 | except BaseException: 43 | pass 44 | 45 | 46 | @register(pattern="^/ball(?: |$)(.*)") 47 | async def _(event): 48 | if event.fwd_from: 49 | return 50 | input_str = event.pattern_match.group(1) 51 | r = await event.reply(file=InputMediaDice("🏀")) 52 | input_int = int(input_str) 53 | if input_int > 5: 54 | await event.reply("hey nigga use number 1 to 6 only") 55 | 56 | else: 57 | try: 58 | required_number = input_int 59 | while r.media.value != required_number: 60 | await r.delete() 61 | r = await event.reply(file=InputMediaDice("🏀")) 62 | except BaseException: 63 | pass 64 | 65 | 66 | 67 | __help__ = """ 68 | *Play Game With Emojis:* 69 | - /dice or /dice 1 to 6 any value 70 | - /ball or /ball 1 to 5 any value 71 | - /dart or /dart 1 to 6 any value 72 | Usage: hahaha just a magic. 73 | warning: you would be in trouble if you input any other value than mentioned. 74 | *Truth And Dare:* 75 | - /Truth : for random truth. 76 | - /dare : for random dare. 77 | """ 78 | 79 | __mod_name__ = "Game" 80 | -------------------------------------------------------------------------------- /LaylaRobot/modules/get_common_chats.py: -------------------------------------------------------------------------------- 1 | import os 2 | from time import sleep 3 | 4 | from LaylaRobot import OWNER_ID, dispatcher 5 | from LaylaRobot.modules.helper_funcs.extraction import extract_user 6 | from LaylaRobot.modules.sql.users_sql import get_user_com_chats 7 | from telegram import Update 8 | from telegram.error import BadRequest, RetryAfter, Unauthorized 9 | from telegram.ext import CallbackContext, CommandHandler, Filters 10 | from telegram.ext.dispatcher import run_async 11 | 12 | 13 | @run_async 14 | def get_user_common_chats(update: Update, context: CallbackContext): 15 | bot, args = context.bot, context.args 16 | msg = update.effective_message 17 | user = extract_user(msg, args) 18 | if not user: 19 | msg.reply_text("I share no common chats with the void.") 20 | return 21 | common_list = get_user_com_chats(user) 22 | if not common_list: 23 | msg.reply_text("No common chats with this user!") 24 | return 25 | name = bot.get_chat(user).first_name 26 | text = f"Common chats with {name}\n" 27 | for chat in common_list: 28 | try: 29 | chat_name = bot.get_chat(chat).title 30 | sleep(0.3) 31 | text += f"• {chat_name}\n" 32 | except BadRequest: 33 | pass 34 | except Unauthorized: 35 | pass 36 | except RetryAfter as e: 37 | sleep(e.retry_after) 38 | 39 | if len(text) < 4096: 40 | msg.reply_text(text, parse_mode="HTML") 41 | else: 42 | with open("common_chats.txt", "w") as f: 43 | f.write(text) 44 | with open("common_chats.txt", "rb") as f: 45 | msg.reply_document(f) 46 | os.remove("common_chats.txt") 47 | 48 | 49 | COMMON_CHATS_HANDLER = CommandHandler( 50 | "getchats", get_user_common_chats, filters=Filters.user(OWNER_ID) 51 | ) 52 | 53 | dispatcher.add_handler(COMMON_CHATS_HANDLER) 54 | -------------------------------------------------------------------------------- /LaylaRobot/modules/gettime.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from typing import List 3 | 4 | import requests 5 | from LaylaRobot import TIME_API_KEY, dispatcher 6 | from LaylaRobot.modules.disable import DisableAbleCommandHandler 7 | from telegram import ParseMode, Update 8 | from telegram.ext import CallbackContext, run_async 9 | 10 | 11 | def generate_time(to_find: str, findtype: List[str]) -> str: 12 | data = requests.get( 13 | f"https://api.timezonedb.com/v2.1/list-time-zone" 14 | f"?key={TIME_API_KEY}" 15 | f"&format=json" 16 | f"&fields=countryCode,countryName,zoneName,gmtOffset,timestamp,dst" 17 | ).json() 18 | 19 | for zone in data["zones"]: 20 | for eachtype in findtype: 21 | if to_find in zone[eachtype].lower(): 22 | country_name = zone["countryName"] 23 | country_zone = zone["zoneName"] 24 | country_code = zone["countryCode"] 25 | 26 | if zone["dst"] == 1: 27 | daylight_saving = "Yes" 28 | else: 29 | daylight_saving = "No" 30 | 31 | date_fmt = r"%d-%m-%Y" 32 | time_fmt = r"%H:%M:%S" 33 | day_fmt = r"%A" 34 | gmt_offset = zone["gmtOffset"] 35 | timestamp = datetime.datetime.now( 36 | datetime.timezone.utc 37 | ) + datetime.timedelta(seconds=gmt_offset) 38 | current_date = timestamp.strftime(date_fmt) 39 | current_time = timestamp.strftime(time_fmt) 40 | current_day = timestamp.strftime(day_fmt) 41 | 42 | break 43 | 44 | try: 45 | result = ( 46 | f"Country: {country_name}\n" 47 | f"Zone Name: {country_zone}\n" 48 | f"Country Code: {country_code}\n" 49 | f"Daylight saving: {daylight_saving}\n" 50 | f"Day: {current_day}\n" 51 | f"Current Time: {current_time}\n" 52 | f"Current Date: {current_date}\n" 53 | 'Timezones: List here' 54 | ) 55 | except: 56 | result = None 57 | 58 | return result 59 | 60 | 61 | @run_async 62 | def gettime(update: Update, context: CallbackContext): 63 | message = update.effective_message 64 | 65 | try: 66 | query = message.text.strip().split(" ", 1)[1] 67 | except: 68 | message.reply_text("Provide a country name/abbreviation/timezone to find.") 69 | return 70 | send_message = message.reply_text( 71 | f"Finding timezone info for {query}", parse_mode=ParseMode.HTML 72 | ) 73 | 74 | query_timezone = query.lower() 75 | if len(query_timezone) == 2: 76 | result = generate_time(query_timezone, ["countryCode"]) 77 | else: 78 | result = generate_time(query_timezone, ["zoneName", "countryName"]) 79 | 80 | if not result: 81 | send_message.edit_text( 82 | f"Timezone info not available for {query}\n" 83 | 'All Timezones: List here', 84 | parse_mode=ParseMode.HTML, 85 | disable_web_page_preview=True, 86 | ) 87 | return 88 | 89 | send_message.edit_text( 90 | result, parse_mode=ParseMode.HTML, disable_web_page_preview=True 91 | ) 92 | 93 | 94 | TIME_HANDLER = DisableAbleCommandHandler("time", gettime) 95 | 96 | dispatcher.add_handler(TIME_HANDLER) 97 | 98 | __mod_name__ = "TIME" 99 | __command_list__ = ["time"] 100 | __handlers__ = [TIME_HANDLER] 101 | -------------------------------------------------------------------------------- /LaylaRobot/modules/gtranslator.py: -------------------------------------------------------------------------------- 1 | from emoji import UNICODE_EMOJI 2 | from google_trans_new import LANGUAGES, google_translator 3 | from telegram import ParseMode, Update 4 | from telegram.ext import CallbackContext, run_async 5 | 6 | from LaylaRobot import dispatcher 7 | from LaylaRobot.modules.disable import DisableAbleCommandHandler 8 | 9 | 10 | @run_async 11 | def totranslate(update: Update, context: CallbackContext): 12 | message = update.effective_message 13 | problem_lang_code = [] 14 | for key in LANGUAGES: 15 | if "-" in key: 16 | problem_lang_code.append(key) 17 | 18 | try: 19 | if message.reply_to_message: 20 | args = update.effective_message.text.split(None, 1) 21 | if message.reply_to_message.text: 22 | text = message.reply_to_message.text 23 | elif message.reply_to_message.caption: 24 | text = message.reply_to_message.caption 25 | 26 | try: 27 | source_lang = args[1].split(None, 1)[0] 28 | except (IndexError, AttributeError): 29 | source_lang = "en" 30 | 31 | else: 32 | args = update.effective_message.text.split(None, 2) 33 | text = args[2] 34 | source_lang = args[1] 35 | 36 | if source_lang.count("-") == 2: 37 | for lang in problem_lang_code: 38 | if lang in source_lang: 39 | if source_lang.startswith(lang): 40 | dest_lang = source_lang.rsplit("-", 1)[1] 41 | source_lang = source_lang.rsplit("-", 1)[0] 42 | else: 43 | dest_lang = source_lang.split("-", 1)[1] 44 | source_lang = source_lang.split("-", 1)[0] 45 | elif source_lang.count("-") == 1: 46 | for lang in problem_lang_code: 47 | if lang in source_lang: 48 | dest_lang = source_lang 49 | source_lang = None 50 | break 51 | if dest_lang is None: 52 | dest_lang = source_lang.split("-")[1] 53 | source_lang = source_lang.split("-")[0] 54 | else: 55 | dest_lang = source_lang 56 | source_lang = None 57 | 58 | exclude_list = UNICODE_EMOJI.keys() 59 | for emoji in exclude_list: 60 | if emoji in text: 61 | text = text.replace(emoji, "") 62 | 63 | trl = google_translator() 64 | if source_lang is None: 65 | detection = trl.detect(text) 66 | trans_str = trl.translate(text, lang_tgt=dest_lang) 67 | return message.reply_text( 68 | f"Translated from `{detection[0]}` to `{dest_lang}`:\n`{trans_str}`", 69 | parse_mode=ParseMode.MARKDOWN, 70 | ) 71 | else: 72 | trans_str = trl.translate(text, lang_tgt=dest_lang, lang_src=source_lang) 73 | message.reply_text( 74 | f"Translated from `{source_lang}` to `{dest_lang}`:\n`{trans_str}`", 75 | parse_mode=ParseMode.MARKDOWN, 76 | ) 77 | 78 | except IndexError: 79 | update.effective_message.reply_text( 80 | "Reply to messages or write messages from other languages ​​for translating into the intended language\n\n" 81 | "Example: `/tr en-ml` to translate from English to Malayalam\n" 82 | "Or use: `/tr ml` for automatic detection and translating it into Malayalam.\n" 83 | "See [List of Language Codes](t.me/OnePunchSupport/12823) for a list of language codes.", 84 | parse_mode="markdown", 85 | disable_web_page_preview=True, 86 | ) 87 | except ValueError: 88 | update.effective_message.reply_text("The intended language is not found!") 89 | else: 90 | return 91 | 92 | 93 | __help__ = """ 94 | ❍ /tr or /tl (language code) as reply to a long message 95 | *Example:* 96 | ❍ /tr en*:* translates something to english 97 | ❍ /tr hi-en*:* translates hindi to english 98 | 99 | *Language Codes* 100 | `af,am,ar,az,be,bg,bn,bs,ca,ceb,co,cs,cy,da,de,el,en,eo,es, 101 | et,eu,fa,fi,fr,fy,ga,gd,gl,gu,ha,haw,hi,hmn,hr,ht,hu,hy, 102 | id,ig,is,it,iw,ja,jw,ka,kk,km,kn,ko,ku,ky,la,lb,lo,lt,lv,mg,mi,mk, 103 | ml,mn,mr,ms,mt,my,ne,nl,no,ny,pa,pl,ps,pt,ro,ru,sd,si,sk,sl, 104 | sm,sn,so,sq,sr,st,su,sv,sw,ta,te,tg,th,tl,tr,uk,ur,uz, 105 | vi,xh,yi,yo,zh,zh_CN,zh_TW,zu` 106 | """ 107 | 108 | TRANSLATE_HANDLER = DisableAbleCommandHandler(["tr", "tl"], totranslate) 109 | 110 | dispatcher.add_handler(TRANSLATE_HANDLER) 111 | 112 | __mod_name__ = "G-Trans" 113 | __command_list__ = ["tr", "tl"] 114 | __handlers__ = [TRANSLATE_HANDLER] 115 | -------------------------------------------------------------------------------- /LaylaRobot/modules/helper_funcs/__init__.py: -------------------------------------------------------------------------------- 1 | """Helpers, also known as Utilities.""" 2 | -------------------------------------------------------------------------------- /LaylaRobot/modules/helper_funcs/alternate.py: -------------------------------------------------------------------------------- 1 | from telegram.error import BadRequest 2 | from functools import wraps 3 | from telegram import ChatAction 4 | 5 | 6 | def send_message(message, text, *args, **kwargs): 7 | try: 8 | return message.reply_text(text, *args, **kwargs) 9 | except BadRequest as err: 10 | if str(err) == "Reply message not found": 11 | return message.reply_text(text, quote=False, *args, **kwargs) 12 | 13 | 14 | def typing_action(func): 15 | """Sends typing action while processing func command.""" 16 | 17 | @wraps(func) 18 | def command_func(update, context, *args, **kwargs): 19 | context.bot.send_chat_action( 20 | chat_id=update.effective_chat.id, action=ChatAction.TYPING 21 | ) 22 | return func(update, context, *args, **kwargs) 23 | 24 | return command_func 25 | -------------------------------------------------------------------------------- /LaylaRobot/modules/helper_funcs/filters.py: -------------------------------------------------------------------------------- 1 | from LaylaRobot import DEV_USERS, DRAGONS, DEMONS 2 | from telegram import Message 3 | from telegram.ext import BaseFilter 4 | 5 | 6 | class CustomFilters(object): 7 | class _Supporters(BaseFilter): 8 | def filter(self, message: Message): 9 | return bool(message.from_user and message.from_user.id in DEMONS) 10 | 11 | support_filter = _Supporters() 12 | 13 | class _Sudoers(BaseFilter): 14 | def filter(self, message: Message): 15 | return bool(message.from_user and message.from_user.id in DRAGONS) 16 | 17 | sudo_filter = _Sudoers() 18 | 19 | class _Developers(BaseFilter): 20 | def filter(self, message: Message): 21 | return bool(message.from_user and message.from_user.id in DEV_USERS) 22 | 23 | dev_filter = _Developers() 24 | 25 | class _MimeType(BaseFilter): 26 | def __init__(self, mimetype): 27 | self.mime_type = mimetype 28 | self.name = "CustomFilters.mime_type({})".format(self.mime_type) 29 | 30 | def filter(self, message: Message): 31 | return bool( 32 | message.document and message.document.mime_type == self.mime_type 33 | ) 34 | 35 | mime_type = _MimeType 36 | 37 | class _HasText(BaseFilter): 38 | def filter(self, message: Message): 39 | return bool( 40 | message.text 41 | or message.sticker 42 | or message.photo 43 | or message.document 44 | or message.video 45 | ) 46 | 47 | has_text = _HasText() 48 | -------------------------------------------------------------------------------- /LaylaRobot/modules/helper_funcs/handlers.py: -------------------------------------------------------------------------------- 1 | import LaylaRobot.modules.sql.blacklistusers_sql as sql 2 | from LaylaRobot import ALLOW_EXCL 3 | from LaylaRobot import DEV_USERS, DRAGONS, DEMONS, TIGERS, WOLVES 4 | 5 | from telegram import Update 6 | from telegram.ext import CommandHandler, MessageHandler, RegexHandler, Filters 7 | from pyrate_limiter import ( 8 | BucketFullException, 9 | Duration, 10 | RequestRate, 11 | Limiter, 12 | MemoryListBucket, 13 | ) 14 | 15 | if ALLOW_EXCL: 16 | CMD_STARTERS = ("/", "!") 17 | else: 18 | CMD_STARTERS = ("/",) 19 | 20 | 21 | class AntiSpam: 22 | def __init__(self): 23 | self.whitelist = ( 24 | (DEV_USERS or []) 25 | + (DRAGONS or []) 26 | + (WOLVES or []) 27 | + (DEMONS or []) 28 | + (TIGERS or []) 29 | ) 30 | # Values are HIGHLY experimental, its recommended you pay attention to our commits as we will be adjusting the values over time with what suits best. 31 | Duration.CUSTOM = 15 # Custom duration, 15 seconds 32 | self.sec_limit = RequestRate(6, Duration.CUSTOM) # 6 / Per 15 Seconds 33 | self.min_limit = RequestRate(20, Duration.MINUTE) # 20 / Per minute 34 | self.hour_limit = RequestRate(100, Duration.HOUR) # 100 / Per hour 35 | self.daily_limit = RequestRate(1000, Duration.DAY) # 1000 / Per day 36 | self.limiter = Limiter( 37 | self.sec_limit, 38 | self.min_limit, 39 | self.hour_limit, 40 | self.daily_limit, 41 | bucket_class=MemoryListBucket, 42 | ) 43 | 44 | def check_user(self, user): 45 | """ 46 | Return True if user is to be ignored else False 47 | """ 48 | if user in self.whitelist: 49 | return False 50 | try: 51 | self.limiter.try_acquire(user) 52 | return False 53 | except BucketFullException: 54 | return True 55 | 56 | 57 | SpamChecker = AntiSpam() 58 | MessageHandlerChecker = AntiSpam() 59 | 60 | 61 | class CustomCommandHandler(CommandHandler): 62 | def __init__(self, command, callback, admin_ok=False, allow_edit=False, **kwargs): 63 | super().__init__(command, callback, **kwargs) 64 | 65 | if allow_edit is False: 66 | self.filters &= ~( 67 | Filters.update.edited_message | Filters.update.edited_channel_post 68 | ) 69 | 70 | def check_update(self, update): 71 | if isinstance(update, Update) and update.effective_message: 72 | message = update.effective_message 73 | 74 | try: 75 | user_id = update.effective_user.id 76 | except: 77 | user_id = None 78 | 79 | if user_id: 80 | if sql.is_user_blacklisted(user_id): 81 | return False 82 | 83 | if message.text and len(message.text) > 1: 84 | fst_word = message.text.split(None, 1)[0] 85 | if len(fst_word) > 1 and any( 86 | fst_word.startswith(start) for start in CMD_STARTERS 87 | ): 88 | 89 | args = message.text.split()[1:] 90 | command = fst_word[1:].split("@") 91 | command.append(message.bot.username) 92 | if user_id == 1087968824: 93 | user_id = update.effective_chat.id 94 | if not ( 95 | command[0].lower() in self.command 96 | and command[1].lower() == message.bot.username.lower() 97 | ): 98 | return None 99 | if SpamChecker.check_user(user_id): 100 | return None 101 | filter_result = self.filters(update) 102 | if filter_result: 103 | return args, filter_result 104 | else: 105 | return False 106 | 107 | def handle_update(self, update, dispatcher, check_result, context=None): 108 | if context: 109 | self.collect_additional_context(context, update, dispatcher, check_result) 110 | return self.callback(update, context) 111 | else: 112 | optional_args = self.collect_optional_args(dispatcher, update, check_result) 113 | return self.callback(dispatcher.bot, update, **optional_args) 114 | 115 | def collect_additional_context(self, context, update, dispatcher, check_result): 116 | if isinstance(check_result, bool): 117 | context.args = update.effective_message.text.split()[1:] 118 | else: 119 | context.args = check_result[0] 120 | if isinstance(check_result[1], dict): 121 | context.update(check_result[1]) 122 | 123 | 124 | class CustomRegexHandler(RegexHandler): 125 | def __init__(self, pattern, callback, friendly="", **kwargs): 126 | super().__init__(pattern, callback, **kwargs) 127 | 128 | 129 | class CustomMessageHandler(MessageHandler): 130 | def __init__(self, filters, callback, friendly="", allow_edit=False, **kwargs): 131 | super().__init__(filters, callback, **kwargs) 132 | if allow_edit is False: 133 | self.filters &= ~( 134 | Filters.update.edited_message | Filters.update.edited_channel_post 135 | ) 136 | 137 | def check_update(self, update): 138 | if isinstance(update, Update) and update.effective_message: 139 | return self.filters(update) 140 | -------------------------------------------------------------------------------- /LaylaRobot/modules/helper_funcs/misc.py: -------------------------------------------------------------------------------- 1 | from math import ceil 2 | from typing import Dict, List 3 | 4 | from LaylaRobot import NO_LOAD 5 | from telegram import MAX_MESSAGE_LENGTH, Bot, InlineKeyboardButton, ParseMode 6 | from telegram.error import TelegramError 7 | 8 | 9 | class EqInlineKeyboardButton(InlineKeyboardButton): 10 | def __eq__(self, other): 11 | return self.text == other.text 12 | 13 | def __lt__(self, other): 14 | return self.text < other.text 15 | 16 | def __gt__(self, other): 17 | return self.text > other.text 18 | 19 | 20 | def split_message(msg: str) -> List[str]: 21 | if len(msg) < MAX_MESSAGE_LENGTH: 22 | return [msg] 23 | 24 | lines = msg.splitlines(True) 25 | small_msg = "" 26 | result = [] 27 | for line in lines: 28 | if len(small_msg) + len(line) < MAX_MESSAGE_LENGTH: 29 | small_msg += line 30 | else: 31 | result.append(small_msg) 32 | small_msg = line 33 | else: 34 | # Else statement at the end of the for loop, so append the leftover string. 35 | result.append(small_msg) 36 | 37 | return result 38 | 39 | 40 | def paginate_modules(page_n: int, module_dict: Dict, prefix, chat=None) -> List: 41 | if not chat: 42 | modules = sorted( 43 | [EqInlineKeyboardButton(x.__mod_name__, 44 | callback_data="{}_module({})".format(prefix, x.__mod_name__.lower())) for x 45 | in module_dict.values()]) 46 | else: 47 | modules = sorted( 48 | [EqInlineKeyboardButton(x.__mod_name__, 49 | callback_data="{}_module({},{})".format(prefix, chat, x.__mod_name__.lower())) for x 50 | in module_dict.values()]) 51 | 52 | pairs = [ 53 | modules[i * 3:(i + 1) * 3] for i in range((len(modules) + 3 - 1) // 3) 54 | ] 55 | 56 | round_num = len(modules) / 3 57 | calc = len(modules) - round(round_num) 58 | if calc == 1: 59 | pairs.append((modules[-1], )) 60 | elif calc == 2: 61 | pairs.append((modules[-1], )) 62 | 63 | max_num_pages = ceil(len(pairs) / 10) 64 | modulo_page = page_n % max_num_pages 65 | 66 | # can only have a certain amount of buttons side by side 67 | if len(pairs) > 8: 68 | pairs = pairs[modulo_page * 8:8 * (modulo_page + 1)] + [ 69 | (EqInlineKeyboardButton("⬅️", callback_data="{}_prev({})".format(prefix, modulo_page)), 70 | EqInlineKeyboardButton("Back", callback_data="layla_back"), 71 | EqInlineKeyboardButton("➡️", callback_data="{}_next({})".format(prefix, modulo_page)))] 72 | 73 | else: 74 | pairs += [[EqInlineKeyboardButton("Back", callback_data="layla_back")]] 75 | 76 | return pairs 77 | 78 | 79 | def send_to_list( 80 | bot: Bot, send_to: list, message: str, markdown=False, html=False 81 | ) -> None: 82 | if html and markdown: 83 | raise Exception("Can only send with either markdown or HTML!") 84 | for user_id in set(send_to): 85 | try: 86 | if markdown: 87 | bot.send_message(user_id, message, parse_mode=ParseMode.MARKDOWN) 88 | elif html: 89 | bot.send_message(user_id, message, parse_mode=ParseMode.HTML) 90 | else: 91 | bot.send_message(user_id, message) 92 | except TelegramError: 93 | pass # ignore users who fail 94 | 95 | 96 | def build_keyboard(buttons): 97 | keyb = [] 98 | for btn in buttons: 99 | if btn.same_line and keyb: 100 | keyb[-1].append(InlineKeyboardButton(btn.name, url=btn.url)) 101 | else: 102 | keyb.append([InlineKeyboardButton(btn.name, url=btn.url)]) 103 | 104 | return keyb 105 | 106 | 107 | def revert_buttons(buttons): 108 | res = "" 109 | for btn in buttons: 110 | if btn.same_line: 111 | res += "\n[{}](buttonurl://{}:same)".format(btn.name, btn.url) 112 | else: 113 | res += "\n[{}](buttonurl://{})".format(btn.name, btn.url) 114 | 115 | return res 116 | 117 | 118 | def build_keyboard_parser(bot, chat_id, buttons): 119 | keyb = [] 120 | for btn in buttons: 121 | if btn.url == "{rules}": 122 | btn.url = "http://t.me/{}?start={}".format(bot.username, chat_id) 123 | if btn.same_line and keyb: 124 | keyb[-1].append(InlineKeyboardButton(btn.name, url=btn.url)) 125 | else: 126 | keyb.append([InlineKeyboardButton(btn.name, url=btn.url)]) 127 | 128 | return keyb 129 | 130 | 131 | def is_module_loaded(name): 132 | return name not in NO_LOAD 133 | -------------------------------------------------------------------------------- /LaylaRobot/modules/helper_funcs/regex_helper.py: -------------------------------------------------------------------------------- 1 | import regex 2 | 3 | 4 | def regex_searcher(regex_string, string): 5 | try: 6 | search = regex.search(regex_string, string, timeout=6) 7 | except TimeoutError: 8 | return False 9 | except Exception: 10 | return False 11 | return search 12 | 13 | 14 | def infinite_loop_check(regex_string): 15 | loop_matches = [ 16 | r"\((.{1,}[\+\*]){1,}\)[\+\*].", 17 | r"[\(\[].{1,}\{\d(,)?\}[\)\]]\{\d(,)?\}", 18 | r"\(.{1,}\)\{.{1,}(,)?\}\(.*\)(\+|\* |\{.*\})", 19 | ] 20 | for match in loop_matches: 21 | match_1 = regex.search(match, regex_string) 22 | if match_1: 23 | return True 24 | return False 25 | -------------------------------------------------------------------------------- /LaylaRobot/modules/helper_funcs/telethn/__init__.py: -------------------------------------------------------------------------------- 1 | from LaylaRobot import DEV_USERS, DRAGONS, DEMONS, TIGERS, WOLVES, telethn 2 | 3 | IMMUNE_USERS = DRAGONS + WOLVES + DEMONS + TIGERS + DEV_USERS 4 | 5 | IMMUNE_USERS = ( 6 | list(DRAGONS) + list(WOLVES) + list(DEMONS) + list(TIGERS) + list(DEV_USERS) 7 | ) 8 | -------------------------------------------------------------------------------- /LaylaRobot/modules/helper_funcs/telethn/chatstatus.py: -------------------------------------------------------------------------------- 1 | from LaylaRobot.modules.helper_funcs.telethn import IMMUNE_USERS, telethn 2 | from LaylaRobot import DRAGONS 3 | from telethon.tl.types import ChannelParticipantsAdmins 4 | 5 | 6 | async def user_is_ban_protected(user_id: int, message): 7 | status = False 8 | if message.is_private or user_id in (IMMUNE_USERS): 9 | return True 10 | 11 | async for user in telethn.iter_participants( 12 | message.chat_id, filter=ChannelParticipantsAdmins 13 | ): 14 | if user_id == user.id: 15 | status = True 16 | break 17 | return status 18 | 19 | 20 | async def user_is_admin(user_id: int, message): 21 | status = False 22 | if message.is_private: 23 | return True 24 | 25 | async for user in telethn.iter_participants( 26 | message.chat_id, filter=ChannelParticipantsAdmins 27 | ): 28 | if user_id == user.id or user_id in DRAGONS: 29 | status = True 30 | break 31 | return status 32 | 33 | 34 | async def is_user_admin(user_id: int, chat_id): 35 | status = False 36 | async for user in telethn.iter_participants( 37 | chat_id, filter=ChannelParticipantsAdmins 38 | ): 39 | if user_id == user.id or user_id in DRAGONS: 40 | status = True 41 | break 42 | return status 43 | 44 | 45 | async def yone_is_admin(chat_id: int): 46 | status = False 47 | yone = await telethn.get_me() 48 | async for user in telethn.iter_participants( 49 | chat_id, filter=ChannelParticipantsAdmins 50 | ): 51 | if yone.id == user.id: 52 | status = True 53 | break 54 | return status 55 | 56 | 57 | async def is_user_in_chat(chat_id: int, user_id: int): 58 | status = False 59 | async for user in telethn.iter_participants(chat_id): 60 | if user_id == user.id: 61 | status = True 62 | break 63 | return status 64 | 65 | 66 | async def can_change_info(message): 67 | status = False 68 | if message.chat.admin_rights: 69 | status = message.chat.admin_rights.change_info 70 | return status 71 | 72 | 73 | async def can_ban_users(message): 74 | status = False 75 | if message.chat.admin_rights: 76 | status = message.chat.admin_rights.ban_users 77 | return status 78 | 79 | 80 | async def can_pin_messages(message): 81 | status = False 82 | if message.chat.admin_rights: 83 | status = message.chat.admin_rights.pin_messages 84 | return status 85 | 86 | 87 | async def can_invite_users(message): 88 | status = False 89 | if message.chat.admin_rights: 90 | status = message.chat.admin_rights.invite_users 91 | return status 92 | 93 | 94 | async def can_add_admins(message): 95 | status = False 96 | if message.chat.admin_rights: 97 | status = message.chat.admin_rights.add_admins 98 | return status 99 | 100 | 101 | async def can_delete_messages(message): 102 | 103 | if message.is_private: 104 | return True 105 | elif message.chat.admin_rights: 106 | status = message.chat.admin_rights.delete_messages 107 | return status 108 | else: 109 | return False 110 | -------------------------------------------------------------------------------- /LaylaRobot/modules/math.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | import pynewtonmath as newton 4 | from LaylaRobot import dispatcher 5 | from LaylaRobot.modules.disable import DisableAbleCommandHandler 6 | from telegram import Update 7 | from telegram.ext import CallbackContext, run_async 8 | 9 | 10 | @run_async 11 | def simplify(update: Update, context: CallbackContext): 12 | args = context.args 13 | message = update.effective_message 14 | message.reply_text(newton.simplify("{}".format(args[0]))) 15 | 16 | 17 | @run_async 18 | def factor(update: Update, context: CallbackContext): 19 | args = context.args 20 | message = update.effective_message 21 | message.reply_text(newton.factor("{}".format(args[0]))) 22 | 23 | 24 | @run_async 25 | def derive(update: Update, context: CallbackContext): 26 | args = context.args 27 | message = update.effective_message 28 | message.reply_text(newton.derive("{}".format(args[0]))) 29 | 30 | 31 | @run_async 32 | def integrate(update: Update, context: CallbackContext): 33 | args = context.args 34 | message = update.effective_message 35 | message.reply_text(newton.integrate("{}".format(args[0]))) 36 | 37 | 38 | @run_async 39 | def zeroes(update: Update, context: CallbackContext): 40 | args = context.args 41 | message = update.effective_message 42 | message.reply_text(newton.zeroes("{}".format(args[0]))) 43 | 44 | 45 | @run_async 46 | def tangent(update: Update, context: CallbackContext): 47 | args = context.args 48 | message = update.effective_message 49 | message.reply_text(newton.tangent("{}".format(args[0]))) 50 | 51 | 52 | @run_async 53 | def area(update: Update, context: CallbackContext): 54 | args = context.args 55 | message = update.effective_message 56 | message.reply_text(newton.area("{}".format(args[0]))) 57 | 58 | 59 | @run_async 60 | def cos(update: Update, context: CallbackContext): 61 | args = context.args 62 | message = update.effective_message 63 | message.reply_text(math.cos(int(args[0]))) 64 | 65 | 66 | @run_async 67 | def sin(update: Update, context: CallbackContext): 68 | args = context.args 69 | message = update.effective_message 70 | message.reply_text(math.sin(int(args[0]))) 71 | 72 | 73 | @run_async 74 | def tan(update: Update, context: CallbackContext): 75 | args = context.args 76 | message = update.effective_message 77 | message.reply_text(math.tan(int(args[0]))) 78 | 79 | 80 | @run_async 81 | def arccos(update: Update, context: CallbackContext): 82 | args = context.args 83 | message = update.effective_message 84 | message.reply_text(math.acos(int(args[0]))) 85 | 86 | 87 | @run_async 88 | def arcsin(update: Update, context: CallbackContext): 89 | args = context.args 90 | message = update.effective_message 91 | message.reply_text(math.asin(int(args[0]))) 92 | 93 | 94 | @run_async 95 | def arctan(update: Update, context: CallbackContext): 96 | args = context.args 97 | message = update.effective_message 98 | message.reply_text(math.atan(int(args[0]))) 99 | 100 | 101 | @run_async 102 | def abs(update: Update, context: CallbackContext): 103 | args = context.args 104 | message = update.effective_message 105 | message.reply_text(math.fabs(int(args[0]))) 106 | 107 | 108 | @run_async 109 | def log(update: Update, context: CallbackContext): 110 | args = context.args 111 | message = update.effective_message 112 | message.reply_text(math.log(int(args[0]))) 113 | 114 | 115 | 116 | __mod_name__ = "Math" 117 | 118 | SIMPLIFY_HANDLER = DisableAbleCommandHandler("math", simplify) 119 | FACTOR_HANDLER = DisableAbleCommandHandler("factor", factor) 120 | DERIVE_HANDLER = DisableAbleCommandHandler("derive", derive) 121 | INTEGRATE_HANDLER = DisableAbleCommandHandler("integrate", integrate) 122 | ZEROES_HANDLER = DisableAbleCommandHandler("zeroes", zeroes) 123 | TANGENT_HANDLER = DisableAbleCommandHandler("tangent", tangent) 124 | AREA_HANDLER = DisableAbleCommandHandler("area", area) 125 | COS_HANDLER = DisableAbleCommandHandler("cos", cos) 126 | SIN_HANDLER = DisableAbleCommandHandler("sin", sin) 127 | TAN_HANDLER = DisableAbleCommandHandler("tan", tan) 128 | ARCCOS_HANDLER = DisableAbleCommandHandler("arccos", arccos) 129 | ARCSIN_HANDLER = DisableAbleCommandHandler("arcsin", arcsin) 130 | ARCTAN_HANDLER = DisableAbleCommandHandler("arctan", arctan) 131 | ABS_HANDLER = DisableAbleCommandHandler("abs", abs) 132 | LOG_HANDLER = DisableAbleCommandHandler("log", log) 133 | 134 | dispatcher.add_handler(SIMPLIFY_HANDLER) 135 | dispatcher.add_handler(FACTOR_HANDLER) 136 | dispatcher.add_handler(DERIVE_HANDLER) 137 | dispatcher.add_handler(INTEGRATE_HANDLER) 138 | dispatcher.add_handler(ZEROES_HANDLER) 139 | dispatcher.add_handler(TANGENT_HANDLER) 140 | dispatcher.add_handler(AREA_HANDLER) 141 | dispatcher.add_handler(COS_HANDLER) 142 | dispatcher.add_handler(SIN_HANDLER) 143 | dispatcher.add_handler(TAN_HANDLER) 144 | dispatcher.add_handler(ARCCOS_HANDLER) 145 | dispatcher.add_handler(ARCSIN_HANDLER) 146 | dispatcher.add_handler(ARCTAN_HANDLER) 147 | dispatcher.add_handler(ABS_HANDLER) 148 | dispatcher.add_handler(LOG_HANDLER) 149 | -------------------------------------------------------------------------------- /LaylaRobot/modules/musicplayer.py: -------------------------------------------------------------------------------- 1 | __mod_name__ = "Music Player" 2 | 3 | __help__ = """ 4 | =>> *Song Playing* 🎧 5 | ❍ /play - play song you requested 6 | ❍ /dplay - play song you requested via deezer 7 | ❍ /splay - play song you requested via jio saavn 8 | ❍ /playlist - Show now playing list 9 | ❍ /current - Show now playing 10 | ❍ /song - download songs you want quickly 11 | ❍ /search - search videos on youtube with details 12 | ❍ /deezer - download songs you want quickly via deezer 13 | ❍ /saavn - download songs you want quickly via saavn 14 | ❍ /video - download videos you want quickly 15 | =>> *Admins only* 16 | ❍ /player - open music player settings panel 17 | ❍ /pause - pause song play 18 | ❍ /resume - resume song play 19 | ❍ /skip - play next song 20 | ❍ /end - stop music play 21 | ❍ /userbotjoin - invite assistant to your chat 22 | ❍ /admincache - Refresh admin list 23 | =>> *Use* 24 | 1) Add @LaylaRobot in your group to admin with all permission 25 | 2) Add Assistant I'd to your group @LaylaAssistant 26 | """ 27 | -------------------------------------------------------------------------------- /LaylaRobot/modules/paste.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from LaylaRobot import dispatcher 3 | from LaylaRobot.modules.disable import DisableAbleCommandHandler 4 | from telegram import ParseMode, Update 5 | from telegram.ext import CallbackContext, run_async 6 | 7 | 8 | @run_async 9 | def paste(update: Update, context: CallbackContext): 10 | args = context.args 11 | message = update.effective_message 12 | 13 | if message.reply_to_message: 14 | data = message.reply_to_message.text 15 | 16 | elif len(args) >= 1: 17 | data = message.text.split(None, 1)[1] 18 | 19 | else: 20 | message.reply_text("What am I supposed to do with this?") 21 | return 22 | 23 | key = ( 24 | requests.post("https://nekobin.com/api/documents", json={"content": data}) 25 | .json() 26 | .get("result") 27 | .get("key") 28 | ) 29 | 30 | url = f"https://nekobin.com/{key}" 31 | 32 | reply_text = f"Nekofied to *Nekobin* : {url}" 33 | 34 | message.reply_text( 35 | reply_text, parse_mode=ParseMode.MARKDOWN, disable_web_page_preview=True 36 | ) 37 | 38 | 39 | PASTE_HANDLER = DisableAbleCommandHandler("paste", paste) 40 | dispatcher.add_handler(PASTE_HANDLER) 41 | 42 | __command_list__ = ["paste"] 43 | __handlers__ = [PASTE_HANDLER] 44 | -------------------------------------------------------------------------------- /LaylaRobot/modules/ping.py: -------------------------------------------------------------------------------- 1 | import time 2 | from typing import List 3 | 4 | import requests 5 | from telegram import ParseMode, Update 6 | from telegram.ext import CallbackContext, run_async 7 | 8 | from LaylaRobot import StartTime, dispatcher 9 | from LaylaRobot.modules.helper_funcs.chat_status import sudo_plus 10 | from LaylaRobot.modules.disable import DisableAbleCommandHandler 11 | 12 | sites_list = { 13 | "Telegram": "https://api.telegram.org", 14 | "Kaizoku": "https://animekaizoku.com", 15 | "Kayo": "https://animekayo.com", 16 | "Jikan": "https://api.jikan.moe/v3", 17 | } 18 | 19 | 20 | def get_readable_time(seconds: int) -> str: 21 | count = 0 22 | ping_time = "" 23 | time_list = [] 24 | time_suffix_list = ["s", "m", "h", "days"] 25 | 26 | while count < 4: 27 | count += 1 28 | if count < 3: 29 | remainder, result = divmod(seconds, 60) 30 | else: 31 | remainder, result = divmod(seconds, 24) 32 | if seconds == 0 and remainder == 0: 33 | break 34 | time_list.append(int(result)) 35 | seconds = int(remainder) 36 | 37 | for x in range(len(time_list)): 38 | time_list[x] = str(time_list[x]) + time_suffix_list[x] 39 | if len(time_list) == 4: 40 | ping_time += time_list.pop() + ", " 41 | 42 | time_list.reverse() 43 | ping_time += ":".join(time_list) 44 | 45 | return ping_time 46 | 47 | 48 | def ping_func(to_ping: List[str]) -> List[str]: 49 | ping_result = [] 50 | 51 | for each_ping in to_ping: 52 | 53 | start_time = time.time() 54 | site_to_ping = sites_list[each_ping] 55 | r = requests.get(site_to_ping) 56 | end_time = time.time() 57 | ping_time = str(round((end_time - start_time), 2)) + "s" 58 | 59 | pinged_site = f"{each_ping}" 60 | 61 | if each_ping == "Kaizoku" or each_ping == "Kayo": 62 | pinged_site = f'{each_ping}' 63 | ping_time = f"{ping_time} (Status: {r.status_code})" 64 | 65 | ping_text = f"{pinged_site}: {ping_time}" 66 | ping_result.append(ping_text) 67 | 68 | return ping_result 69 | 70 | 71 | @run_async 72 | @sudo_plus 73 | def ping(update: Update, context: CallbackContext): 74 | msg = update.effective_message 75 | 76 | start_time = time.time() 77 | message = msg.reply_text("Pinging...") 78 | end_time = time.time() 79 | telegram_ping = str(round((end_time - start_time) * 1000, 3)) + " ms" 80 | uptime = get_readable_time((time.time() - StartTime)) 81 | 82 | message.edit_text( 83 | "PONG!!\n" 84 | "Time Taken: {}\n" 85 | "Service uptime: {}".format(telegram_ping, uptime), 86 | parse_mode=ParseMode.HTML, 87 | ) 88 | 89 | 90 | @run_async 91 | @sudo_plus 92 | def pingall(update: Update, context: CallbackContext): 93 | to_ping = ["Kaizoku", "Kayo", "Telegram", "Jikan"] 94 | pinged_list = ping_func(to_ping) 95 | pinged_list.insert(2, "") 96 | uptime = get_readable_time((time.time() - StartTime)) 97 | 98 | reply_msg = "⏱Ping results are:\n" 99 | reply_msg += "\n".join(pinged_list) 100 | reply_msg += "\nService uptime: {}".format(uptime) 101 | 102 | update.effective_message.reply_text( 103 | reply_msg, parse_mode=ParseMode.HTML, disable_web_page_preview=True 104 | ) 105 | 106 | 107 | PING_HANDLER = DisableAbleCommandHandler("ping", ping) 108 | PINGALL_HANDLER = DisableAbleCommandHandler("pingall", pingall) 109 | 110 | dispatcher.add_handler(PING_HANDLER) 111 | dispatcher.add_handler(PINGALL_HANDLER) 112 | 113 | __command_list__ = ["ping", "pingall"] 114 | __handlers__ = [PING_HANDLER, PINGALL_HANDLER] 115 | -------------------------------------------------------------------------------- /LaylaRobot/modules/purge.py: -------------------------------------------------------------------------------- 1 | import time 2 | from telethon import events 3 | 4 | from LaylaRobot import telethn 5 | from LaylaRobot.modules.helper_funcs.telethn.chatstatus import ( 6 | can_delete_messages, 7 | user_is_admin, 8 | ) 9 | 10 | 11 | async def purge_messages(event): 12 | start = time.perf_counter() 13 | if event.from_id is None: 14 | return 15 | 16 | if not await user_is_admin( 17 | user_id=event.sender_id, message=event 18 | ) and event.from_id not in [1087968824]: 19 | await event.reply("Only Admins are allowed to use this command") 20 | return 21 | 22 | if not await can_delete_messages(message=event): 23 | await event.reply("Can't seem to purge the message") 24 | return 25 | 26 | reply_msg = await event.get_reply_message() 27 | if not reply_msg: 28 | await event.reply("Reply to a message to select where to start purging from.") 29 | return 30 | messages = [] 31 | message_id = reply_msg.id 32 | delete_to = event.message.id 33 | 34 | messages.append(event.reply_to_msg_id) 35 | for msg_id in range(message_id, delete_to + 1): 36 | messages.append(msg_id) 37 | if len(messages) == 100: 38 | await event.client.delete_messages(event.chat_id, messages) 39 | messages = [] 40 | 41 | try: 42 | await event.client.delete_messages(event.chat_id, messages) 43 | except: 44 | pass 45 | time_ = time.perf_counter() - start 46 | text = f"Purged Successfully in {time_:0.2f} Second(s)" 47 | await event.respond(text, parse_mode="markdown") 48 | 49 | 50 | async def delete_messages(event): 51 | if event.from_id is None: 52 | return 53 | 54 | if not await user_is_admin( 55 | user_id=event.sender_id, message=event 56 | ) and event.from_id not in [1087968824]: 57 | await event.reply("Only Admins are allowed to use this command") 58 | return 59 | 60 | if not await can_delete_messages(message=event): 61 | await event.reply("Can't seem to delete this?") 62 | return 63 | 64 | message = await event.get_reply_message() 65 | if not message: 66 | await event.reply("Whadya want to delete?") 67 | return 68 | chat = await event.get_input_chat() 69 | del_message = [message, event.message] 70 | await event.client.delete_messages(chat, del_message) 71 | 72 | 73 | 74 | PURGE_HANDLER = purge_messages, events.NewMessage(pattern="^[!/]purge$") 75 | DEL_HANDLER = delete_messages, events.NewMessage(pattern="^[!/]del$") 76 | 77 | telethn.add_event_handler(*PURGE_HANDLER) 78 | telethn.add_event_handler(*DEL_HANDLER) 79 | 80 | __mod_name__ = "DETELE" 81 | __command_list__ = ["del", "purge"] 82 | __handlers__ = [PURGE_HANDLER, DEL_HANDLER] 83 | -------------------------------------------------------------------------------- /LaylaRobot/modules/reactions.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | from LaylaRobot import dispatcher 4 | from LaylaRobot.modules.disable import DisableAbleCommandHandler 5 | from telegram import Update 6 | from telegram.ext import CallbackContext, run_async 7 | 8 | reactions = [ 9 | "( ͡° ͜ʖ ͡°)", 10 | "( . •́ _ʖ •̀ .)", 11 | "( ಠ ͜ʖ ಠ)", 12 | "( ͡ ͜ʖ ͡ )", 13 | "(ʘ ͜ʖ ʘ)", 14 | "ヾ(´〇`)ノ♪♪♪", 15 | "ヽ(o´∀`)ノ♪♬", 16 | "♪♬((d⌒ω⌒b))♬♪", 17 | "└(^^)┐", 18 | "( ̄▽ ̄)/♫•*¨*•.¸¸♪", 19 | "ヾ(⌐■_■)ノ♪", 20 | "乁( • ω •乁)", 21 | "♬♫♪◖(● o ●)◗♪♫♬", 22 | "(っ˘ڡ˘ς)", 23 | "( ˘▽˘)っ♨", 24 | "( ・ω・)⊃-[二二]", 25 | "(*´ー`)旦 旦( ̄ω ̄*)", 26 | "(  ̄▽ ̄)[] [](≧▽≦ )", 27 | "(* ̄▽ ̄)旦 且(´∀`*)", 28 | "(ノ ˘_˘)ノ ζ|||ζ ζ|||ζ ζ|||ζ", 29 | "(ノ°∀°)ノ⌒・*:.。. .。.:*・゜゚・*☆", 30 | "(⊃。•́‿•̀。)⊃━✿✿✿✿✿✿", 31 | "(∩` ロ ´)⊃━炎炎炎炎炎", 32 | "( ・∀・)・・・--------☆", 33 | "( -ω-)/占~~~~~", 34 | "○∞∞∞∞ヽ(^ー^ )", 35 | "(*^^)/~~~~~~~~~~◎", 36 | "(((  ̄□)_/", 37 | "(メ ̄▽ ̄)︻┳═一", 38 | "ヽ( ・∀・)ノ_θ彡☆Σ(ノ `Д´)ノ", 39 | "(*`0´)θ☆(メ°皿°)ノ", 40 | "(; -_-)――――――C<―_-)", 41 | "ヽ(>_<ヽ) ―⊂|=0ヘ(^‿^ )", 42 | "(҂` ロ ´)︻デ═一 \(º □ º l|l)/", 43 | "/( .□.)\ ︵╰(°益°)╯︵ /(.□. /)", 44 | "(`⌒*)O-(`⌒´Q)", 45 | "(っ•﹏•)っ ✴==≡눈٩(`皿´҂)ง", 46 | "ヾ(・ω・)メ(・ω・)ノ", 47 | "(*^ω^)八(⌒▽⌒)八(-‿‿- )ヽ", 48 | "ヽ( ⌒ω⌒)人(=^‥^= )ノ", 49 | "。*:☆(・ω・人・ω・)。:゜☆。", 50 | "(°(°ω(°ω°(☆ω☆)°ω°)ω°)°)", 51 | "(っ˘▽˘)(˘▽˘)˘▽˘ς)", 52 | "(*^ω^)人(^ω^*)", 53 | "\(▽ ̄ \ ( ̄▽ ̄) /  ̄▽)/", 54 | "( ̄Θ ̄)", 55 | "\( ˋ Θ ´ )/", 56 | "( ´(00)ˋ )", 57 | "\( ̄(oo) ̄)/", 58 | "/(≧ x ≦)\", 59 | "/(=・ x ・=)\", 60 | "(=^・ω・^=)", 61 | "(= ; ェ ; =)", 62 | "(=⌒‿‿⌒=)", 63 | "(^• ω •^)", 64 | "ଲ(ⓛ ω ⓛ)ଲ", 65 | "ଲ(ⓛ ω ⓛ)ଲ", 66 | "(^◔ᴥ◔^)", 67 | "[(--)]..zzZ", 68 | "( ̄o ̄) zzZZzzZZ", 69 | "(_ _*) Z z z", 70 | "☆ミ(o*・ω・)ノ", 71 | "ε=ε=ε=ε=┌(; ̄▽ ̄)┘", 72 | "ε===(っ≧ω≦)っ", 73 | "__φ(..)", 74 | "ヾ( `ー´)シφ__", 75 | "( ^▽^)ψ__", 76 | "|・ω・)", 77 | "|д・)", 78 | "┬┴┬┴┤・ω・)ノ", 79 | "|・д・)ノ", 80 | "(* ̄ii ̄)", 81 | "(^〃^)", 82 | "m(_ _)m", 83 | "人(_ _*)", 84 | "(シ. .)シ", 85 | "(^_~)", 86 | "(>ω^)", 87 | "(^_<)〜☆", 88 | "(^_<)", 89 | "(づ ̄ ³ ̄)づ", 90 | "(⊃。•́‿•̀。)⊃", 91 | "⊂(´• ω •`⊂)", 92 | "(*・ω・)ノ", 93 | "(^-^*)/", 94 | "ヾ(*'▽'*)", 95 | "(^0^)ノ", 96 | "(*°ー°)ノ", 97 | "( ̄ω ̄)/", 98 | "(≧▽≦)/", 99 | "w(°o°)w", 100 | "(⊙_⊙)", 101 | "(°ロ°) !", 102 | "∑(O_O;)", 103 | "(¬_¬)", 104 | "(¬_¬ )", 105 | "(↼_↼)", 106 | "( ̄ω ̄;)", 107 | "┐('~`;)┌", 108 | "(・_・;)", 109 | "(@_@)", 110 | "(•ิ_•ิ)?", 111 | "ヽ(ー_ー )ノ", 112 | "┐( ̄ヘ ̄)┌", 113 | "┐( ̄~ ̄)┌", 114 | "┐( ´ д ` )┌", 115 | "╮(︶▽︶)╭", 116 | "ᕕ( ᐛ )ᕗ", 117 | "(ノωヽ)", 118 | "(″ロ゛)", 119 | "(/ω\)", 120 | "(((><)))", 121 | "~(>_<~)", 122 | "(×_×)", 123 | "(×﹏×)", 124 | "(ノ_<。)", 125 | "(μ_μ)", 126 | "o(TヘTo)", 127 | "( ゚,_ゝ`)", 128 | "( ╥ω╥ )", 129 | "(/ˍ・、)", 130 | "(つω`。)", 131 | "(T_T)", 132 | "o(〒﹏〒)o", 133 | "(#`Д´)", 134 | "(・`ω´・)", 135 | "( `ε´ )", 136 | "(メ` ロ ´)", 137 | "Σ(▼□▼メ)", 138 | "(҂ `з´ )", 139 | "٩(╬ʘ益ʘ╬)۶", 140 | "↑_(ΦwΦ)Ψ", 141 | "(ノಥ益ಥ)ノ", 142 | "(#><)", 143 | "(; ̄Д ̄)", 144 | "(¬_¬;)", 145 | "(^^#)", 146 | "( ̄︿ ̄)", 147 | "ヾ(  ̄O ̄)ツ", 148 | "(ᗒᗣᗕ)՞", 149 | "(ノ_<。)ヾ(´ ▽ ` )", 150 | "ヽ( ̄ω ̄(。。 )ゝ", 151 | "(ノ_;)ヾ(´ ∀ ` )", 152 | "(´-ω-`( _ _ )", 153 | "(⌒_⌒;)", 154 | "(*/_\)", 155 | "( ◡‿◡ *)", 156 | "(//ω//)", 157 | "( ̄▽ ̄*)ゞ", 158 | "(„ಡωಡ„)", 159 | "(ノ´ з `)ノ", 160 | "(♡-_-♡)", 161 | "(─‿‿─)♡", 162 | "(´ ω `♡)", 163 | "(ღ˘⌣˘ღ)", 164 | "(´• ω •`) ♡", 165 | "╰(*´︶`*)╯♡", 166 | "(≧◡≦) ♡", 167 | "♡ (˘▽˘>ԅ( ˘⌣˘)", 168 | "σ(≧ε≦σ) ♡", 169 | "(˘∀˘)/(μ‿μ) ❤", 170 | "Σ>―(〃°ω°〃)♡→", 171 | "(* ^ ω ^)", 172 | "(o^▽^o)", 173 | "ヽ(・∀・)ノ", 174 | "(o・ω・o)", 175 | "(^人^)", 176 | "( ´ ω ` )", 177 | "(´• ω •`)", 178 | "╰(▔∀▔)╯", 179 | "(✯◡✯)", 180 | "(⌒‿⌒)", 181 | "(*°▽°*)", 182 | "(´。• ᵕ •。`)", 183 | "ヽ(>∀<☆)ノ", 184 | "\( ̄▽ ̄)/", 185 | "(o˘◡˘o)", 186 | "(╯✧▽✧)╯", 187 | "( ‾́ ◡ ‾́ )", 188 | "(๑˘︶˘๑)", 189 | "(´・ᴗ・ ` )", 190 | "( ͡° ʖ̯ ͡°)", 191 | "( ఠ ͟ʖ ఠ)", 192 | "( ಥ ʖ̯ ಥ)", 193 | "(≖ ͜ʖ≖)", 194 | "ヘ( ̄ω ̄ヘ)", 195 | "(ノ≧∀≦)ノ", 196 | "└( ̄- ̄└))", 197 | "┌(^^)┘", 198 | "(^_^♪)", 199 | "(〜 ̄△ ̄)〜", 200 | "(「• ω •)「", 201 | "( ˘ ɜ˘) ♬♪♫", 202 | "( o˘◡˘o) ┌iii┐", 203 | "♨o(>_<)o♨", 204 | "( ・・)つ―{}@{}@{}-", 205 | "(*´з`)口゚。゚口(・∀・ )", 206 | "( *^^)o∀*∀o(^^* )", 207 | "-●●●-c(・・ )", 208 | "(ノ≧∀≦)ノ ‥…━━━★", 209 | "╰( ͡° ͜ʖ ͡° )つ──☆*:・゚", 210 | "(∩ᄑ_ᄑ)⊃━☆゚*・。*・:≡( ε:)", 211 | ] 212 | 213 | 214 | @run_async 215 | def react(update: Update, context: CallbackContext): 216 | message = update.effective_message 217 | react = random.choice(reactions) 218 | if message.reply_to_message: 219 | message.reply_to_message.reply_text(react) 220 | else: 221 | message.reply_text(react) 222 | 223 | 224 | REACT_HANDLER = DisableAbleCommandHandler("react", react) 225 | 226 | dispatcher.add_handler(REACT_HANDLER) 227 | 228 | __command_list__ = ["react"] 229 | __handlers__ = [REACT_HANDLER] 230 | -------------------------------------------------------------------------------- /LaylaRobot/modules/rules.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | import LaylaRobot.modules.sql.rules_sql as sql 4 | from LaylaRobot import dispatcher 5 | from LaylaRobot.modules.helper_funcs.chat_status import user_admin 6 | from LaylaRobot.modules.helper_funcs.string_handling import markdown_parser 7 | from telegram import ( 8 | InlineKeyboardButton, 9 | InlineKeyboardMarkup, 10 | Message, 11 | ParseMode, 12 | Update, 13 | User, 14 | ) 15 | from telegram.error import BadRequest 16 | from telegram.ext import CallbackContext, CommandHandler, Filters, run_async 17 | from telegram.utils.helpers import escape_markdown 18 | 19 | 20 | @run_async 21 | def get_rules(update: Update, context: CallbackContext): 22 | chat_id = update.effective_chat.id 23 | send_rules(update, chat_id) 24 | 25 | 26 | # Do not async - not from a handler 27 | def send_rules(update, chat_id, from_pm=False): 28 | bot = dispatcher.bot 29 | user = update.effective_user # type: Optional[User] 30 | try: 31 | chat = bot.get_chat(chat_id) 32 | except BadRequest as excp: 33 | if excp.message == "Chat not found" and from_pm: 34 | bot.send_message( 35 | user.id, 36 | "The rules shortcut for this chat hasn't been set properly! Ask admins to " 37 | "fix this.\nMaybe they forgot the hyphen in ID", 38 | ) 39 | return 40 | else: 41 | raise 42 | 43 | rules = sql.get_rules(chat_id) 44 | text = f"The rules for *{escape_markdown(chat.title)}* are:\n\n{rules}" 45 | 46 | if from_pm and rules: 47 | bot.send_message( 48 | user.id, text, parse_mode=ParseMode.MARKDOWN, disable_web_page_preview=True 49 | ) 50 | elif from_pm: 51 | bot.send_message( 52 | user.id, 53 | "The group admins haven't set any rules for this chat yet. " 54 | "This probably doesn't mean it's lawless though...!", 55 | ) 56 | elif rules: 57 | update.effective_message.reply_text( 58 | "Please click the button below to see the rules.", 59 | reply_markup=InlineKeyboardMarkup( 60 | [ 61 | [ 62 | InlineKeyboardButton( 63 | text="Rules", url=f"t.me/{bot.username}?start={chat_id}" 64 | ) 65 | ] 66 | ] 67 | ), 68 | ) 69 | else: 70 | update.effective_message.reply_text( 71 | "The group admins haven't set any rules for this chat yet. " 72 | "This probably doesn't mean it's lawless though...!" 73 | ) 74 | 75 | 76 | @run_async 77 | @user_admin 78 | def set_rules(update: Update, context: CallbackContext): 79 | chat_id = update.effective_chat.id 80 | msg = update.effective_message # type: Optional[Message] 81 | raw_text = msg.text 82 | args = raw_text.split(None, 1) # use python's maxsplit to separate cmd and args 83 | if len(args) == 2: 84 | txt = args[1] 85 | offset = len(txt) - len(raw_text) # set correct offset relative to command 86 | markdown_rules = markdown_parser( 87 | txt, entities=msg.parse_entities(), offset=offset 88 | ) 89 | 90 | sql.set_rules(chat_id, markdown_rules) 91 | update.effective_message.reply_text("Successfully set rules for this group.") 92 | 93 | 94 | @run_async 95 | @user_admin 96 | def clear_rules(update: Update, context: CallbackContext): 97 | chat_id = update.effective_chat.id 98 | sql.set_rules(chat_id, "") 99 | update.effective_message.reply_text("Successfully cleared rules!") 100 | 101 | 102 | def __stats__(): 103 | return f"• {sql.num_chats()} chats have rules set." 104 | 105 | 106 | def __import_data__(chat_id, data): 107 | # set chat rules 108 | rules = data.get("info", {}).get("rules", "") 109 | sql.set_rules(chat_id, rules) 110 | 111 | 112 | def __migrate__(old_chat_id, new_chat_id): 113 | sql.migrate_chat(old_chat_id, new_chat_id) 114 | 115 | 116 | def __chat_settings__(chat_id, user_id): 117 | return f"This chat has had it's rules set: `{bool(sql.get_rules(chat_id))}`" 118 | 119 | 120 | __help__ = """ 121 | ❍ /rules*:* get the rules for this chat. 122 | 123 | *Admins only:* 124 | ❍ /setrules *:* set the rules for this chat. 125 | ❍ /clearrules*:* clear the rules for this chat. 126 | """ 127 | 128 | __mod_name__ = "Rules" 129 | 130 | GET_RULES_HANDLER = CommandHandler("rules", get_rules, filters=Filters.group) 131 | SET_RULES_HANDLER = CommandHandler("setrules", set_rules, filters=Filters.group) 132 | RESET_RULES_HANDLER = CommandHandler("clearrules", clear_rules, filters=Filters.group) 133 | 134 | dispatcher.add_handler(GET_RULES_HANDLER) 135 | dispatcher.add_handler(SET_RULES_HANDLER) 136 | dispatcher.add_handler(RESET_RULES_HANDLER) 137 | -------------------------------------------------------------------------------- /LaylaRobot/modules/shell.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | 3 | from LaylaRobot import LOGGER, dispatcher 4 | from LaylaRobot.modules.helper_funcs.chat_status import dev_plus 5 | from telegram import ParseMode, Update 6 | from telegram.ext import CallbackContext, CommandHandler 7 | from telegram.ext.dispatcher import run_async 8 | 9 | 10 | @dev_plus 11 | @run_async 12 | def shell(update: Update, context: CallbackContext): 13 | message = update.effective_message 14 | cmd = message.text.split(" ", 1) 15 | if len(cmd) == 1: 16 | message.reply_text("No command to execute was given.") 17 | return 18 | cmd = cmd[1] 19 | process = subprocess.Popen( 20 | cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True 21 | ) 22 | stdout, stderr = process.communicate() 23 | reply = "" 24 | stderr = stderr.decode() 25 | stdout = stdout.decode() 26 | if stdout: 27 | reply += f"*Stdout*\n`{stdout}`\n" 28 | LOGGER.info(f"Shell - {cmd} - {stdout}") 29 | if stderr: 30 | reply += f"*Stderr*\n`{stderr}`\n" 31 | LOGGER.error(f"Shell - {cmd} - {stderr}") 32 | if len(reply) > 3000: 33 | with open("shell_output.txt", "w") as file: 34 | file.write(reply) 35 | with open("shell_output.txt", "rb") as doc: 36 | context.bot.send_document( 37 | document=doc, 38 | filename=doc.name, 39 | reply_to_message_id=message.message_id, 40 | chat_id=message.chat_id, 41 | ) 42 | else: 43 | message.reply_text(reply, parse_mode=ParseMode.MARKDOWN) 44 | 45 | 46 | SHELL_HANDLER = CommandHandler(["sh"], shell) 47 | dispatcher.add_handler(SHELL_HANDLER) 48 | __mod_name__ = "Shell" 49 | __command_list__ = ["sh"] 50 | __handlers__ = [SHELL_HANDLER] 51 | -------------------------------------------------------------------------------- /LaylaRobot/modules/speed_test.py: -------------------------------------------------------------------------------- 1 | import speedtest 2 | from LaylaRobot import DEV_USERS, dispatcher 3 | from LaylaRobot.modules.disable import DisableAbleCommandHandler 4 | from LaylaRobot.modules.helper_funcs.chat_status import dev_plus 5 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode, Update 6 | from telegram.ext import CallbackContext, CallbackQueryHandler, run_async 7 | 8 | 9 | def convert(speed): 10 | return round(int(speed) / 1048576, 2) 11 | 12 | 13 | @dev_plus 14 | @run_async 15 | def speedtestxyz(update: Update, context: CallbackContext): 16 | buttons = [ 17 | [ 18 | InlineKeyboardButton("Image", callback_data="speedtest_image"), 19 | InlineKeyboardButton("Text", callback_data="speedtest_text"), 20 | ] 21 | ] 22 | update.effective_message.reply_text( 23 | "Select SpeedTest Mode", reply_markup=InlineKeyboardMarkup(buttons) 24 | ) 25 | 26 | 27 | @run_async 28 | def speedtestxyz_callback(update: Update, context: CallbackContext): 29 | query = update.callback_query 30 | 31 | if query.from_user.id in DEV_USERS: 32 | msg = update.effective_message.edit_text("Running a speedtest....") 33 | speed = speedtest.Speedtest() 34 | speed.get_best_server() 35 | speed.download() 36 | speed.upload() 37 | replymsg = "SpeedTest Results:" 38 | 39 | if query.data == "speedtest_image": 40 | speedtest_image = speed.results.share() 41 | update.effective_message.reply_photo( 42 | photo=speedtest_image, caption=replymsg 43 | ) 44 | msg.delete() 45 | 46 | elif query.data == "speedtest_text": 47 | result = speed.results.dict() 48 | replymsg += f"\nDownload: `{convert(result['download'])}Mb/s`\nUpload: `{convert(result['upload'])}Mb/s`\nPing: `{result['ping']}`" 49 | update.effective_message.edit_text(replymsg, parse_mode=ParseMode.MARKDOWN) 50 | else: 51 | query.answer("You are required to join Heroes Association to use this command.") 52 | 53 | 54 | SPEED_TEST_HANDLER = DisableAbleCommandHandler("speedtest", speedtestxyz) 55 | SPEED_TEST_CALLBACKHANDLER = CallbackQueryHandler( 56 | speedtestxyz_callback, pattern="speedtest_.*" 57 | ) 58 | 59 | dispatcher.add_handler(SPEED_TEST_HANDLER) 60 | dispatcher.add_handler(SPEED_TEST_CALLBACKHANDLER) 61 | 62 | __mod_name__ = "SpeedTest" 63 | __command_list__ = ["speedtest"] 64 | __handlers__ = [SPEED_TEST_HANDLER, SPEED_TEST_CALLBACKHANDLER] 65 | -------------------------------------------------------------------------------- /LaylaRobot/modules/sql/__init__.py: -------------------------------------------------------------------------------- 1 | from LaylaRobot import DB_URI 2 | from sqlalchemy import create_engine 3 | from sqlalchemy.ext.declarative import declarative_base 4 | from sqlalchemy.orm import scoped_session, sessionmaker 5 | 6 | 7 | def start() -> scoped_session: 8 | engine = create_engine(DB_URI, client_encoding="utf8") 9 | BASE.metadata.bind = engine 10 | BASE.metadata.create_all(engine) 11 | return scoped_session(sessionmaker(bind=engine, autoflush=False)) 12 | 13 | 14 | BASE = declarative_base() 15 | SESSION = start() 16 | -------------------------------------------------------------------------------- /LaylaRobot/modules/sql/afk_sql.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | from LaylaRobot.modules.sql import BASE, SESSION 4 | from sqlalchemy import Boolean, Column, Integer, UnicodeText 5 | 6 | 7 | class AFK(BASE): 8 | __tablename__ = "afk_users" 9 | 10 | user_id = Column(Integer, primary_key=True) 11 | is_afk = Column(Boolean) 12 | reason = Column(UnicodeText) 13 | 14 | def __init__(self, user_id, reason="", is_afk=True): 15 | self.user_id = user_id 16 | self.reason = reason 17 | self.is_afk = is_afk 18 | 19 | def __repr__(self): 20 | return "afk_status for {}".format(self.user_id) 21 | 22 | 23 | AFK.__table__.create(checkfirst=True) 24 | INSERTION_LOCK = threading.RLock() 25 | 26 | AFK_USERS = {} 27 | 28 | 29 | def is_afk(user_id): 30 | return user_id in AFK_USERS 31 | 32 | 33 | def check_afk_status(user_id): 34 | try: 35 | return SESSION.query(AFK).get(user_id) 36 | finally: 37 | SESSION.close() 38 | 39 | 40 | def set_afk(user_id, reason=""): 41 | with INSERTION_LOCK: 42 | curr = SESSION.query(AFK).get(user_id) 43 | if not curr: 44 | curr = AFK(user_id, reason, True) 45 | else: 46 | curr.is_afk = True 47 | 48 | AFK_USERS[user_id] = reason 49 | 50 | SESSION.add(curr) 51 | SESSION.commit() 52 | 53 | 54 | def rm_afk(user_id): 55 | with INSERTION_LOCK: 56 | curr = SESSION.query(AFK).get(user_id) 57 | if curr: 58 | if user_id in AFK_USERS: # sanity check 59 | del AFK_USERS[user_id] 60 | 61 | SESSION.delete(curr) 62 | SESSION.commit() 63 | return True 64 | 65 | SESSION.close() 66 | return False 67 | 68 | 69 | def toggle_afk(user_id, reason=""): 70 | with INSERTION_LOCK: 71 | curr = SESSION.query(AFK).get(user_id) 72 | if not curr: 73 | curr = AFK(user_id, reason, True) 74 | elif curr.is_afk: 75 | curr.is_afk = False 76 | elif not curr.is_afk: 77 | curr.is_afk = True 78 | SESSION.add(curr) 79 | SESSION.commit() 80 | 81 | 82 | def __load_afk_users(): 83 | global AFK_USERS 84 | try: 85 | all_afk = SESSION.query(AFK).all() 86 | AFK_USERS = {user.user_id: user.reason for user in all_afk if user.is_afk} 87 | finally: 88 | SESSION.close() 89 | 90 | 91 | __load_afk_users() 92 | -------------------------------------------------------------------------------- /LaylaRobot/modules/sql/aihelp_sql.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | from LaylaRobot.modules.sql import BASE, SESSION 4 | from sqlalchemy import Column, String 5 | 6 | 7 | class aiChats(BASE): 8 | __tablename__ = "ai_chats" 9 | chat_id = Column(String(14), primary_key=True) 10 | ses_id = Column(String(70)) 11 | expires = Column(String(15)) 12 | 13 | def __init__(self, chat_id, ses_id, expires): 14 | self.chat_id = chat_id 15 | self.ses_id = ses_id 16 | self.expires = expires 17 | 18 | 19 | aiChats.__table__.create(checkfirst=True) 20 | 21 | INSERTION_LOCK = threading.RLock() 22 | 23 | 24 | def is_chat(chat_id): 25 | try: 26 | chat = SESSION.query(aiChats).get(str(chat_id)) 27 | if chat: 28 | return True 29 | return False 30 | finally: 31 | SESSION.close() 32 | 33 | 34 | def set_ses(chat_id, ses_id, expires): 35 | with INSERTION_LOCK: 36 | autochat = SESSION.query(aiChats).get(str(chat_id)) 37 | if not autochat: 38 | autochat = aiChats(str(chat_id), str(ses_id), str(expires)) 39 | else: 40 | autochat.ses_id = str(ses_id) 41 | autochat.expires = str(expires) 42 | 43 | SESSION.add(autochat) 44 | SESSION.commit() 45 | 46 | 47 | def get_ses(chat_id): 48 | autochat = SESSION.query(aiChats).get(str(chat_id)) 49 | sesh = "" 50 | exp = "" 51 | if autochat: 52 | sesh = str(autochat.ses_id) 53 | exp = str(autochat.expires) 54 | 55 | SESSION.close() 56 | return sesh, exp 57 | 58 | 59 | def rem_chat(chat_id): 60 | with INSERTION_LOCK: 61 | autochat = SESSION.query(aiChats).get(str(chat_id)) 62 | if autochat: 63 | SESSION.delete(autochat) 64 | 65 | SESSION.commit() 66 | 67 | 68 | def get_all_chats(): 69 | try: 70 | return SESSION.query(aiChats.chat_id).all() 71 | finally: 72 | SESSION.close() -------------------------------------------------------------------------------- /LaylaRobot/modules/sql/antiflood_sql.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | from sqlalchemy import String, Column, Integer, UnicodeText 4 | 5 | from LaylaRobot.modules.sql import SESSION, BASE 6 | 7 | DEF_COUNT = 1 8 | DEF_LIMIT = 0 9 | DEF_OBJ = (None, DEF_COUNT, DEF_LIMIT) 10 | 11 | 12 | class FloodControl(BASE): 13 | __tablename__ = "antiflood" 14 | chat_id = Column(String(14), primary_key=True) 15 | user_id = Column(Integer) 16 | count = Column(Integer, default=DEF_COUNT) 17 | limit = Column(Integer, default=DEF_LIMIT) 18 | 19 | def __init__(self, chat_id): 20 | self.chat_id = str(chat_id) # ensure string 21 | 22 | def __repr__(self): 23 | return "" % self.chat_id 24 | 25 | 26 | class FloodSettings(BASE): 27 | __tablename__ = "antiflood_settings" 28 | chat_id = Column(String(14), primary_key=True) 29 | flood_type = Column(Integer, default=1) 30 | value = Column(UnicodeText, default="0") 31 | 32 | def __init__(self, chat_id, flood_type=1, value="0"): 33 | self.chat_id = str(chat_id) 34 | self.flood_type = flood_type 35 | self.value = value 36 | 37 | def __repr__(self): 38 | return "<{} will executing {} for flood.>".format(self.chat_id, self.flood_type) 39 | 40 | 41 | FloodControl.__table__.create(checkfirst=True) 42 | FloodSettings.__table__.create(checkfirst=True) 43 | 44 | INSERTION_FLOOD_LOCK = threading.RLock() 45 | INSERTION_FLOOD_SETTINGS_LOCK = threading.RLock() 46 | 47 | CHAT_FLOOD = {} 48 | 49 | 50 | def set_flood(chat_id, amount): 51 | with INSERTION_FLOOD_LOCK: 52 | flood = SESSION.query(FloodControl).get(str(chat_id)) 53 | if not flood: 54 | flood = FloodControl(str(chat_id)) 55 | 56 | flood.user_id = None 57 | flood.limit = amount 58 | 59 | CHAT_FLOOD[str(chat_id)] = (None, DEF_COUNT, amount) 60 | 61 | SESSION.add(flood) 62 | SESSION.commit() 63 | 64 | 65 | def update_flood(chat_id: str, user_id) -> bool: 66 | if str(chat_id) in CHAT_FLOOD: 67 | curr_user_id, count, limit = CHAT_FLOOD.get(str(chat_id), DEF_OBJ) 68 | 69 | if limit == 0: # no antiflood 70 | return False 71 | 72 | if user_id != curr_user_id or user_id is None: # other user 73 | CHAT_FLOOD[str(chat_id)] = (user_id, DEF_COUNT, limit) 74 | return False 75 | 76 | count += 1 77 | if count > limit: # too many msgs, kick 78 | CHAT_FLOOD[str(chat_id)] = (None, DEF_COUNT, limit) 79 | return True 80 | 81 | # default -> update 82 | CHAT_FLOOD[str(chat_id)] = (user_id, count, limit) 83 | return False 84 | 85 | 86 | def get_flood_limit(chat_id): 87 | return CHAT_FLOOD.get(str(chat_id), DEF_OBJ)[2] 88 | 89 | 90 | def set_flood_strength(chat_id, flood_type, value): 91 | # for flood_type 92 | # 1 = ban 93 | # 2 = kick 94 | # 3 = mute 95 | # 4 = tban 96 | # 5 = tmute 97 | with INSERTION_FLOOD_SETTINGS_LOCK: 98 | curr_setting = SESSION.query(FloodSettings).get(str(chat_id)) 99 | if not curr_setting: 100 | curr_setting = FloodSettings( 101 | chat_id, flood_type=int(flood_type), value=value 102 | ) 103 | 104 | curr_setting.flood_type = int(flood_type) 105 | curr_setting.value = str(value) 106 | 107 | SESSION.add(curr_setting) 108 | SESSION.commit() 109 | 110 | 111 | def get_flood_setting(chat_id): 112 | try: 113 | setting = SESSION.query(FloodSettings).get(str(chat_id)) 114 | if setting: 115 | return setting.flood_type, setting.value 116 | else: 117 | return 1, "0" 118 | 119 | finally: 120 | SESSION.close() 121 | 122 | 123 | def migrate_chat(old_chat_id, new_chat_id): 124 | with INSERTION_FLOOD_LOCK: 125 | flood = SESSION.query(FloodControl).get(str(old_chat_id)) 126 | if flood: 127 | CHAT_FLOOD[str(new_chat_id)] = CHAT_FLOOD.get(str(old_chat_id), DEF_OBJ) 128 | flood.chat_id = str(new_chat_id) 129 | SESSION.commit() 130 | 131 | SESSION.close() 132 | 133 | 134 | def __load_flood_settings(): 135 | global CHAT_FLOOD 136 | try: 137 | all_chats = SESSION.query(FloodControl).all() 138 | CHAT_FLOOD = {chat.chat_id: (None, DEF_COUNT, chat.limit) for chat in all_chats} 139 | finally: 140 | SESSION.close() 141 | 142 | 143 | __load_flood_settings() 144 | -------------------------------------------------------------------------------- /LaylaRobot/modules/sql/approve_sql.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | from sqlalchemy import Column, String, UnicodeText, Integer, func, distinct 4 | 5 | from LaylaRobot.modules.sql import BASE, SESSION 6 | 7 | 8 | class Approvals(BASE): 9 | __tablename__ = "approval" 10 | chat_id = Column(String(14), primary_key=True) 11 | user_id = Column(Integer, primary_key=True) 12 | 13 | def __init__(self, chat_id, user_id): 14 | self.chat_id = str(chat_id) # ensure string 15 | self.user_id = user_id 16 | 17 | def __repr__(self): 18 | return "" % self.user_id 19 | 20 | 21 | Approvals.__table__.create(checkfirst=True) 22 | 23 | APPROVE_INSERTION_LOCK = threading.RLock() 24 | 25 | 26 | def approve(chat_id, user_id): 27 | with APPROVE_INSERTION_LOCK: 28 | approve_user = Approvals(str(chat_id), user_id) 29 | SESSION.add(approve_user) 30 | SESSION.commit() 31 | 32 | 33 | def is_approved(chat_id, user_id): 34 | try: 35 | return SESSION.query(Approvals).get((str(chat_id), user_id)) 36 | finally: 37 | SESSION.close() 38 | 39 | 40 | def disapprove(chat_id, user_id): 41 | with APPROVE_INSERTION_LOCK: 42 | disapprove_user = SESSION.query(Approvals).get((str(chat_id), user_id)) 43 | if disapprove_user: 44 | SESSION.delete(disapprove_user) 45 | SESSION.commit() 46 | return True 47 | else: 48 | SESSION.close() 49 | return False 50 | 51 | 52 | def list_approved(chat_id): 53 | try: 54 | return ( 55 | SESSION.query(Approvals) 56 | .filter(Approvals.chat_id == str(chat_id)) 57 | .order_by(Approvals.user_id.asc()) 58 | .all() 59 | ) 60 | finally: 61 | SESSION.close() 62 | -------------------------------------------------------------------------------- /LaylaRobot/modules/sql/blacklistusers_sql.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | from LaylaRobot.modules.sql import BASE, SESSION 4 | from sqlalchemy import Column, String, UnicodeText 5 | 6 | 7 | class BlacklistUsers(BASE): 8 | __tablename__ = "blacklistusers" 9 | user_id = Column(String(14), primary_key=True) 10 | reason = Column(UnicodeText) 11 | 12 | def __init__(self, user_id, reason=None): 13 | self.user_id = user_id 14 | self.reason = reason 15 | 16 | 17 | BlacklistUsers.__table__.create(checkfirst=True) 18 | 19 | BLACKLIST_LOCK = threading.RLock() 20 | BLACKLIST_USERS = set() 21 | 22 | 23 | def blacklist_user(user_id, reason=None): 24 | with BLACKLIST_LOCK: 25 | user = SESSION.query(BlacklistUsers).get(str(user_id)) 26 | if not user: 27 | user = BlacklistUsers(str(user_id), reason) 28 | else: 29 | user.reason = reason 30 | 31 | SESSION.add(user) 32 | SESSION.commit() 33 | __load_blacklist_userid_list() 34 | 35 | 36 | def unblacklist_user(user_id): 37 | with BLACKLIST_LOCK: 38 | user = SESSION.query(BlacklistUsers).get(str(user_id)) 39 | if user: 40 | SESSION.delete(user) 41 | 42 | SESSION.commit() 43 | __load_blacklist_userid_list() 44 | 45 | 46 | def get_reason(user_id): 47 | user = SESSION.query(BlacklistUsers).get(str(user_id)) 48 | rep = "" 49 | if user: 50 | rep = user.reason 51 | 52 | SESSION.close() 53 | return rep 54 | 55 | 56 | def is_user_blacklisted(user_id): 57 | return user_id in BLACKLIST_USERS 58 | 59 | 60 | def __load_blacklist_userid_list(): 61 | global BLACKLIST_USERS 62 | try: 63 | BLACKLIST_USERS = {int(x.user_id) for x in SESSION.query(BlacklistUsers).all()} 64 | finally: 65 | SESSION.close() 66 | 67 | 68 | __load_blacklist_userid_list() 69 | -------------------------------------------------------------------------------- /LaylaRobot/modules/sql/chatbot_sql.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | from LaylaRobot.modules.sql import BASE, SESSION 4 | from sqlalchemy import Column, String 5 | 6 | 7 | class ChatbotChats(BASE): 8 | __tablename__ = "chatbot_chats" 9 | chat_id = Column(String(14), primary_key=True) 10 | ses_id = Column(String(70)) 11 | expires = Column(String(15)) 12 | 13 | def __init__(self, chat_id, ses_id, expires): 14 | self.chat_id = chat_id 15 | self.ses_id = ses_id 16 | self.expires = expires 17 | 18 | 19 | ChatbotChats.__table__.create(checkfirst=True) 20 | 21 | INSERTION_LOCK = threading.RLock() 22 | 23 | 24 | def is_chat(chat_id): 25 | try: 26 | chat = SESSION.query(ChatbotChats).get(str(chat_id)) 27 | if chat: 28 | return True 29 | else: 30 | return False 31 | finally: 32 | SESSION.close() 33 | 34 | 35 | def set_ses(chat_id, ses_id, expires): 36 | with INSERTION_LOCK: 37 | autochat = SESSION.query(ChatbotChats).get(str(chat_id)) 38 | if not autochat: 39 | autochat = ChatbotChats(str(chat_id), str(ses_id), str(expires)) 40 | else: 41 | autochat.ses_id = str(ses_id) 42 | autochat.expires = str(expires) 43 | 44 | SESSION.add(autochat) 45 | SESSION.commit() 46 | 47 | 48 | def get_ses(chat_id): 49 | autochat = SESSION.query(ChatbotChats).get(str(chat_id)) 50 | sesh = "" 51 | exp = "" 52 | if autochat: 53 | sesh = str(autochat.ses_id) 54 | exp = str(autochat.expires) 55 | 56 | SESSION.close() 57 | return sesh, exp 58 | 59 | 60 | def rem_chat(chat_id): 61 | with INSERTION_LOCK: 62 | autochat = SESSION.query(ChatbotChats).get(str(chat_id)) 63 | if autochat: 64 | SESSION.delete(autochat) 65 | 66 | SESSION.commit() 67 | 68 | 69 | def get_all_chats(): 70 | try: 71 | return SESSION.query(ChatbotChats.chat_id).all() 72 | finally: 73 | SESSION.close() 74 | -------------------------------------------------------------------------------- /LaylaRobot/modules/sql/disable_sql.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | from LaylaRobot.modules.sql import BASE, SESSION 4 | from sqlalchemy import Column, String, UnicodeText, distinct, func 5 | 6 | 7 | class Disable(BASE): 8 | __tablename__ = "disabled_commands" 9 | chat_id = Column(String(14), primary_key=True) 10 | command = Column(UnicodeText, primary_key=True) 11 | 12 | def __init__(self, chat_id, command): 13 | self.chat_id = chat_id 14 | self.command = command 15 | 16 | def __repr__(self): 17 | return "Disabled cmd {} in {}".format(self.command, self.chat_id) 18 | 19 | 20 | Disable.__table__.create(checkfirst=True) 21 | DISABLE_INSERTION_LOCK = threading.RLock() 22 | 23 | DISABLED = {} 24 | 25 | 26 | def disable_command(chat_id, disable): 27 | with DISABLE_INSERTION_LOCK: 28 | disabled = SESSION.query(Disable).get((str(chat_id), disable)) 29 | 30 | if not disabled: 31 | DISABLED.setdefault(str(chat_id), set()).add(disable) 32 | 33 | disabled = Disable(str(chat_id), disable) 34 | SESSION.add(disabled) 35 | SESSION.commit() 36 | return True 37 | 38 | SESSION.close() 39 | return False 40 | 41 | 42 | def enable_command(chat_id, enable): 43 | with DISABLE_INSERTION_LOCK: 44 | disabled = SESSION.query(Disable).get((str(chat_id), enable)) 45 | 46 | if disabled: 47 | if enable in DISABLED.get(str(chat_id)): # sanity check 48 | DISABLED.setdefault(str(chat_id), set()).remove(enable) 49 | 50 | SESSION.delete(disabled) 51 | SESSION.commit() 52 | return True 53 | 54 | SESSION.close() 55 | return False 56 | 57 | 58 | def is_command_disabled(chat_id, cmd): 59 | return str(cmd).lower() in DISABLED.get(str(chat_id), set()) 60 | 61 | 62 | def get_all_disabled(chat_id): 63 | return DISABLED.get(str(chat_id), set()) 64 | 65 | 66 | def num_chats(): 67 | try: 68 | return SESSION.query(func.count(distinct(Disable.chat_id))).scalar() 69 | finally: 70 | SESSION.close() 71 | 72 | 73 | def num_disabled(): 74 | try: 75 | return SESSION.query(Disable).count() 76 | finally: 77 | SESSION.close() 78 | 79 | 80 | def migrate_chat(old_chat_id, new_chat_id): 81 | with DISABLE_INSERTION_LOCK: 82 | chats = SESSION.query(Disable).filter(Disable.chat_id == str(old_chat_id)).all() 83 | for chat in chats: 84 | chat.chat_id = str(new_chat_id) 85 | SESSION.add(chat) 86 | 87 | if str(old_chat_id) in DISABLED: 88 | DISABLED[str(new_chat_id)] = DISABLED.get(str(old_chat_id), set()) 89 | 90 | SESSION.commit() 91 | 92 | 93 | def __load_disabled_commands(): 94 | global DISABLED 95 | try: 96 | all_chats = SESSION.query(Disable).all() 97 | for chat in all_chats: 98 | DISABLED.setdefault(chat.chat_id, set()).add(chat.command) 99 | 100 | finally: 101 | SESSION.close() 102 | 103 | 104 | __load_disabled_commands() 105 | -------------------------------------------------------------------------------- /LaylaRobot/modules/sql/global_bans_sql.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | from LaylaRobot.modules.sql import BASE, SESSION 4 | from sqlalchemy import Boolean, Column, Integer, String, UnicodeText 5 | 6 | 7 | class GloballyBannedUsers(BASE): 8 | __tablename__ = "gbans" 9 | user_id = Column(Integer, primary_key=True) 10 | name = Column(UnicodeText, nullable=False) 11 | reason = Column(UnicodeText) 12 | 13 | def __init__(self, user_id, name, reason=None): 14 | self.user_id = user_id 15 | self.name = name 16 | self.reason = reason 17 | 18 | def __repr__(self): 19 | return "".format(self.name, self.user_id) 20 | 21 | def to_dict(self): 22 | return {"user_id": self.user_id, "name": self.name, "reason": self.reason} 23 | 24 | 25 | class GbanSettings(BASE): 26 | __tablename__ = "gban_settings" 27 | chat_id = Column(String(14), primary_key=True) 28 | setting = Column(Boolean, default=True, nullable=False) 29 | 30 | def __init__(self, chat_id, enabled): 31 | self.chat_id = str(chat_id) 32 | self.setting = enabled 33 | 34 | def __repr__(self): 35 | return "".format(self.chat_id, self.setting) 36 | 37 | 38 | GloballyBannedUsers.__table__.create(checkfirst=True) 39 | GbanSettings.__table__.create(checkfirst=True) 40 | 41 | GBANNED_USERS_LOCK = threading.RLock() 42 | GBAN_SETTING_LOCK = threading.RLock() 43 | GBANNED_LIST = set() 44 | GBANSTAT_LIST = set() 45 | 46 | 47 | def gban_user(user_id, name, reason=None): 48 | with GBANNED_USERS_LOCK: 49 | user = SESSION.query(GloballyBannedUsers).get(user_id) 50 | if not user: 51 | user = GloballyBannedUsers(user_id, name, reason) 52 | else: 53 | user.name = name 54 | user.reason = reason 55 | 56 | SESSION.merge(user) 57 | SESSION.commit() 58 | __load_gbanned_userid_list() 59 | 60 | 61 | def update_gban_reason(user_id, name, reason=None): 62 | with GBANNED_USERS_LOCK: 63 | user = SESSION.query(GloballyBannedUsers).get(user_id) 64 | if not user: 65 | return None 66 | old_reason = user.reason 67 | user.name = name 68 | user.reason = reason 69 | 70 | SESSION.merge(user) 71 | SESSION.commit() 72 | return old_reason 73 | 74 | 75 | def ungban_user(user_id): 76 | with GBANNED_USERS_LOCK: 77 | user = SESSION.query(GloballyBannedUsers).get(user_id) 78 | if user: 79 | SESSION.delete(user) 80 | 81 | SESSION.commit() 82 | __load_gbanned_userid_list() 83 | 84 | 85 | def is_user_gbanned(user_id): 86 | return user_id in GBANNED_LIST 87 | 88 | 89 | def get_gbanned_user(user_id): 90 | try: 91 | return SESSION.query(GloballyBannedUsers).get(user_id) 92 | finally: 93 | SESSION.close() 94 | 95 | 96 | def get_gban_list(): 97 | try: 98 | return [x.to_dict() for x in SESSION.query(GloballyBannedUsers).all()] 99 | finally: 100 | SESSION.close() 101 | 102 | 103 | def enable_gbans(chat_id): 104 | with GBAN_SETTING_LOCK: 105 | chat = SESSION.query(GbanSettings).get(str(chat_id)) 106 | if not chat: 107 | chat = GbanSettings(chat_id, True) 108 | 109 | chat.setting = True 110 | SESSION.add(chat) 111 | SESSION.commit() 112 | if str(chat_id) in GBANSTAT_LIST: 113 | GBANSTAT_LIST.remove(str(chat_id)) 114 | 115 | 116 | def disable_gbans(chat_id): 117 | with GBAN_SETTING_LOCK: 118 | chat = SESSION.query(GbanSettings).get(str(chat_id)) 119 | if not chat: 120 | chat = GbanSettings(chat_id, False) 121 | 122 | chat.setting = False 123 | SESSION.add(chat) 124 | SESSION.commit() 125 | GBANSTAT_LIST.add(str(chat_id)) 126 | 127 | 128 | def does_chat_gban(chat_id): 129 | return str(chat_id) not in GBANSTAT_LIST 130 | 131 | 132 | def num_gbanned_users(): 133 | return len(GBANNED_LIST) 134 | 135 | 136 | def __load_gbanned_userid_list(): 137 | global GBANNED_LIST 138 | try: 139 | GBANNED_LIST = {x.user_id for x in SESSION.query(GloballyBannedUsers).all()} 140 | finally: 141 | SESSION.close() 142 | 143 | 144 | def __load_gban_stat_list(): 145 | global GBANSTAT_LIST 146 | try: 147 | GBANSTAT_LIST = { 148 | x.chat_id for x in SESSION.query(GbanSettings).all() if not x.setting 149 | } 150 | finally: 151 | SESSION.close() 152 | 153 | 154 | def migrate_chat(old_chat_id, new_chat_id): 155 | with GBAN_SETTING_LOCK: 156 | chat = SESSION.query(GbanSettings).get(str(old_chat_id)) 157 | if chat: 158 | chat.chat_id = new_chat_id 159 | SESSION.add(chat) 160 | 161 | SESSION.commit() 162 | 163 | 164 | # Create in memory userid to avoid disk access 165 | __load_gbanned_userid_list() 166 | __load_gban_stat_list() 167 | -------------------------------------------------------------------------------- /LaylaRobot/modules/sql/log_channel_sql.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | from LaylaRobot.modules.sql import BASE, SESSION 4 | from sqlalchemy import Column, String, distinct, func 5 | 6 | 7 | class GroupLogs(BASE): 8 | __tablename__ = "log_channels" 9 | chat_id = Column(String(14), primary_key=True) 10 | log_channel = Column(String(14), nullable=False) 11 | 12 | def __init__(self, chat_id, log_channel): 13 | self.chat_id = str(chat_id) 14 | self.log_channel = str(log_channel) 15 | 16 | 17 | GroupLogs.__table__.create(checkfirst=True) 18 | 19 | LOGS_INSERTION_LOCK = threading.RLock() 20 | 21 | CHANNELS = {} 22 | 23 | 24 | def set_chat_log_channel(chat_id, log_channel): 25 | with LOGS_INSERTION_LOCK: 26 | res = SESSION.query(GroupLogs).get(str(chat_id)) 27 | if res: 28 | res.log_channel = log_channel 29 | else: 30 | res = GroupLogs(chat_id, log_channel) 31 | SESSION.add(res) 32 | 33 | CHANNELS[str(chat_id)] = log_channel 34 | SESSION.commit() 35 | 36 | 37 | def get_chat_log_channel(chat_id): 38 | return CHANNELS.get(str(chat_id)) 39 | 40 | 41 | def stop_chat_logging(chat_id): 42 | with LOGS_INSERTION_LOCK: 43 | res = SESSION.query(GroupLogs).get(str(chat_id)) 44 | if res: 45 | if str(chat_id) in CHANNELS: 46 | del CHANNELS[str(chat_id)] 47 | 48 | log_channel = res.log_channel 49 | SESSION.delete(res) 50 | SESSION.commit() 51 | return log_channel 52 | 53 | 54 | def num_logchannels(): 55 | try: 56 | return SESSION.query(func.count(distinct(GroupLogs.chat_id))).scalar() 57 | finally: 58 | SESSION.close() 59 | 60 | 61 | def migrate_chat(old_chat_id, new_chat_id): 62 | with LOGS_INSERTION_LOCK: 63 | chat = SESSION.query(GroupLogs).get(str(old_chat_id)) 64 | if chat: 65 | chat.chat_id = str(new_chat_id) 66 | SESSION.add(chat) 67 | if str(old_chat_id) in CHANNELS: 68 | CHANNELS[str(new_chat_id)] = CHANNELS.get(str(old_chat_id)) 69 | 70 | SESSION.commit() 71 | 72 | 73 | def __load_log_channels(): 74 | global CHANNELS 75 | try: 76 | all_chats = SESSION.query(GroupLogs).all() 77 | CHANNELS = {chat.chat_id: chat.log_channel for chat in all_chats} 78 | finally: 79 | SESSION.close() 80 | 81 | 82 | __load_log_channels() 83 | -------------------------------------------------------------------------------- /LaylaRobot/modules/sql/nsfw_sql.py: -------------------------------------------------------------------------------- 1 | import threading 2 | from sqlalchemy import Column, String 3 | from LaylaRobot.modules.sql import BASE, SESSION 4 | # |----------------------------------| 5 | # | Test Module by @EverythingSuckz | 6 | # | Kang with Credits | 7 | # |----------------------------------| 8 | class NSFWChats(BASE): 9 | __tablename__ = "nsfw_chats" 10 | chat_id = Column(String(14), primary_key=True) 11 | 12 | def __init__(self, chat_id): 13 | self.chat_id = chat_id 14 | 15 | NSFWChats.__table__.create(checkfirst=True) 16 | INSERTION_LOCK = threading.RLock() 17 | 18 | 19 | def is_nsfw(chat_id): 20 | try: 21 | chat = SESSION.query(NSFWChats).get(str(chat_id)) 22 | if chat: 23 | return True 24 | else: 25 | return False 26 | finally: 27 | SESSION.close() 28 | 29 | def set_nsfw(chat_id): 30 | with INSERTION_LOCK: 31 | nsfwchat = SESSION.query(NSFWChats).get(str(chat_id)) 32 | if not nsfwchat: 33 | nsfwchat = NSFWChats(str(chat_id)) 34 | SESSION.add(nsfwchat) 35 | SESSION.commit() 36 | 37 | def rem_nsfw(chat_id): 38 | with INSERTION_LOCK: 39 | nsfwchat = SESSION.query(NSFWChats).get(str(chat_id)) 40 | if nsfwchat: 41 | SESSION.delete(nsfwchat) 42 | SESSION.commit() 43 | 44 | 45 | def get_all_nsfw_chats(): 46 | try: 47 | return SESSION.query(NSFWChats.chat_id).all() 48 | finally: 49 | SESSION.close() 50 | -------------------------------------------------------------------------------- /LaylaRobot/modules/sql/reporting_sql.py: -------------------------------------------------------------------------------- 1 | import threading 2 | from typing import Union 3 | 4 | from LaylaRobot.modules.sql import BASE, SESSION 5 | from sqlalchemy import Boolean, Column, Integer, String 6 | 7 | 8 | class ReportingUserSettings(BASE): 9 | __tablename__ = "user_report_settings" 10 | user_id = Column(Integer, primary_key=True) 11 | should_report = Column(Boolean, default=True) 12 | 13 | def __init__(self, user_id): 14 | self.user_id = user_id 15 | 16 | def __repr__(self): 17 | return "".format(self.user_id) 18 | 19 | 20 | class ReportingChatSettings(BASE): 21 | __tablename__ = "chat_report_settings" 22 | chat_id = Column(String(14), primary_key=True) 23 | should_report = Column(Boolean, default=True) 24 | 25 | def __init__(self, chat_id): 26 | self.chat_id = str(chat_id) 27 | 28 | def __repr__(self): 29 | return "".format(self.chat_id) 30 | 31 | 32 | ReportingUserSettings.__table__.create(checkfirst=True) 33 | ReportingChatSettings.__table__.create(checkfirst=True) 34 | 35 | CHAT_LOCK = threading.RLock() 36 | USER_LOCK = threading.RLock() 37 | 38 | 39 | def chat_should_report(chat_id: Union[str, int]) -> bool: 40 | try: 41 | chat_setting = SESSION.query(ReportingChatSettings).get(str(chat_id)) 42 | if chat_setting: 43 | return chat_setting.should_report 44 | return False 45 | finally: 46 | SESSION.close() 47 | 48 | 49 | def user_should_report(user_id: int) -> bool: 50 | try: 51 | user_setting = SESSION.query(ReportingUserSettings).get(user_id) 52 | if user_setting: 53 | return user_setting.should_report 54 | return True 55 | finally: 56 | SESSION.close() 57 | 58 | 59 | def set_chat_setting(chat_id: Union[int, str], setting: bool): 60 | with CHAT_LOCK: 61 | chat_setting = SESSION.query(ReportingChatSettings).get(str(chat_id)) 62 | if not chat_setting: 63 | chat_setting = ReportingChatSettings(chat_id) 64 | 65 | chat_setting.should_report = setting 66 | SESSION.add(chat_setting) 67 | SESSION.commit() 68 | 69 | 70 | def set_user_setting(user_id: int, setting: bool): 71 | with USER_LOCK: 72 | user_setting = SESSION.query(ReportingUserSettings).get(user_id) 73 | if not user_setting: 74 | user_setting = ReportingUserSettings(user_id) 75 | 76 | user_setting.should_report = setting 77 | SESSION.add(user_setting) 78 | SESSION.commit() 79 | 80 | 81 | def migrate_chat(old_chat_id, new_chat_id): 82 | with CHAT_LOCK: 83 | chat_notes = ( 84 | SESSION.query(ReportingChatSettings) 85 | .filter(ReportingChatSettings.chat_id == str(old_chat_id)) 86 | .all() 87 | ) 88 | for note in chat_notes: 89 | note.chat_id = str(new_chat_id) 90 | SESSION.commit() 91 | -------------------------------------------------------------------------------- /LaylaRobot/modules/sql/rss_sql.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | from LaylaRobot.modules.sql import BASE, SESSION 4 | from sqlalchemy import Column, Integer, UnicodeText 5 | 6 | 7 | class RSS(BASE): 8 | __tablename__ = "rss_feed" 9 | id = Column(Integer, primary_key=True) 10 | chat_id = Column(UnicodeText, nullable=False) 11 | feed_link = Column(UnicodeText) 12 | old_entry_link = Column(UnicodeText) 13 | 14 | def __init__(self, chat_id, feed_link, old_entry_link): 15 | self.chat_id = chat_id 16 | self.feed_link = feed_link 17 | self.old_entry_link = old_entry_link 18 | 19 | def __repr__(self): 20 | return "".format( 21 | self.chat_id, self.feed_link, self.old_entry_link 22 | ) 23 | 24 | 25 | RSS.__table__.create(checkfirst=True) 26 | INSERTION_LOCK = threading.RLock() 27 | 28 | 29 | def check_url_availability(tg_chat_id, tg_feed_link): 30 | try: 31 | return ( 32 | SESSION.query(RSS) 33 | .filter(RSS.feed_link == tg_feed_link, RSS.chat_id == tg_chat_id) 34 | .all() 35 | ) 36 | finally: 37 | SESSION.close() 38 | 39 | 40 | def add_url(tg_chat_id, tg_feed_link, tg_old_entry_link): 41 | with INSERTION_LOCK: 42 | action = RSS(tg_chat_id, tg_feed_link, tg_old_entry_link) 43 | 44 | SESSION.add(action) 45 | SESSION.commit() 46 | 47 | 48 | def remove_url(tg_chat_id, tg_feed_link): 49 | with INSERTION_LOCK: 50 | # this loops to delete any possible duplicates for the same TG User ID, TG Chat ID and link 51 | for row in check_url_availability(tg_chat_id, tg_feed_link): 52 | # add the action to the DB query 53 | SESSION.delete(row) 54 | 55 | SESSION.commit() 56 | 57 | 58 | def get_urls(tg_chat_id): 59 | try: 60 | return SESSION.query(RSS).filter(RSS.chat_id == tg_chat_id).all() 61 | finally: 62 | SESSION.close() 63 | 64 | 65 | def get_all(): 66 | try: 67 | return SESSION.query(RSS).all() 68 | finally: 69 | SESSION.close() 70 | 71 | 72 | def update_url(row_id, new_entry_links): 73 | with INSERTION_LOCK: 74 | row = SESSION.query(RSS).get(row_id) 75 | 76 | # set the new old_entry_link with the latest update from the RSS Feed 77 | row.old_entry_link = new_entry_links[0] 78 | 79 | # commit the changes to the DB 80 | SESSION.commit() 81 | -------------------------------------------------------------------------------- /LaylaRobot/modules/sql/rules_sql.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | from LaylaRobot.modules.sql import BASE, SESSION 4 | from sqlalchemy import Column, String, UnicodeText, distinct, func 5 | 6 | 7 | class Rules(BASE): 8 | __tablename__ = "rules" 9 | chat_id = Column(String(14), primary_key=True) 10 | rules = Column(UnicodeText, default="") 11 | 12 | def __init__(self, chat_id): 13 | self.chat_id = chat_id 14 | 15 | def __repr__(self): 16 | return "".format(self.chat_id, self.rules) 17 | 18 | 19 | Rules.__table__.create(checkfirst=True) 20 | 21 | INSERTION_LOCK = threading.RLock() 22 | 23 | 24 | def set_rules(chat_id, rules_text): 25 | with INSERTION_LOCK: 26 | rules = SESSION.query(Rules).get(str(chat_id)) 27 | if not rules: 28 | rules = Rules(str(chat_id)) 29 | rules.rules = rules_text 30 | 31 | SESSION.add(rules) 32 | SESSION.commit() 33 | 34 | 35 | def get_rules(chat_id): 36 | rules = SESSION.query(Rules).get(str(chat_id)) 37 | ret = "" 38 | if rules: 39 | ret = rules.rules 40 | 41 | SESSION.close() 42 | return ret 43 | 44 | 45 | def num_chats(): 46 | try: 47 | return SESSION.query(func.count(distinct(Rules.chat_id))).scalar() 48 | finally: 49 | SESSION.close() 50 | 51 | 52 | def migrate_chat(old_chat_id, new_chat_id): 53 | with INSERTION_LOCK: 54 | chat = SESSION.query(Rules).get(str(old_chat_id)) 55 | if chat: 56 | chat.chat_id = str(new_chat_id) 57 | SESSION.commit() 58 | -------------------------------------------------------------------------------- /LaylaRobot/modules/sql/userinfo_sql.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | from LaylaRobot.modules.sql import BASE, SESSION 4 | from sqlalchemy import Column, Integer, UnicodeText 5 | 6 | 7 | class UserInfo(BASE): 8 | __tablename__ = "userinfo" 9 | user_id = Column(Integer, primary_key=True) 10 | info = Column(UnicodeText) 11 | 12 | def __init__(self, user_id, info): 13 | self.user_id = user_id 14 | self.info = info 15 | 16 | def __repr__(self): 17 | return "" % self.user_id 18 | 19 | 20 | class UserBio(BASE): 21 | __tablename__ = "userbio" 22 | user_id = Column(Integer, primary_key=True) 23 | bio = Column(UnicodeText) 24 | 25 | def __init__(self, user_id, bio): 26 | self.user_id = user_id 27 | self.bio = bio 28 | 29 | def __repr__(self): 30 | return "" % self.user_id 31 | 32 | 33 | UserInfo.__table__.create(checkfirst=True) 34 | UserBio.__table__.create(checkfirst=True) 35 | 36 | INSERTION_LOCK = threading.RLock() 37 | 38 | 39 | def get_user_me_info(user_id): 40 | userinfo = SESSION.query(UserInfo).get(user_id) 41 | SESSION.close() 42 | if userinfo: 43 | return userinfo.info 44 | return None 45 | 46 | 47 | def set_user_me_info(user_id, info): 48 | with INSERTION_LOCK: 49 | userinfo = SESSION.query(UserInfo).get(user_id) 50 | if userinfo: 51 | userinfo.info = info 52 | else: 53 | userinfo = UserInfo(user_id, info) 54 | SESSION.add(userinfo) 55 | SESSION.commit() 56 | 57 | 58 | def get_user_bio(user_id): 59 | userbio = SESSION.query(UserBio).get(user_id) 60 | SESSION.close() 61 | if userbio: 62 | return userbio.bio 63 | return None 64 | 65 | 66 | def set_user_bio(user_id, bio): 67 | with INSERTION_LOCK: 68 | userbio = SESSION.query(UserBio).get(user_id) 69 | if userbio: 70 | userbio.bio = bio 71 | else: 72 | userbio = UserBio(user_id, bio) 73 | 74 | SESSION.add(userbio) 75 | SESSION.commit() 76 | -------------------------------------------------------------------------------- /LaylaRobot/modules/sql_extended/forceSubscribe_sql.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import Column, String, Numeric, Boolean 2 | from LaylaRobot.modules.sql import BASE, SESSION 3 | 4 | 5 | class forceSubscribe(BASE): 6 | __tablename__ = "forceSubscribe" 7 | chat_id = Column(Numeric, primary_key=True) 8 | channel = Column(String) 9 | 10 | def __init__(self, chat_id, channel): 11 | self.chat_id = chat_id 12 | self.channel = channel 13 | 14 | 15 | forceSubscribe.__table__.create(checkfirst=True) 16 | 17 | 18 | def fs_settings(chat_id): 19 | try: 20 | return SESSION.query(forceSubscribe).filter(forceSubscribe.chat_id == chat_id).one() 21 | except: 22 | return None 23 | finally: 24 | SESSION.close() 25 | 26 | 27 | def add_channel(chat_id, channel): 28 | adder = SESSION.query(forceSubscribe).get(chat_id) 29 | if adder: 30 | adder.channel = channel 31 | else: 32 | adder = forceSubscribe( 33 | chat_id, 34 | channel 35 | ) 36 | SESSION.add(adder) 37 | SESSION.commit() 38 | 39 | def disapprove(chat_id): 40 | rem = SESSION.query(forceSubscribe).get(chat_id) 41 | if rem: 42 | SESSION.delete(rem) 43 | SESSION.commit() -------------------------------------------------------------------------------- /LaylaRobot/modules/sql_extended/night_mode_sql.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import Boolean, Column, Integer, String, UnicodeText 2 | from LaylaRobot.modules.sql import BASE, SESSION 3 | 4 | 5 | class Nightmode(BASE): 6 | __tablename__ = "nightmode" 7 | chat_id = Column(String(14), primary_key=True) 8 | 9 | def __init__(self, chat_id): 10 | self.chat_id = chat_id 11 | 12 | 13 | Nightmode.__table__.create(checkfirst=True) 14 | 15 | 16 | def add_nightmode(chat_id: str): 17 | nightmoddy = Nightmode(str(chat_id)) 18 | SESSION.add(nightmoddy) 19 | SESSION.commit() 20 | 21 | 22 | def rmnightmode(chat_id: str): 23 | rmnightmoddy = SESSION.query(Nightmode).get(str(chat_id)) 24 | if rmnightmoddy: 25 | SESSION.delete(rmnightmoddy) 26 | SESSION.commit() 27 | 28 | 29 | def get_all_chat_id(): 30 | stark = SESSION.query(Nightmode).all() 31 | SESSION.close() 32 | return stark 33 | 34 | 35 | def is_nightmode_indb(chat_id: str): 36 | try: 37 | s__ = SESSION.query(Nightmode).get(str(chat_id)) 38 | if s__: 39 | return str(s__.chat_id) 40 | finally: 41 | SESSION.close() 42 | -------------------------------------------------------------------------------- /LaylaRobot/modules/sql_extended/nsfw_watch_sql.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Midhun KM 2020-2021 2 | # This program is free software: you can redistribute it and/or modify 3 | # it under the terms of the GNU Affero General Public License as published by 4 | # the Free Software Foundation, either version 3 of the License, or 5 | # 6 | # This program is distributed in the hope that it will be useful, 7 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 | # GNU Affero General Public License for more details. 10 | # 11 | # You should have received a copy of the GNU Affero General Public License 12 | # along with this program. If not, see . 13 | 14 | from sqlalchemy import Column, String 15 | 16 | from LaylaRobot.modules.sql import BASE, SESSION 17 | 18 | 19 | class Nsfwatch(BASE): 20 | __tablename__ = "nsfwatch" 21 | chat_id = Column(String(14), primary_key=True) 22 | 23 | def __init__(self, chat_id): 24 | self.chat_id = chat_id 25 | 26 | 27 | Nsfwatch.__table__.create(checkfirst=True) 28 | 29 | 30 | def add_nsfwatch(chat_id: str): 31 | nsfws = Nsfwatch(str(chat_id)) 32 | SESSION.add(nsfws) 33 | SESSION.commit() 34 | 35 | 36 | def rmnsfwatch(chat_id: str): 37 | nsfwm = SESSION.query(Nsfwatch).get(str(chat_id)) 38 | if nsfwm: 39 | SESSION.delete(nsfwm) 40 | SESSION.commit() 41 | 42 | 43 | def get_all_nsfw_enabled_chat(): 44 | stark = SESSION.query(Nsfwatch).all() 45 | SESSION.close() 46 | return stark 47 | 48 | 49 | def is_nsfwatch_indb(chat_id: str): 50 | try: 51 | s__ = SESSION.query(Nsfwatch).get(str(chat_id)) 52 | if s__: 53 | return str(s__.chat_id) 54 | finally: 55 | SESSION.close() -------------------------------------------------------------------------------- /LaylaRobot/modules/tagall.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020-2021 by DevsExpo@Github, < https://github.com/DevsExpo >. 2 | # 3 | # This file is part of < https://github.com/DevsExpo/FridayUserBot > project, 4 | # and is released under the "GNU v3.0 License Agreement". 5 | # Please see < https://github.com/DevsExpo/blob/master/LICENSE > 6 | # 7 | # All rights reserved. 8 | 9 | 10 | from pyrogram import filters 11 | 12 | from LaylaRobot.pyrogramee.pluginshelper import admins_only, get_text 13 | from LaylaRobot import pbot 14 | 15 | 16 | @pbot.on_message(filters.command("tagall") & ~filters.edited & ~filters.bot) 17 | @admins_only 18 | async def tagall(client, message): 19 | await message.reply("`Processing.....`") 20 | sh = get_text(message) 21 | if not sh: 22 | sh = "Hi!" 23 | mentions = "" 24 | async for member in client.iter_chat_members(message.chat.id): 25 | mentions += member.user.mention + " " 26 | n = 4096 27 | kk = [mentions[i : i + n] for i in range(0, len(mentions), n)] 28 | for i in kk: 29 | j = f"{sh} \n{i}" 30 | await client.send_message(message.chat.id, j, parse_mode="html") 31 | 32 | 33 | __mod_name__ = "Tagall" 34 | __help__ = """ 35 | - /tagall : Tag everyone in a chat 36 | """ -------------------------------------------------------------------------------- /LaylaRobot/modules/truth_and_dare.py: -------------------------------------------------------------------------------- 1 | import html 2 | import random 3 | import LaylaRobot.modules.truth_and_dare_string as truth_and_dare_string 4 | from LaylaRobot import dispatcher 5 | from telegram import ParseMode, Update, Bot 6 | from LaylaRobot.modules.disable import DisableAbleCommandHandler 7 | from telegram.ext import CallbackContext, run_async 8 | 9 | @run_async 10 | def truth(update: Update, context: CallbackContext): 11 | args = context.args 12 | update.effective_message.reply_text(random.choice(truth_and_dare_string.TRUTH)) 13 | 14 | @run_async 15 | def dare(update: Update, context: CallbackContext): 16 | args = context.args 17 | update.effective_message.reply_text(random.choice(truth_and_dare_string.DARE)) 18 | 19 | 20 | TRUTH_HANDLER = DisableAbleCommandHandler("truth", truth) 21 | DARE_HANDLER = DisableAbleCommandHandler("dare", dare) 22 | 23 | 24 | dispatcher.add_handler(TRUTH_HANDLER) 25 | dispatcher.add_handler(DARE_HANDLER) 26 | 27 | -------------------------------------------------------------------------------- /LaylaRobot/modules/truth_and_dare_string.py: -------------------------------------------------------------------------------- 1 | TRUTH = ( 2 | "Have you ghosted someone?" 3 | "Have you ever walked in on your parents doing 'it'?", 4 | "Who was the last person you liked the most? Why?", 5 | "Have you ever been suspended from school?", 6 | "If you had to choose between going naked or having your thoughts appear in thought bubbles above your head for everyone to read, which would you choose?", 7 | "What’s the one thing you’re afraid to lose?", 8 | "Do you like someone as of the moment?", 9 | "One thing about your best friend you are jealous of?", 10 | "Would you cheat on your boyfriend for a rich guy?", 11 | "What is your biggest turn on?", 12 | "When’s the last time you lied to your parents and why?", 13 | "Describe your ideal partner.", 14 | "What’s the scariest thing you’ve ever done?", 15 | "Have you ever picked your nose and eaten it?", 16 | "When’s the last time you lied to your parents and why?", 17 | "Have you ever lied about your age to participate in a contest?", 18 | "Have you ever been caught checking someone out?", 19 | 20 | ) 21 | 22 | DARE = ( 23 | "Show the most embarrassing photo on your phone" 24 | "Show the last five people you texted and what the messages said", 25 | "Let the rest of the group DM someone from your Instagram account", 26 | "Eat a raw piece of garlic", 27 | "Do 100 squats", 28 | "Keep three ice cubes in your mouth until they melt", 29 | "Say something dirty to the person on your leftYou've got company!", 30 | "Give a foot massage to the person on your right", 31 | "Put 10 different available liquids into a cup and drink it", 32 | "*Yell out the first word that comes to your mind", 33 | "Give a lap dance to someone of your choice", 34 | "Remove four items of clothing", 35 | "Like the first 15 posts on your Facebook newsfeed", 36 | "Eat a spoonful of mustard", 37 | "Keep your eyes closed until it's your go again", 38 | "Send a sext to the last person in your phonebook", 39 | "Show off your orgasm face", 40 | "Seductively eat a banana", 41 | "Empty out your wallet/purse and show everyone what's inside", 42 | "Do your best sexy crawl", 43 | "Pretend to be the person to your right for 10 minutes", 44 | "Eat a snack without using your hands", 45 | "Say two honest things about everyone else in the group", 46 | "Twerk for a minute", 47 | "Try and make the group laugh as quickly as possible", 48 | "Try to put your whole fist in your mouth", 49 | "Tell everyone an embarrassing story about yourself", 50 | "Try to lick your elbow", 51 | "Post the oldest selfie on your phone on Instagram Stories", 52 | "Tell the saddest story you know", 53 | "Howl like a wolf for two minutes", 54 | "Dance without music for two minutes", 55 | "Pole dance with an imaginary pole", 56 | "Let someone else tickle you and try not to laugh", 57 | "Put as many snacks into your mouth at once as you can", 58 | "Send your most recent selfie.", 59 | "Send your ugliest selfie.", 60 | "Send a screenshot of your facebook search history", 61 | "Send a screenshot of your gallery.", 62 | "Send a screenshot of your messenger inbox", 63 | "Tell something very intimate.", 64 | "Send a screenshot of your twitter inbox", 65 | "Send a screenshot of your homescreen.", 66 | "Send a cover of your favorite song. 🎤", 67 | "Do a lyric prank on someone and send proof.", 68 | "Confess to your current crush. ❤️", 69 | "Declare who is your true love.", 70 | "Send a screenshot of your gallery.", 71 | "Set your crush’s picture as your dp.", 72 | "Suggest me more dares.", 73 | ) 74 | -------------------------------------------------------------------------------- /LaylaRobot/modules/ud.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from LaylaRobot import dispatcher 3 | from LaylaRobot.modules.disable import DisableAbleCommandHandler 4 | from telegram import ParseMode, Update 5 | from telegram.ext import CallbackContext, run_async 6 | 7 | 8 | @run_async 9 | def ud(update: Update, context: CallbackContext): 10 | message = update.effective_message 11 | text = message.text[len("/ud ") :] 12 | results = requests.get( 13 | f"https://api.urbandictionary.com/v0/define?term={text}" 14 | ).json() 15 | try: 16 | reply_text = f'*{text}*\n\n{results["list"][0]["definition"]}\n\n_{results["list"][0]["example"]}_' 17 | except: 18 | reply_text = "No results found." 19 | message.reply_text(reply_text, parse_mode=ParseMode.MARKDOWN) 20 | 21 | 22 | UD_HANDLER = DisableAbleCommandHandler(["ud"], ud) 23 | 24 | dispatcher.add_handler(UD_HANDLER) 25 | 26 | __command_list__ = ["ud"] 27 | __handlers__ = [UD_HANDLER] 28 | -------------------------------------------------------------------------------- /LaylaRobot/modules/wallpaper.py: -------------------------------------------------------------------------------- 1 | from random import randint 2 | 3 | import requests as r 4 | from LaylaRobot import SUPPORT_CHAT, WALL_API, dispatcher 5 | from LaylaRobot.modules.disable import DisableAbleCommandHandler 6 | from telegram import Update 7 | from telegram.ext import CallbackContext, run_async 8 | 9 | # Wallpapers module by @TheRealPhoenix using wall.alphacoders.com 10 | 11 | 12 | @run_async 13 | def wall(update: Update, context: CallbackContext): 14 | chat_id = update.effective_chat.id 15 | msg = update.effective_message 16 | args = context.args 17 | msg_id = update.effective_message.message_id 18 | bot = context.bot 19 | query = " ".join(args) 20 | if not query: 21 | msg.reply_text("Please enter a query!") 22 | return 23 | else: 24 | caption = query 25 | term = query.replace(" ", "%20") 26 | json_rep = r.get( 27 | f"https://wall.alphacoders.com/api2.0/get.php?auth={WALL_API}&method=search&term={term}" 28 | ).json() 29 | if not json_rep.get("success"): 30 | msg.reply_text(f"An error occurred! Report this @{SUPPORT_CHAT}") 31 | else: 32 | wallpapers = json_rep.get("wallpapers") 33 | if not wallpapers: 34 | msg.reply_text("No results found! Refine your search.") 35 | return 36 | else: 37 | index = randint(0, len(wallpapers) - 1) # Choose random index 38 | wallpaper = wallpapers[index] 39 | wallpaper = wallpaper.get("url_image") 40 | wallpaper = wallpaper.replace("\\", "") 41 | bot.send_photo( 42 | chat_id, 43 | photo=wallpaper, 44 | caption="Preview", 45 | reply_to_message_id=msg_id, 46 | timeout=60, 47 | ) 48 | bot.send_document( 49 | chat_id, 50 | document=wallpaper, 51 | filename="wallpaper", 52 | caption=caption, 53 | reply_to_message_id=msg_id, 54 | timeout=60, 55 | ) 56 | 57 | 58 | WALLPAPER_HANDLER = DisableAbleCommandHandler("wall", wall) 59 | dispatcher.add_handler(WALLPAPER_HANDLER) 60 | -------------------------------------------------------------------------------- /LaylaRobot/modules/wiki.py: -------------------------------------------------------------------------------- 1 | import wikipedia 2 | from LaylaRobot import dispatcher 3 | from LaylaRobot.modules.disable import DisableAbleCommandHandler 4 | from telegram import ParseMode, Update 5 | from telegram.ext import CallbackContext, run_async 6 | from wikipedia.exceptions import DisambiguationError, PageError 7 | 8 | 9 | @run_async 10 | def wiki(update: Update, context: CallbackContext): 11 | msg = ( 12 | update.effective_message.reply_to_message 13 | if update.effective_message.reply_to_message 14 | else update.effective_message 15 | ) 16 | res = "" 17 | if msg == update.effective_message: 18 | search = msg.text.split(" ", maxsplit=1)[1] 19 | else: 20 | search = msg.text 21 | try: 22 | res = wikipedia.summary(search) 23 | except DisambiguationError as e: 24 | update.message.reply_text( 25 | "Disambiguated pages found! Adjust your query accordingly.\n{}".format( 26 | e 27 | ), 28 | parse_mode=ParseMode.HTML, 29 | ) 30 | except PageError as e: 31 | update.message.reply_text( 32 | "{}".format(e), parse_mode=ParseMode.HTML 33 | ) 34 | if res: 35 | result = f"{search}\n\n" 36 | result += f"{res}\n" 37 | result += f"""Read more...""" 38 | if len(result) > 4000: 39 | with open("result.txt", "w") as f: 40 | f.write(f"{result}\n\nUwU OwO OmO UmU") 41 | with open("result.txt", "rb") as f: 42 | context.bot.send_document( 43 | document=f, 44 | filename=f.name, 45 | reply_to_message_id=update.message.message_id, 46 | chat_id=update.effective_chat.id, 47 | parse_mode=ParseMode.HTML, 48 | ) 49 | else: 50 | update.message.reply_text( 51 | result, parse_mode=ParseMode.HTML, disable_web_page_preview=True 52 | ) 53 | 54 | 55 | WIKI_HANDLER = DisableAbleCommandHandler("wiki", wiki) 56 | dispatcher.add_handler(WIKI_HANDLER) 57 | -------------------------------------------------------------------------------- /LaylaRobot/modules/zombies.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from asyncio import sleep 3 | 4 | from telethon import events 5 | from telethon.errors import ChatAdminRequiredError, UserAdminInvalidError 6 | from telethon.tl.functions.channels import EditBannedRequest 7 | from telethon.tl.types import ChatBannedRights, ChannelParticipantsAdmins 8 | 9 | from LaylaRobot import telethn, OWNER_ID, DEV_USERS, DRAGONS, DEMONS 10 | 11 | # =================== CONSTANT =================== 12 | 13 | BANNED_RIGHTS = ChatBannedRights( 14 | until_date=None, 15 | view_messages=True, 16 | send_messages=True, 17 | send_media=True, 18 | send_stickers=True, 19 | send_gifs=True, 20 | send_games=True, 21 | send_inline=True, 22 | embed_links=True, 23 | ) 24 | 25 | 26 | UNBAN_RIGHTS = ChatBannedRights( 27 | until_date=None, 28 | send_messages=None, 29 | send_media=None, 30 | send_stickers=None, 31 | send_gifs=None, 32 | send_games=None, 33 | send_inline=None, 34 | embed_links=None, 35 | ) 36 | 37 | OFFICERS = [OWNER_ID] + DEV_USERS + DRAGONS + DEMONS 38 | 39 | # Check if user has admin rights 40 | async def is_administrator(user_id: int, message): 41 | admin = False 42 | async for user in telethn.iter_participants( 43 | message.chat_id, filter=ChannelParticipantsAdmins 44 | ): 45 | if user_id == user.id or user_id in OFFICERS: 46 | admin = True 47 | break 48 | return admin 49 | 50 | 51 | 52 | @telethn.on(events.NewMessage(pattern=f"^[!/]zombies ?(.*)")) 53 | async def zombies(event): 54 | """ For .zombies command, list all the zombies in a chat. """ 55 | 56 | con = event.pattern_match.group(1).lower() 57 | del_u = 0 58 | del_status = "No Deleted Accounts Found, Group Is Clean." 59 | 60 | if con != "clean": 61 | find_zombies = await event.respond("Searching For Zombies...") 62 | async for user in event.client.iter_participants(event.chat_id): 63 | 64 | if user.deleted: 65 | del_u += 1 66 | await sleep(1) 67 | if del_u > 0: 68 | del_status = f"Found **{del_u}** Zombies In This Group.\ 69 | \nClean Them By Using - `/zombies clean`" 70 | await find_zombies.edit(del_status) 71 | return 72 | 73 | # Here laying the sanity check 74 | chat = await event.get_chat() 75 | admin = chat.admin_rights 76 | creator = chat.creator 77 | 78 | # Well 79 | if not await is_administrator(user_id=event.from_id, message=event): 80 | await event.respond("You're Not An Admin!") 81 | return 82 | 83 | if not admin and not creator: 84 | await event.respond("I Am Not An Admin Here!") 85 | return 86 | 87 | cleaning_zombies = await event.respond("Cleaning Zombies...") 88 | del_u = 0 89 | del_a = 0 90 | 91 | async for user in event.client.iter_participants(event.chat_id): 92 | if user.deleted: 93 | try: 94 | await event.client( 95 | EditBannedRequest(event.chat_id, user.id, BANNED_RIGHTS) 96 | ) 97 | except ChatAdminRequiredError: 98 | await cleaning_zombies.edit("I Don't Have Ban Rights In This Group.") 99 | return 100 | except UserAdminInvalidError: 101 | del_u -= 1 102 | del_a += 1 103 | await event.client(EditBannedRequest(event.chat_id, user.id, UNBAN_RIGHTS)) 104 | del_u += 1 105 | 106 | if del_u > 0: 107 | del_status = f"Cleaned `{del_u}` Zombies" 108 | 109 | if del_a > 0: 110 | del_status = f"Cleaned `{del_u}` Zombies \ 111 | \n`{del_a}` Zombie Admin Accounts Are Not Removed!" 112 | 113 | await cleaning_zombies.edit(del_status) 114 | 115 | 116 | from telethon.tl.types import UserStatusLastMonth, UserStatusLastWeek, ChatBannedRights 117 | from LaylaRobot.events import register 118 | from telethon import * 119 | from telethon.tl.functions.channels import (EditBannedRequest) 120 | 121 | 122 | @register(pattern="^/kickthefools") 123 | async def _(event): 124 | if event.fwd_from: 125 | return 126 | chat = await event.get_chat() 127 | admin = chat.admin_rights 128 | creator = chat.creator 129 | if not event.chat.admin_rights.ban_users: 130 | return 131 | if not admin and not creator: 132 | await event.reply("I am not admin here !") 133 | return 134 | c = 0 135 | KICK_RIGHTS = ChatBannedRights(until_date=None, view_messages=True) 136 | await event.reply("Searching Participant Lists...") 137 | async for i in event.client.iter_participants(event.chat_id): 138 | 139 | if isinstance(i.status, UserStatusLastMonth): 140 | status = await event.client(EditBannedRequest(event.chat_id, i, KICK_RIGHTS)) 141 | if not status: 142 | return 143 | else: 144 | c = c + 1 145 | 146 | if isinstance(i.status, UserStatusLastMonth): 147 | status = await event.client(EditBannedRequest(event.chat_id, i, KICK_RIGHTS)) 148 | if not status: 149 | return 150 | else: 151 | c = c + 1 152 | 153 | required_string = "Successfully Kicked **{}** users" 154 | await event.reply(required_string.format(c)) 155 | 156 | -------------------------------------------------------------------------------- /LaylaRobot/mongo.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import sys 3 | 4 | from motor import motor_asyncio 5 | from LaylaRobot import MONGO_DB_URI 6 | from pymongo import MongoClient 7 | from pymongo.errors import ServerSelectionTimeoutError 8 | from LaylaRobot.conf import get_int_key, get_str_key 9 | 10 | 11 | MONGO_PORT = get_int_key("27017") 12 | MONGO_DB_URI = get_str_key("MONGO_DB_URI") 13 | MONGO_DB = "DaisyX" 14 | 15 | 16 | client = MongoClient() 17 | client = MongoClient(MONGO_DB_URI, MONGO_PORT)[MONGO_DB] 18 | motor = motor_asyncio.AsyncIOMotorClient(MONGO_DB_URI, MONGO_PORT) 19 | db = motor[MONGO_DB] 20 | db = client["LaylaRobot"] 21 | try: 22 | asyncio.get_event_loop().run_until_complete(motor.server_info()) 23 | except ServerSelectionTimeoutError: 24 | sys.exit(log.critical("Can't connect to mongodb! Exiting...")) -------------------------------------------------------------------------------- /LaylaRobot/pyrogramee/dark.py: -------------------------------------------------------------------------------- 1 | def get_arg(message): 2 | msg = message.text 3 | msg = msg.replace(" ", "", 1) if msg[1] == " " else msg 4 | split = msg[1:].replace("\n", " \n").split(" ") 5 | if " ".join(split[1:]).strip() == "": 6 | return "" 7 | return " ".join(split[1:]) 8 | -------------------------------------------------------------------------------- /LaylaRobot/pyrogramee/errors.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import traceback 3 | from functools import wraps 4 | from LaylaRobot import pbot, SUPPORT_CHAT 5 | 6 | def split_limits(text): 7 | if len(text) < 2048: 8 | return [text] 9 | 10 | lines = text.splitlines(True) 11 | small_msg = '' 12 | result = [] 13 | for line in lines: 14 | if len(small_msg) + len(line) < 2048: 15 | small_msg += line 16 | else: 17 | result.append(small_msg) 18 | small_msg = line 19 | else: 20 | result.append(small_msg) 21 | 22 | return result 23 | 24 | def capture_err(func): 25 | @wraps(func) 26 | async def capture(client, message, *args, **kwargs): 27 | try: 28 | return await func(client, message, *args, **kwargs) 29 | except Exception as err: 30 | exc_type, exc_obj, exc_tb = sys.exc_info() 31 | errors = traceback.format_exception( 32 | etype=exc_type, value=exc_obj, tb=exc_tb, 33 | ) 34 | error_feedback = split_limits( 35 | '**ERROR** | `{}` | `{}`\n\n```{}```\n\n```{}```\n'.format( 36 | 0 if not message.from_user else message.from_user.id, 37 | 0 if not message.chat else message.chat.id, 38 | message.text or message.caption, 39 | ''.join(errors), 40 | ), 41 | ) 42 | for x in error_feedback: 43 | await pbot.send_message( 44 | SUPPORT_CHAT, 45 | x 46 | ) 47 | raise err 48 | return capture 49 | -------------------------------------------------------------------------------- /LaylaRobot/resources/Chopsic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shiv-x/LaylaRobot/a899ec54e1fa4048a1a71fdaedba14f9e679d8fb/LaylaRobot/resources/Chopsic.otf -------------------------------------------------------------------------------- /LaylaRobot/resources/Maghrib.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shiv-x/LaylaRobot/a899ec54e1fa4048a1a71fdaedba14f9e679d8fb/LaylaRobot/resources/Maghrib.ttf -------------------------------------------------------------------------------- /LaylaRobot/resources/blackbg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shiv-x/LaylaRobot/a899ec54e1fa4048a1a71fdaedba14f9e679d8fb/LaylaRobot/resources/blackbg.jpg -------------------------------------------------------------------------------- /LaylaRobot/resources/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shiv-x/LaylaRobot/a899ec54e1fa4048a1a71fdaedba14f9e679d8fb/LaylaRobot/resources/hero.png -------------------------------------------------------------------------------- /LaylaRobot/resources/images.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shiv-x/LaylaRobot/a899ec54e1fa4048a1a71fdaedba14f9e679d8fb/LaylaRobot/resources/images.jpeg -------------------------------------------------------------------------------- /LaylaRobot/sample_config.py: -------------------------------------------------------------------------------- 1 | # Create a new config.py or rename this to config.py file in same dir and import, then extend this class. 2 | import json 3 | import os 4 | 5 | 6 | def get_user_list(config, key): 7 | with open("{}/LaylaRobot/{}".format(os.getcwd(), config), "r") as json_file: 8 | return json.load(json_file)[key] 9 | 10 | 11 | # Create a new config.py or rename this to config.py file in same dir and import, then extend this class. 12 | class Config(object): 13 | LOGGER = True 14 | # REQUIRED 15 | # Login to https://my.telegram.org and fill in these slots with the details given by it 16 | 17 | API_ID = 123456 # integer value, dont use "" 18 | API_HASH = "awoo" 19 | TOKEN = "BOT_TOKEN" # This var used to be API_KEY but it is now TOKEN, adjust accordingly. 20 | OWNER_ID = 797768146 # If you dont know, run the bot and do /id in your private chat with it, also an integer 21 | OWNER_USERNAME = "HEROGAMERS1" 22 | SUPPORT_CHAT = "AwesomeSupport" # Your own group for support, do not add the @ 23 | JOIN_LOGGER = ( 24 | -1001392103597 25 | ) # Prints any new group the bot is added to, prints just the name and ID. 26 | EVENT_LOGS = ( 27 | -1001392103597 28 | ) # Prints information like gbans, sudo promotes, AI enabled disable states that may help in debugging and shit 29 | 30 | # RECOMMENDED 31 | SQLALCHEMY_DATABASE_URI = "something://somewhat:user@hosturl:port/databasename" # needed for any database modules 32 | LOAD = [] 33 | NO_LOAD = ["rss", "cleaner", "connection", "math"] 34 | WEBHOOK = False 35 | INFOPIC = True 36 | URL = None 37 | SPAMWATCH_API = "" # go to support.spamwat.ch to get key 38 | SPAMWATCH_SUPPORT_CHAT = "SpamWatchSupport" 39 | 40 | # OPTIONAL 41 | ##List of id's - (not usernames) for users which have sudo access to the bot. 42 | DRAGONS = get_user_list("elevated_users.json", "sudos") 43 | ##List of id's - (not usernames) for developers who will have the same perms as the owner 44 | DEV_USERS = get_user_list("elevated_users.json", "devs") 45 | ##List of id's (not usernames) for users which are allowed to gban, but can also be banned. 46 | DEMONS = get_user_list("elevated_users.json", "supports") 47 | # List of id's (not usernames) for users which WONT be banned/kicked by the bot. 48 | TIGERS = get_user_list("elevated_users.json", "tigers") 49 | WOLVES = get_user_list("elevated_users.json", "whitelists") 50 | DONATION_LINK = None # EG, paypal 51 | CERT_PATH = None 52 | PORT = 5000 53 | DEL_CMDS = True # Delete commands that users dont have access to, like delete /ban if a non admin uses it. 54 | STRICT_GBAN = True 55 | WORKERS = ( 56 | 8 # Number of subthreads to use. Set as number of threads your processor uses 57 | ) 58 | BAN_STICKER = "" # banhammer marie sticker id, the bot will send this sticker before banning or kicking a user in chat. 59 | ALLOW_EXCL = True # Allow ! commands as well as / (Leave this to true so that blacklist can work) 60 | CASH_API_KEY = ( 61 | "awoo" # Get your API key from https://www.alphavantage.co/support/#api-key 62 | ) 63 | TIME_API_KEY = "awoo" # Get your API key from https://timezonedb.com/api 64 | WALL_API = ( 65 | "awoo" # For wallpapers, get one from https://wall.alphacoders.com/api.php 66 | ) 67 | AI_API_KEY = "awoo" # For chatbot, get one from https://coffeehouse.intellivoid.net/dashboard 68 | BL_CHATS = [] # List of groups that you want blacklisted. 69 | SPAMMERS = None 70 | 71 | class Production(Config): 72 | LOGGER = True 73 | 74 | 75 | class Development(Config): 76 | LOGGER = True 77 | -------------------------------------------------------------------------------- /LaylaRobot/utils/X: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /LaylaRobot/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .progress import progress 2 | from .tools import human_to_bytes, humanbytes, md5, time_formatter 3 | -------------------------------------------------------------------------------- /LaylaRobot/utils/dbfunc.py: -------------------------------------------------------------------------------- 1 | from LaylaRobot.mongo import db 2 | from typing import Dict, List, Union 3 | 4 | 5 | coupledb = db.couple 6 | 7 | 8 | # Couple Chooser 9 | 10 | async def _get_lovers(chat_id: int): 11 | lovers = coupledb.find_one({"chat_id": chat_id}) 12 | if lovers: 13 | lovers = lovers["couple"] 14 | else: 15 | lovers = {} 16 | return lovers 17 | 18 | 19 | async def get_couple(chat_id: int, date: str): 20 | lovers = await _get_lovers(chat_id) 21 | if date in lovers: 22 | return lovers[date] 23 | else: 24 | return False 25 | 26 | 27 | async def save_couple(chat_id: int, date: str, couple: dict): 28 | lovers = await _get_lovers(chat_id) 29 | lovers[date] = couple 30 | await coupledb.update_one( 31 | {"chat_id": chat_id}, 32 | { 33 | "$set": { 34 | "couple": lovers 35 | } 36 | }, 37 | upsert=True 38 | ) 39 | -------------------------------------------------------------------------------- /LaylaRobot/utils/errors.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import traceback 3 | from functools import wraps 4 | from LaylaRobot import pbot as app 5 | from pyrogram.errors.exceptions.forbidden_403 import ChatWriteForbidden 6 | 7 | LOG_GROUP_ID = int(-1001196083551) 8 | 9 | def split_limits(text): 10 | if len(text) < 2048: 11 | return [text] 12 | 13 | lines = text.splitlines(True) 14 | small_msg = '' 15 | result = [] 16 | for line in lines: 17 | if len(small_msg) + len(line) < 2048: 18 | small_msg += line 19 | else: 20 | result.append(small_msg) 21 | small_msg = line 22 | else: 23 | result.append(small_msg) 24 | 25 | return result 26 | 27 | 28 | def capture_err(func): 29 | @wraps(func) 30 | async def capture(client, message, *args, **kwargs): 31 | try: 32 | return await func(client, message, *args, **kwargs) 33 | except ChatWriteForbidden: 34 | await app.leave_chat(message.chat.id) 35 | return 36 | except Exception as err: 37 | exc_type, exc_obj, exc_tb = sys.exc_info() 38 | errors = traceback.format_exception( 39 | etype=exc_type, value=exc_obj, tb=exc_tb, 40 | ) 41 | error_feedback = split_limits( 42 | '**ERROR** | `{}` | `{}`\n\n```{}```\n\n```{}```\n'.format( 43 | 0 if not message.from_user else message.from_user.id, 44 | 0 if not message.chat else message.chat.id, 45 | message.text or message.caption, 46 | ''.join(errors), 47 | ), 48 | ) 49 | for x in error_feedback: 50 | await app.send_message( 51 | LOG_GROUP_ID, 52 | x 53 | ) 54 | raise err 55 | return capture 56 | -------------------------------------------------------------------------------- /LaylaRobot/utils/exceptions.py: -------------------------------------------------------------------------------- 1 | class CancelProcess(Exception): 2 | """ 3 | Cancel Process 4 | """ 5 | -------------------------------------------------------------------------------- /LaylaRobot/utils/my.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /LaylaRobot/utils/progress.py: -------------------------------------------------------------------------------- 1 | import math 2 | import time 3 | 4 | from .exceptions import CancelProcess 5 | from .tools import humanbytes, time_formatter 6 | 7 | 8 | async def progress( 9 | current, total, gdrive, start, prog_type, file_name=None, is_cancelled=False 10 | ): 11 | now = time.time() 12 | diff = now - start 13 | if is_cancelled is True: 14 | raise CancelProcess 15 | 16 | if round(diff % 10.00) == 0 or current == total: 17 | percentage = current * 100 / total 18 | speed = current / diff 19 | elapsed_time = round(diff) 20 | eta = round((total - current) / speed) 21 | if "upload" in prog_type.lower(): 22 | status = "Uploading" 23 | elif "download" in prog_type.lower(): 24 | status = "Downloading" 25 | else: 26 | status = "Unknown" 27 | progress_str = "`{0}` | [{1}{2}] `{3}%`".format( 28 | status, 29 | "".join("●" for i in range(math.floor(percentage / 10))), 30 | "".join("○" for i in range(10 - math.floor(percentage / 10))), 31 | round(percentage, 2), 32 | ) 33 | tmp = ( 34 | f"{progress_str}\n" 35 | f"`{humanbytes(current)} of {humanbytes(total)}" 36 | f" @ {humanbytes(speed)}`\n" 37 | f"`ETA` -> {time_formatter(eta)}\n" 38 | f"`Duration` -> {time_formatter(elapsed_time)}" 39 | ) 40 | await gdrive.edit(f"`{prog_type}`\n\n" f"`Status`\n{tmp}") 41 | -------------------------------------------------------------------------------- /LaylaRobot/utils/tools.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | import re 3 | 4 | 5 | async def md5(fname: str) -> str: 6 | hash_md5 = hashlib.md5() 7 | with open(fname, "rb") as f: 8 | for chunk in iter(lambda: f.read(4096), b""): 9 | hash_md5.update(chunk) 10 | return hash_md5.hexdigest() 11 | 12 | 13 | def humanbytes(size: int) -> str: 14 | if size is None or isinstance(size, str): 15 | return "" 16 | 17 | power = 2 ** 10 18 | raised_to_pow = 0 19 | dict_power_n = {0: "", 1: "Ki", 2: "Mi", 3: "Gi", 4: "Ti"} 20 | while size > power: 21 | size /= power 22 | raised_to_pow += 1 23 | return str(round(size, 2)) + " " + dict_power_n[raised_to_pow] + "B" 24 | 25 | 26 | def time_formatter(seconds: int) -> str: 27 | minutes, seconds = divmod(seconds, 60) 28 | hours, minutes = divmod(minutes, 60) 29 | days, hours = divmod(hours, 24) 30 | tmp = ( 31 | ((str(days) + " day(s), ") if days else "") 32 | + ((str(hours) + " hour(s), ") if hours else "") 33 | + ((str(minutes) + " minute(s), ") if minutes else "") 34 | + ((str(seconds) + " second(s), ") if seconds else "") 35 | ) 36 | return tmp[:-2] 37 | 38 | 39 | def human_to_bytes(size: str) -> int: 40 | units = { 41 | "M": 2 ** 20, 42 | "MB": 2 ** 20, 43 | "G": 2 ** 30, 44 | "GB": 2 ** 30, 45 | "T": 2 ** 40, 46 | "TB": 2 ** 40, 47 | } 48 | 49 | size = size.upper() 50 | if not re.match(r" ", size): 51 | size = re.sub(r"([KMGT])", r" \1", size) 52 | number, unit = [string.strip() for string in size.split()] 53 | return int(float(number) * units[unit]) 54 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | worker: python3 -m LaylaRobot 2 | ps:scale worker=1 3 | -------------------------------------------------------------------------------- /Setup venv.bat: -------------------------------------------------------------------------------- 1 | TITLE Setting up virtual env 2 | :: Running it once is fine, this just sets up virtual env >> install all modules there 3 | py -m venv env && env\scripts\activate.bat && pip install -r requirements.txt 4 | 5 | :: Note to rerun the requirements.txt in case you ever add a mdoule. 6 | :: Running this multiple time will not make a mess of your setup, dont worry about that bit. 7 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-architect -------------------------------------------------------------------------------- /exp.sh: -------------------------------------------------------------------------------- 1 | sudo bash -c 'echo "{ \"cgroup-parent\": \"/actions_job\",\"experimental\":true}" > /etc/docker/daemon.json' 2 | sudo systemctl restart docker.service -------------------------------------------------------------------------------- /heroku.yml: -------------------------------------------------------------------------------- 1 | build: 2 | docker: 3 | worker: Dockerfile 4 | run: 5 | worker: python3 -m LaylaRobot 6 | -------------------------------------------------------------------------------- /profanity_wordlist.txt: -------------------------------------------------------------------------------- 1 | 2g1c 2 | 2 girls 1 cup 3 | 4r5e 4 | anal 5 | anus 6 | arse 7 | ass 8 | asses 9 | assfucker 10 | assfukka 11 | asshole 12 | arsehole 13 | asswhole 14 | assmunch 15 | auto erotic 16 | autoerotic 17 | ballsack 18 | bastard 19 | beastial 20 | bestial 21 | bellend 22 | bdsm 23 | beastiality 24 | bestiality 25 | bitch 26 | bitches 27 | bitchin 28 | bitching 29 | bimbo 30 | bimbos 31 | blow job 32 | blowjob 33 | blowjobs 34 | blue waffle 35 | boob 36 | boobs 37 | booobs 38 | boooobs 39 | booooobs 40 | booooooobs 41 | breasts 42 | booty call 43 | brown shower 44 | brown showers 45 | boner 46 | bondage 47 | buceta 48 | bukake 49 | bukkake 50 | bullshit 51 | bull shit 52 | busty 53 | butthole 54 | carpet muncher 55 | cawk 56 | chink 57 | cipa 58 | clit 59 | clits 60 | clitoris 61 | cnut 62 | cock 63 | cocks 64 | cockface 65 | cockhead 66 | cockmunch 67 | cockmuncher 68 | cocksuck 69 | cocksucked 70 | cocksucking 71 | cocksucks 72 | cocksucker 73 | cokmuncher 74 | coon 75 | cow girl 76 | cow girls 77 | cowgirl 78 | cowgirls 79 | crap 80 | crotch 81 | cum 82 | cummer 83 | cumming 84 | cuming 85 | cums 86 | cumshot 87 | cunilingus 88 | cunillingus 89 | cunnilingus 90 | cunt 91 | cuntlicker 92 | cuntlicking 93 | cunts 94 | damn 95 | dick 96 | dickhead 97 | dildo 98 | dildos 99 | dink 100 | dinks 101 | deepthroat 102 | deep throat 103 | dog style 104 | doggie style 105 | doggiestyle 106 | doggy style 107 | doggystyle 108 | donkeyribber 109 | doosh 110 | douche 111 | duche 112 | dyke 113 | ejaculate 114 | ejaculated 115 | ejaculates 116 | ejaculating 117 | ejaculatings 118 | ejaculation 119 | ejakulate 120 | erotic 121 | erotism 122 | fag 123 | faggot 124 | fagging 125 | faggit 126 | faggitt 127 | faggs 128 | fagot 129 | fagots 130 | fags 131 | fatass 132 | femdom 133 | fingering 134 | footjob 135 | foot job 136 | fuck 137 | fucks 138 | fucker 139 | fuckers 140 | fucked 141 | fuckhead 142 | fuckheads 143 | fuckin 144 | fucking 145 | fcuk 146 | fcuker 147 | fcuking 148 | felching 149 | fellate 150 | fellatio 151 | fingerfuck 152 | fingerfucked 153 | fingerfucker 154 | fingerfuckers 155 | fingerfucking 156 | fingerfucks 157 | fistfuck 158 | fistfucked 159 | fistfucker 160 | fistfuckers 161 | fistfucking 162 | fistfuckings 163 | fistfucks 164 | flange 165 | fook 166 | fooker 167 | fucka 168 | fuk 169 | fuks 170 | fuker 171 | fukker 172 | fukkin 173 | fukking 174 | futanari 175 | futanary 176 | gangbang 177 | gangbanged 178 | gang bang 179 | gokkun 180 | golden shower 181 | goldenshower 182 | gaysex 183 | goatse 184 | handjob 185 | hand job 186 | hentai 187 | hooker 188 | hoer 189 | homo 190 | horny 191 | incest 192 | jackoff 193 | jack off 194 | jerkoff 195 | jerk off 196 | jizz 197 | knob 198 | kinbaku 199 | labia 200 | masturbate 201 | masochist 202 | mofo 203 | mothafuck 204 | motherfuck 205 | motherfucker 206 | mothafucka 207 | mothafuckas 208 | mothafuckaz 209 | mothafucked 210 | mothafucker 211 | mothafuckers 212 | mothafuckin 213 | mothafucking 214 | mothafuckings 215 | mothafucks 216 | mother fucker 217 | motherfucked 218 | motherfucker 219 | motherfuckers 220 | motherfuckin 221 | motherfucking 222 | motherfuckings 223 | motherfuckka 224 | motherfucks 225 | milf 226 | muff 227 | nigga 228 | nigger 229 | nigg 230 | nipple 231 | nipples 232 | nob 233 | nob jokey 234 | nobhead 235 | nobjocky 236 | nobjokey 237 | numbnuts 238 | nutsack 239 | nude 240 | nudes 241 | orgy 242 | orgasm 243 | orgasms 244 | panty 245 | panties 246 | penis 247 | playboy 248 | porn 249 | porno 250 | pornography 251 | pron 252 | pussy 253 | pussies 254 | rape 255 | raping 256 | rapist 257 | rectum 258 | retard 259 | rimming 260 | sadist 261 | sadism 262 | schlong 263 | scrotum 264 | sex 265 | semen 266 | shemale 267 | she male 268 | shibari 269 | shibary 270 | shit 271 | shitdick 272 | shitfuck 273 | shitfull 274 | shithead 275 | shiting 276 | shitings 277 | shits 278 | shitted 279 | shitters 280 | shitting 281 | shittings 282 | shitty 283 | shota 284 | skank 285 | slut 286 | sluts 287 | smut 288 | smegma 289 | spunk 290 | strip club 291 | stripclub 292 | tit 293 | tits 294 | titties 295 | titty 296 | titfuck 297 | tittiefucker 298 | titties 299 | tittyfuck 300 | tittywank 301 | titwank 302 | threesome 303 | three some 304 | throating 305 | twat 306 | twathead 307 | twatty 308 | twunt 309 | viagra 310 | vagina 311 | vulva 312 | wank 313 | wanker 314 | wanky 315 | whore 316 | whoar 317 | xxx 318 | xx 319 | yaoi 320 | yury 321 | sexy -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | future 2 | emoji 3 | lxml 4 | wget 5 | gtts 6 | faker 7 | beautifulsoup4 8 | requests==2.20.0 9 | python-telegram-bot==12.8 10 | sqlalchemy==1.3.20 11 | psycopg2-binary 12 | feedparser 13 | hachoir 14 | pynewtonmath 15 | spongemock 16 | zalgo-text 17 | geopy 18 | nltk 19 | psutil 20 | aiohttp>=2.2.5 21 | Pillow>=4.2.0 22 | CurrencyConverter 23 | #googletrans 24 | google_trans_new 25 | jikanpy 26 | speedtest-cli 27 | coffeehouse==2.2.4 28 | regex 29 | bleach 30 | git+https://github.com/starry69/python-markdown2.git 31 | wikipedia 32 | telethon==1.16.4 33 | telegraph 34 | heroku3 35 | spamwatch 36 | alphabet_detector 37 | pybase64 38 | pySmartDL 39 | validators 40 | nekos.py 41 | aiofiles 42 | pyrate-limiter 43 | cachetools 44 | ujson 45 | pretty_errors 46 | TgCrypto 47 | Pyrogram 48 | youtube-dl 49 | youtube_search_python 50 | youtube_search 51 | asyncio 52 | dateparser==1.0.0 53 | pymongo==3.11.0 54 | dnspython 55 | secureme 56 | apscheduler 57 | emoji-country-flag 58 | countryinfo 59 | html2text 60 | bs4 61 | fontTools 62 | bing_image_downloader 63 | search_engine_parser 64 | pytz 65 | lyricsgenius 66 | tswift 67 | envparse 68 | better_profanity 69 | nudepy 70 | motor 71 | cloudscraper 72 | -------------------------------------------------------------------------------- /restart.bat: -------------------------------------------------------------------------------- 1 | :: starts a cmd to silently start the bat file, just another dirty way of getting things done for my env on windows 2 | start cmd.exe /c start_service.bat -------------------------------------------------------------------------------- /runtime.txt: -------------------------------------------------------------------------------- 1 | python-3.8.6 2 | -------------------------------------------------------------------------------- /start.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | TITLE Layla Robot 3 | :: Enables virtual env mode and then starts Rika 4 | env\scripts\activate.bat && py -m LaylaRobot 5 | -------------------------------------------------------------------------------- /start_service.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | :: This runs the batch file as an admin - required UAC to be off 3 | :: This is just an asty hack in to get job done cause we host it on windows dedi. 4 | :: BatchGotAdmin 5 | :------------------------------------- 6 | REM --> Check for permissions 7 | >nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system" 8 | 9 | REM --> If error flag set, we do not have admin. 10 | if '%errorlevel%' NEQ '0' ( 11 | echo Requesting administrative privileges... 12 | goto UACPrompt 13 | ) else ( goto gotAdmin ) 14 | 15 | :UACPrompt 16 | echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs" 17 | set params = %*:"="" 18 | echo UAC.ShellExecute "cmd.exe", "/c %~s0 %params%", "", "runas", 1 >> "%temp%\getadmin.vbs" 19 | 20 | "%temp%\getadmin.vbs" 21 | del "%temp%\getadmin.vbs" 22 | exit /B 23 | 24 | :gotAdmin 25 | pushd "%CD%" 26 | CD /D "%~dp0" 27 | :-------------------------------------- 28 | :: your commands begin from this point. 29 | :: stops the service and then starts it 30 | net stop LaylaRobot 31 | net start LaylaRobot 32 | --------------------------------------------------------------------------------