├── .github
├── CODEOWNERS
├── README.md
├── dependabot.yml
└── workflows
│ └── PyLint.yml
├── Dockerfile
├── FallenRobot
├── __init__.py
├── __main__.py
├── config.py
├── events.py
├── modules
│ ├── __init__.py
│ ├── admin.py
│ ├── afk.py
│ ├── alive.py
│ ├── antiflood.py
│ ├── approve.py
│ ├── backups.py
│ ├── bans.py
│ ├── blacklist.py
│ ├── blacklist_stickers.py
│ ├── blacklistusers.py
│ ├── carbon.py
│ ├── chatbot.py
│ ├── cleaner.py
│ ├── connection.py
│ ├── country.py
│ ├── couples.py
│ ├── currency_converter.py
│ ├── cust_filters.py
│ ├── dbcleanup.py
│ ├── debug.py
│ ├── dev.py
│ ├── disable.py
│ ├── disasters.py
│ ├── encrypt.py
│ ├── english.py
│ ├── error_handler.py
│ ├── eval.py
│ ├── fonts.py
│ ├── fun.py
│ ├── fun_strings.py
│ ├── get_common_chats.py
│ ├── gettime.py
│ ├── gitinfo.py
│ ├── global_bans.py
│ ├── google.py
│ ├── gps.py
│ ├── group.py
│ ├── helper_funcs
│ │ ├── __init__.py
│ │ ├── admin_rights.py
│ │ ├── alternate.py
│ │ ├── chat_status.py
│ │ ├── extraction.py
│ │ ├── filters.py
│ │ ├── handlers.py
│ │ ├── misc.py
│ │ ├── msg_types.py
│ │ ├── regex_helper.py
│ │ ├── string_handling.py
│ │ └── telethn
│ │ │ ├── __init__.py
│ │ │ └── chatstatus.py
│ ├── json.py
│ ├── locks.py
│ ├── log_channel.py
│ ├── logo.py
│ ├── math.py
│ ├── memify.py
│ ├── misc.py
│ ├── modules.py
│ ├── muting.py
│ ├── nightmode.py
│ ├── notes.py
│ ├── paste.py
│ ├── ping.py
│ ├── purge.py
│ ├── reactions.py
│ ├── remote_cmds.py
│ ├── reporting.py
│ ├── rules.py
│ ├── sed.py
│ ├── shell.py
│ ├── source.py
│ ├── speed_test.py
│ ├── sql
│ │ ├── __init__.py
│ │ ├── afk_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
│ │ ├── global_bans_sql.py
│ │ ├── locks_sql.py
│ │ ├── log_channel_sql.py
│ │ ├── night_mode_sql.py
│ │ ├── notes_sql.py
│ │ ├── reporting_sql.py
│ │ ├── rss_sql.py
│ │ ├── rules_sql.py
│ │ ├── userinfo_sql.py
│ │ ├── users_sql.py
│ │ ├── warns_sql.py
│ │ └── welcome_sql.py
│ ├── stickers.py
│ ├── tagall.py
│ ├── telegraph.py
│ ├── tiny.py
│ ├── translator.py
│ ├── truth_and_dare.py
│ ├── ud.py
│ ├── userinfo.py
│ ├── users.py
│ ├── wallpaper.py
│ ├── warns.py
│ ├── weather.py
│ ├── webshot.py
│ ├── welcome.py
│ ├── wiki.py
│ ├── writetool.py
│ ├── zip.py
│ └── zombies.py
├── resources
│ ├── blank_background.png
│ ├── default.ttf
│ ├── fallen.jpg
│ ├── fglitch.gif
│ └── fonts
│ │ ├── AVENGEANCE HEROIC AVENGER AT.otf
│ │ ├── AVENGEANCE HEROIC AVENGER AT.ttf
│ │ ├── AVENGEANCE HEROIC AVENGER BI.otf
│ │ ├── Big Space.otf
│ │ ├── CRAWLER-RegularDEMO.ttf
│ │ ├── CROWNT.TTF
│ │ ├── Chopsic.otf
│ │ ├── Crozzoe-Personal-Use.otf
│ │ ├── DIGIT.ttf
│ │ ├── Damages-Italic.ttf
│ │ ├── Damages.ttf
│ │ ├── Damages3D-Italic.ttf
│ │ ├── Damages3D.ttf
│ │ ├── Damages3DFilled-Italic.ttf
│ │ ├── Damages3DFilled.ttf
│ │ ├── Damar Kurung.otf
│ │ ├── Damar Kurung.ttf
│ │ ├── Dark Ministry.ttf
│ │ ├── Dark Seed.otf
│ │ ├── Dark.ttf
│ │ ├── Dash-Dermo.ttf
│ │ ├── Dead Revolution.otf
│ │ ├── DezertDemoDash.ttf
│ │ ├── DezertDemoItalic.ttf
│ │ ├── DezertDemoItalicDash.ttf
│ │ ├── DezertDemoOutline.ttf
│ │ ├── DezertDemoOutlineDash.ttf
│ │ ├── DezertDemoRegular.ttf
│ │ ├── DisposableDroidBB_bld.ttf
│ │ ├── DragonForcE.ttf
│ │ ├── Dramaga Demo.otf
│ │ ├── Dramaga Demo.ttf
│ │ ├── Dreamscar.ttf
│ │ ├── EVILDEAD.TTF
│ │ ├── Europhonic.otf
│ │ ├── Exorcista_-Jed_40.ttf
│ │ ├── Fire Flight FREE.otf
│ │ ├── Fire Flight FREE.ttf
│ │ ├── FontRemix.ttf
│ │ ├── FontRemix2.ttf
│ │ ├── Friend Head.otf
│ │ ├── Frostbite Boss Fight.otf
│ │ ├── Fucking Hostile.ttf
│ │ ├── GRAMES.ttf
│ │ ├── Gang Wolfik.ttf
│ │ ├── Garda.ttf
│ │ ├── Garreng-Personal-Use.otf
│ │ ├── Geizer.otf
│ │ ├── Georgent.otf
│ │ ├── Georgent.ttf
│ │ ├── Hallowed Grad.otf
│ │ ├── Harker Bold Italic.otf
│ │ ├── Harker Italic.otf
│ │ ├── Maghrib.ttf
│ │ ├── ObelixProB-cyr Alfi Stefa.ttf
│ │ ├── RealFast Alfi Stefa.ttf
│ │ ├── Roboto-Italic.ttf
│ │ ├── Roboto-Medium.ttf
│ │ ├── Roboto-Regular.ttf
│ │ ├── TruenoBlkOl.otf
│ │ ├── TruenoRg.otf
│ │ ├── TruenoRgIt.otf
│ │ ├── TruenoSBdIt.otf
│ │ ├── Vendetta.otf
│ │ ├── __init__.py
│ │ ├── digital.ttf
│ │ ├── elric.TTF
│ │ ├── font.otf
│ │ ├── fontx.ttf
│ │ ├── hawkmoon.ttf
│ │ └── monumentextended-regular.otf
└── utils
│ ├── admins.py
│ ├── errors.py
│ ├── fonts.py
│ ├── functions.py
│ ├── mongo.py
│ ├── pastebin.py
│ └── post.py
├── Git_Pull.bat
├── Git_Push.bat
├── LICENSE
├── Procfile
├── Setup venv.bat
├── _config.yml
├── app.json
├── heroku.yml
├── requirements.txt
├── restart.bat
├── runtime.txt
├── start.bat
└── start_service.bat
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @AnonymousX1025
2 |
--------------------------------------------------------------------------------
/.github/README.md:
--------------------------------------------------------------------------------
1 | [━━━━━━━━━━━━━━━━━━━━
2 |
3 |
4 | ──「™° 🫧 🇴 🇽 𝐘 𓃭🇨𝐇𝐀𝐓 𝐁𝐎𝐓 ⃟⛦⃕͜༆」──
5 |
6 |
7 |
8 |
9 |
10 |
11 | _**ᴀᴠᴀɪʟᴀʙʟᴇ ᴏɴ ᴛᴇʟᴇɢʀᴀᴍ ᴀs [™° 🫧 🇴 🇽 𝐘 𓃭🇨𝐇𝐀𝐓 𝐁𝐎𝐓 ⃟⛦⃕͜༆](https://t.me/DESISWAGGERHU)**_
12 | ━━━━━━━━━━━━━━━━━━━━
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | ━━━━━━━━━━━━━━━━━━━━
26 |
27 |
28 |
29 |
30 |
31 |
32 | 𝗗𝗘𝗣𝗟𝗢𝗬𝗠𝗘𝗡𝗧 𝗠𝗘𝗧𝗛𝗢𝗗𝗦
33 |
34 |
35 |
36 | ─「 ᴅᴇᴩʟᴏʏ ᴏɴ ʜᴇʀᴏᴋᴜ 」─
37 |
38 |
39 | 
40 |
41 |
42 |
43 | ─「 ᴅᴇᴩʟᴏʏ ᴏɴ ᴠᴘs/ʟᴏᴄᴀʟ 」─
44 |
45 |
46 |
47 |
48 | - ᴠᴘs/ʟᴏᴄᴀʟ ᴅᴇᴘʟᴏʏᴍᴇɴᴛ ᴍᴇᴛʜᴏᴅ
49 |
50 |
51 | - Get your [Necessary Variables](https://github.com/AnonymousX1025/FallenRobot/blob/master/FallenRobot/config.py)
52 | - Upgrade and Update by :
53 | `sudo apt-get update && sudo apt-get upgrade -y`
54 | - Install required packages by :
55 | `sudo apt-get install python3-pip -y`
56 | - Install pip by :
57 | `sudo pip3 install -U pip`
58 | - Clone the repository by :
59 | `git clone https://github.com/AnonymousX1025/FallenRobot && cd FallenRobot`
60 | - Install/Upgrade setuptools by :
61 | `pip3 install --upgrade pip setuptools`
62 | - Install requirements by :
63 | `pip3 install -U -r requirements.txt`
64 | - Fill your variables in config by :
65 | `vi FallenRobot/config.py`
66 |
67 | Press `I` on the keyboard for editing config
68 |
69 | Press `Ctrl+C` when you're done with editing config and `:wq` to save the config
70 | - Install tmux to keep running your bot when you close the terminal by :
71 | `sudo apt install tmux && tmux`
72 | - Finally run the bot by :
73 | `python3 -m FallenRobot`
74 | - For getting out from tmux session
75 |
76 | Press `Ctrl+b` and then `d`
77 |
78 |
79 |
80 |
81 |
82 |
83 | ━━━━━━━━━━━━━━━━━━━━
84 |
85 |
86 | ─「 sᴜᴩᴩᴏʀᴛ 」─
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | ━━━━━━━━━━━━━━━━━━━━
97 |
98 |
99 | ─「 ᴄʀᴇᴅɪᴛs 」─
100 |
101 |
102 | - [ᴀɴᴏɴʏᴍᴏᴜs](https://github.com/AnonymousX1025) ➻ [sᴏᴍᴇᴛʜɪɴɢ](https://github.com/PRADHAN474/FallenRobot)
103 | - [ᴩᴀᴜʟ ʟᴀʀsᴇɴ](https://github.com/PaulSonOfLars) ➻ [ᴛɢ ʙᴏᴛ](https://github.com/PaulSonOfLars/tgbot)
104 | - [ʜᴀᴍᴋᴇʀ ᴄᴀᴛ](https://github.com/TheHamkerCat) ➻ [ᴡɪʟʟɪᴀᴍ ʙᴜᴛᴄʜᴇʀ](https://github.com/TheHamkerCat/WilliamButcherBot)
105 |
106 | ᴀɴᴅ ᴀʟʟ [ᴛʜᴇ ᴄᴏɴᴛʀɪʙᴜᴛᴏʀs](https://github.com/AnonymousX1025/FallenRobot/graphs/contributors) ᴡʜᴏ ʜᴇʟᴩᴇᴅ ɪɴ ᴍᴀᴋɪɴɢ ғᴀʟʟᴇɴ ✘ ʀᴏʙᴏᴛ ᴜsᴇғᴜʟ & ᴩᴏᴡᴇʀғᴜʟ 🖤
107 |
108 | ━━━━━━━━━━━━━━━━━━━━
109 | ](https://github.com/AnonymousX1025/FallenRobot.git)https://github.com/AnonymousX1025/FallenRobot.git
110 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: pip
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | time: "00:00"
8 | timezone: "Asia/Kolkata"
9 | labels:
10 | - "dependencies"
11 | open-pull-requests-limit: 50
12 | ignore:
13 | - dependency-name: "python-telegram-bot"
14 | # Ignoring all ptb updates
15 | - dependency-name: "sqlalchemy"
16 | # Ignoring all sqlalchemy updates
17 |
--------------------------------------------------------------------------------
/.github/workflows/PyLint.yml:
--------------------------------------------------------------------------------
1 | name: PyLint
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | PEP8:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v2
10 |
11 | - name: Setup Python
12 | uses: actions/setup-python@v1
13 | with:
14 | python-version: 3.10.12
15 | - name: Install Python lint libraries
16 | run: |
17 | pip install autoflake isort black
18 | - name: Remove unused imports and variables
19 | run: |
20 | autoflake --in-place --recursive --remove-all-unused-imports --ignore-init-module-imports .
21 | - name: lint with isort
22 | run: |
23 | isort .
24 | - name: lint with black
25 | run: |
26 | black .
27 | # commit changes
28 | - uses: stefanzweifel/git-auto-commit-action@v4
29 | with:
30 | commit_message: 'Auto Fixes'
31 | commit_options: '--no-verify'
32 | repository: .
33 | commit_user_name: AnonymousX1025
34 | commit_user_email: TheAnonymousX1025@gmail.com
35 | commit_author: AnonymousX1025
36 |
--------------------------------------------------------------------------------
/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/FallenRobot
68 | RUN git clone https://github.com/AnonymousX1025/FallenRobot /root/FallenRobot
69 | WORKDIR /root/FallenRobot
70 |
71 | #Copy config file to /root/FallenRobot/FallenRobot
72 | COPY ./FallenRobot/config.py ./FallenRobot/config.py* /root/FallenRobot/FallenRobot/
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","FallenRobot"]
81 |
--------------------------------------------------------------------------------
/FallenRobot/config.py:
--------------------------------------------------------------------------------
1 | class Config(object):
2 | LOGGER = True
3 |
4 | # Get this value from my.telegram.org/apps
5 | API_ID = 6
6 | API_HASH = "eb06d4abfb49dc3eeb1aeb98ae0f581e"
7 |
8 | CASH_API_KEY = "" # Get this value for currency converter from https://www.alphavantage.co/support/#api-key
9 |
10 | DATABASE_URL = "" # A sql database url from elephantsql.com
11 |
12 | EVENT_LOGS = () # Event logs channel to note down important bot level events
13 |
14 | MONGO_DB_URI = "" # Get ths value from cloud.mongodb.com
15 |
16 | # Telegraph link of the image which will be shown at start command.
17 | START_IMG = "https://te.legra.ph/file/40eb1ed850cdea274693e.jpg"
18 |
19 | SUPPORT_CHAT = "BWANDARLOK" # Your Telegram support group chat username where your users will go and bother you
20 |
21 | TOKEN = "" # Get bot token from @BotFather on Telegram
22 |
23 | TIME_API_KEY = "" # Get this value from https://timezonedb.com/api
24 |
25 | OWNER_ID = 5059737154 # User id of your telegram account (Must be integer)
26 |
27 | # Optional fields
28 | BL_CHATS = [] # List of groups that you want blacklisted.
29 | DRAGONS = [] # User id of sudo users
30 | DEV_USERS = [] # User id of dev users
31 | DEMONS = [] # User id of support users
32 | TIGERS = [] # User id of tiger users
33 | WOLVES = [] # User id of whitelist users
34 |
35 | ALLOW_CHATS = True
36 | ALLOW_EXCL = True
37 | DEL_CMDS = True
38 | INFOPIC = True
39 | LOAD = []
40 | NO_LOAD = []
41 | STRICT_GBAN = True
42 | TEMP_DOWNLOAD_DIRECTORY = "./"
43 | WORKERS = 8
44 |
45 |
46 | class Production(Config):
47 | LOGGER = True
48 |
49 |
50 | class Development(Config):
51 | LOGGER = True
52 |
--------------------------------------------------------------------------------
/FallenRobot/events.py:
--------------------------------------------------------------------------------
1 | import inspect
2 | import re
3 | from pathlib import Path
4 |
5 | from pymongo import MongoClient
6 | from telethon import events
7 |
8 | from FallenRobot import MONGO_DB_URI, telethn
9 |
10 | client = MongoClient()
11 | client = MongoClient(MONGO_DB_URI)
12 | db = client["Anonymous"]
13 | gbanned = db.gban
14 |
15 |
16 | def register(**args):
17 | """Registers a new message."""
18 | pattern = args.get("pattern", None)
19 |
20 | r_pattern = r"^[/!.]"
21 |
22 | if pattern is not None and not pattern.startswith("(?i)"):
23 | args["pattern"] = "(?i)" + pattern
24 |
25 | args["pattern"] = pattern.replace("^/", r_pattern, 1)
26 |
27 | def decorator(func):
28 | telethn.add_event_handler(func, events.NewMessage(**args))
29 | return func
30 |
31 | return decorator
32 |
33 |
34 | def chataction(**args):
35 | """Registers chat actions."""
36 |
37 | def decorator(func):
38 | telethn.add_event_handler(func, events.ChatAction(**args))
39 | return func
40 |
41 | return decorator
42 |
43 |
44 | def userupdate(**args):
45 | """Registers user updates."""
46 |
47 | def decorator(func):
48 | telethn.add_event_handler(func, events.UserUpdate(**args))
49 | return func
50 |
51 | return decorator
52 |
53 |
54 | def inlinequery(**args):
55 | """Registers inline query."""
56 | pattern = args.get("pattern", None)
57 |
58 | if pattern is not None and not pattern.startswith("(?i)"):
59 | args["pattern"] = "(?i)" + pattern
60 |
61 | def decorator(func):
62 | telethn.add_event_handler(func, events.InlineQuery(**args))
63 | return func
64 |
65 | return decorator
66 |
67 |
68 | def callbackquery(**args):
69 | """Registers inline query."""
70 |
71 | def decorator(func):
72 | telethn.add_event_handler(func, events.CallbackQuery(**args))
73 | return func
74 |
75 | return decorator
76 |
77 |
78 | def bot(**args):
79 | pattern = args.get("pattern")
80 | r_pattern = r"^[/]"
81 |
82 | if pattern is not None and not pattern.startswith("(?i)"):
83 | args["pattern"] = "(?i)" + pattern
84 |
85 | args["pattern"] = pattern.replace("^/", r_pattern, 1)
86 | stack = inspect.stack()
87 | previous_stack_frame = stack[1]
88 | file_test = Path(previous_stack_frame.filename)
89 | file_test = file_test.stem.replace(".py", "")
90 | reg = re.compile("(.*)")
91 |
92 | if pattern is not None:
93 | try:
94 | cmd = re.search(reg, pattern)
95 | try:
96 | cmd = cmd.group(1).replace("$", "").replace("\\", "").replace("^", "")
97 | except BaseException:
98 | pass
99 |
100 | try:
101 | FUN_LIST[file_test].append(cmd)
102 | except BaseException:
103 | FUN_LIST.update({file_test: [cmd]})
104 | except BaseException:
105 | pass
106 |
107 | def decorator(func):
108 | async def wrapper(check):
109 | if check.edit_date:
110 | return
111 | if check.fwd_from:
112 | return
113 | if check.is_group or check.is_private:
114 | pass
115 | else:
116 | print("i don't work in channels")
117 | return
118 | if check.is_group:
119 | if check.chat.megagroup:
120 | pass
121 | else:
122 | print("i don't work in small chats")
123 | return
124 |
125 | users = gbanned.find({})
126 | for c in users:
127 | if check.sender_id == c["user"]:
128 | return
129 | try:
130 | await func(check)
131 | try:
132 | LOAD_PLUG[file_test].append(func)
133 | except Exception:
134 | LOAD_PLUG.update({file_test: [func]})
135 | except BaseException:
136 | return
137 | else:
138 | pass
139 |
140 | telethn.add_event_handler(wrapper, events.NewMessage(**args))
141 | return wrapper
142 |
143 | return decorator
144 |
145 |
146 | def fallenrobot(**args):
147 | pattern = args.get("pattern", None)
148 | args.get("disable_edited", False)
149 | ignore_unsafe = args.get("ignore_unsafe", False)
150 | unsafe_pattern = r"^[^/!#@\$A-Za-z]"
151 | args.get("group_only", False)
152 | args.get("disable_errors", False)
153 | args.get("insecure", False)
154 | if pattern is not None and not pattern.startswith("(?i)"):
155 | args["pattern"] = "(?i)" + pattern
156 |
157 | if "disable_edited" in args:
158 | del args["disable_edited"]
159 |
160 | if "ignore_unsafe" in args:
161 | del args["ignore_unsafe"]
162 |
163 | if "group_only" in args:
164 | del args["group_only"]
165 |
166 | if "disable_errors" in args:
167 | del args["disable_errors"]
168 |
169 | if "insecure" in args:
170 | del args["insecure"]
171 |
172 | if pattern:
173 | if not ignore_unsafe:
174 | args["pattern"] = args["pattern"].replace("^.", unsafe_pattern, 1)
175 |
--------------------------------------------------------------------------------
/FallenRobot/modules/__init__.py:
--------------------------------------------------------------------------------
1 | from FallenRobot 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 |
--------------------------------------------------------------------------------
/FallenRobot/modules/alive.py:
--------------------------------------------------------------------------------
1 | from pyrogram import __version__ as pyrover
2 | from pyrogram import filters
3 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message
4 | from telegram import __version__ as telever
5 | from telethon import __version__ as tlhver
6 |
7 | from FallenRobot import BOT_NAME, BOT_USERNAME, OWNER_ID, START_IMG, SUPPORT_CHAT, pbot
8 |
9 |
10 | @pbot.on_message(filters.command("alive"))
11 | async def awake(_, message: Message):
12 | TEXT = f"**ʜᴇʏ {message.from_user.mention},\n\nɪ ᴀᴍ {BOT_NAME}**\n━━━━━━━━━━━━━━━━━━━\n\n"
13 | TEXT += f"» **ᴍʏ ᴅᴇᴠᴇʟᴏᴘᴇʀ :** [™° 🫧 🇴 🇽 𝐘 𝐆 𝐄 𝐍](tg://user?id={OWNER_ID})\n\n"
14 | TEXT += f"» **ʟɪʙʀᴀʀʏ ᴠᴇʀsɪᴏɴ :** `{telever}` \n\n"
15 | TEXT += f"» **ᴛᴇʟᴇᴛʜᴏɴ ᴠᴇʀsɪᴏɴ :** `{tlhver}` \n\n"
16 | TEXT += f"» **ᴘʏʀᴏɢʀᴀᴍ ᴠᴇʀsɪᴏɴ :** `{pyrover}` \n━━━━━━━━━━━━━━━━━\n\n"
17 | BUTTON = [
18 | [
19 | InlineKeyboardButton("ʜᴇʟᴘ", url=f"https://t.me/{BOT_USERNAME}?start=help"),
20 | InlineKeyboardButton("sᴜᴘᴘᴏʀᴛ", url=f"https://t.me/{SUPPORT_CHAT}"),
21 | ]
22 | ]
23 | await message.reply_photo(
24 | photo=START_IMG,
25 | caption=TEXT,
26 | reply_markup=InlineKeyboardMarkup(BUTTON),
27 | )
28 |
29 |
30 | __mod_name__ = "Aʟɪᴠᴇ"
31 |
--------------------------------------------------------------------------------
/FallenRobot/modules/blacklistusers.py:
--------------------------------------------------------------------------------
1 | import html
2 |
3 | from telegram import ParseMode, Update
4 | from telegram.error import BadRequest
5 | from telegram.ext import CallbackContext, CommandHandler
6 | from telegram.utils.helpers import mention_html
7 |
8 | import FallenRobot.modules.sql.blacklistusers_sql as sql
9 | from FallenRobot import DEMONS, DEV_USERS, DRAGONS, OWNER_ID, TIGERS, WOLVES, dispatcher
10 | from FallenRobot.modules.helper_funcs.chat_status import dev_plus
11 | from FallenRobot.modules.helper_funcs.extraction import (
12 | extract_user,
13 | extract_user_and_text,
14 | )
15 | from FallenRobot.modules.log_channel import gloggable
16 |
17 | BLACKLISTWHITELIST = [OWNER_ID] + DEV_USERS + DRAGONS + WOLVES + DEMONS
18 | BLABLEUSERS = [OWNER_ID] + DEV_USERS
19 |
20 |
21 | @dev_plus
22 | @gloggable
23 | def bl_user(update: Update, context: CallbackContext) -> str:
24 | message = update.effective_message
25 | user = update.effective_user
26 | bot, args = context.bot, context.args
27 | user_id, reason = extract_user_and_text(message, args)
28 |
29 | if not user_id:
30 | message.reply_text("I doubt that's a user.")
31 | return ""
32 |
33 | if user_id == bot.id:
34 | message.reply_text("How am I supposed to do my work if I am ignoring myself?")
35 | return ""
36 |
37 | if user_id in BLACKLISTWHITELIST:
38 | message.reply_text("No!\nNoticing Disasters is my job.")
39 | return ""
40 |
41 | try:
42 | target_user = bot.get_chat(user_id)
43 | except BadRequest as excp:
44 | if excp.message == "User not found":
45 | message.reply_text("I can't seem to find this user.")
46 | return ""
47 | else:
48 | raise
49 |
50 | sql.blacklist_user(user_id, reason)
51 | message.reply_text("I shall ignore the existence of this user!")
52 | log_message = (
53 | f"#BLACKLIST\n"
54 | f"Admin: {mention_html(user.id, html.escape(user.first_name))}\n"
55 | f"User: {mention_html(target_user.id, html.escape(target_user.first_name))}"
56 | )
57 | if reason:
58 | log_message += f"\nReason: {reason}"
59 |
60 | return log_message
61 |
62 |
63 | @dev_plus
64 | @gloggable
65 | def unbl_user(update: Update, context: CallbackContext) -> str:
66 | message = update.effective_message
67 | user = update.effective_user
68 | bot, args = context.bot, context.args
69 | user_id = extract_user(message, args)
70 |
71 | if not user_id:
72 | message.reply_text("I doubt that's a user.")
73 | return ""
74 |
75 | if user_id == bot.id:
76 | message.reply_text("I always notice myself.")
77 | return ""
78 |
79 | try:
80 | target_user = bot.get_chat(user_id)
81 | except BadRequest as excp:
82 | if excp.message == "User not found":
83 | message.reply_text("I can't seem to find this user.")
84 | return ""
85 | else:
86 | raise
87 |
88 | if sql.is_user_blacklisted(user_id):
89 | sql.unblacklist_user(user_id)
90 | message.reply_text("*notices user*")
91 | log_message = (
92 | f"#UNBLACKLIST\n"
93 | f"Admin: {mention_html(user.id, html.escape(user.first_name))}\n"
94 | f"User: {mention_html(target_user.id, html.escape(target_user.first_name))}"
95 | )
96 |
97 | return log_message
98 |
99 | else:
100 | message.reply_text("I am not ignoring them at all though!")
101 | return ""
102 |
103 |
104 | @dev_plus
105 | def bl_users(update: Update, context: CallbackContext):
106 | users = []
107 | bot = context.bot
108 | for each_user in sql.BLACKLIST_USERS:
109 | user = bot.get_chat(each_user)
110 | reason = sql.get_reason(each_user)
111 |
112 | if reason:
113 | users.append(
114 | f"• {mention_html(user.id, html.escape(user.first_name))} :- {reason}"
115 | )
116 | else:
117 | users.append(f"• {mention_html(user.id, html.escape(user.first_name))}")
118 |
119 | message = "Blacklisted Users\n"
120 | if not users:
121 | message += "None is being ignored as of yet."
122 | else:
123 | message += "\n".join(users)
124 |
125 | update.effective_message.reply_text(message, parse_mode=ParseMode.HTML)
126 |
127 |
128 | def __user_info__(user_id):
129 | is_blacklisted = sql.is_user_blacklisted(user_id)
130 |
131 | text = "Blacklisted: {}"
132 | if user_id in [777000, 1087968824]:
133 | return ""
134 | if user_id == dispatcher.bot.id:
135 | return ""
136 | if int(user_id) in DRAGONS + TIGERS + WOLVES:
137 | return ""
138 | if is_blacklisted:
139 | text = text.format("Yes")
140 | reason = sql.get_reason(user_id)
141 | if reason:
142 | text += f"\nReason: {reason}
"
143 | else:
144 | text = text.format("No")
145 |
146 | return text
147 |
148 |
149 | BL_HANDLER = CommandHandler("ignore", bl_user, run_async=True)
150 | UNBL_HANDLER = CommandHandler("notice", unbl_user, run_async=True)
151 | BLUSERS_HANDLER = CommandHandler("ignoredlist", bl_users, run_async=True)
152 |
153 | dispatcher.add_handler(BL_HANDLER)
154 | dispatcher.add_handler(UNBL_HANDLER)
155 | dispatcher.add_handler(BLUSERS_HANDLER)
156 |
157 | __mod_name__ = "Blacklisting Users"
158 | __handlers__ = [BL_HANDLER, UNBL_HANDLER, BLUSERS_HANDLER]
159 |
--------------------------------------------------------------------------------
/FallenRobot/modules/carbon.py:
--------------------------------------------------------------------------------
1 | from pyrogram import filters
2 |
3 | from FallenRobot import pbot
4 | from FallenRobot.utils.errors import capture_err
5 | from FallenRobot.utils.functions import make_carbon
6 |
7 |
8 | @pbot.on_message(filters.command("carbon"))
9 | @capture_err
10 | async def carbon_func(_, message):
11 | if message.reply_to_message:
12 | if message.reply_to_message.text:
13 | txt = message.reply_to_message.text
14 | else:
15 | return await message.reply_text("ʀᴇᴘʟʏ ᴛᴏ ᴀ ᴍᴇssᴀɢᴇ ᴏʀ ɢɪᴠᴇ sᴏᴍᴇ ᴛᴇxᴛ.")
16 | else:
17 | try:
18 | txt = message.text.split(None, 1)[1]
19 | except IndexError:
20 | return await message.reply_text("ʀᴇᴘʟʏ ᴛᴏ ᴀ ᴍᴇssᴀɢᴇ ᴏʀ ɢɪᴠᴇ sᴏᴍᴇ ᴛᴇxᴛ.")
21 | m = await message.reply_text("ɢᴇɴᴇʀᴀᴛɪɴɢ ᴄᴀʀʙᴏɴ...")
22 | carbon = await make_carbon(txt)
23 | await m.edit_text("ᴜᴩʟᴏᴀᴅɪɴɢ ɢᴇɴᴇʀᴀᴛᴇᴅ ᴄᴀʀʙᴏɴ...")
24 | await pbot.send_photo(
25 | message.chat.id,
26 | photo=carbon,
27 | caption=f"» ʀᴇᴏ̨ᴜᴇsᴛᴇᴅ ʙʏ : {message.from_user.mention}",
28 | )
29 | await m.delete()
30 | carbon.close()
31 |
32 |
33 | __mod_name__ = "Cᴀʀʙᴏɴ"
34 |
35 | __help__ = """
36 | ᴍᴀᴋᴇs ᴀ ᴄᴀʀʙᴏɴ ᴏғ ᴛʜᴇ ɢɪᴠᴇɴ ᴛᴇxᴛ ᴀɴᴅ sᴇɴᴅ ɪᴛ ᴛᴏ ʏᴏᴜ.
37 |
38 | ❍ /carbon *:* ᴍᴀᴋᴇs ᴄᴀʀʙᴏɴ ᴏғ ᴛʜᴇ ɢɪᴠᴇɴ ᴛᴇxᴛ.
39 | """
40 |
--------------------------------------------------------------------------------
/FallenRobot/modules/country.py:
--------------------------------------------------------------------------------
1 | import flag
2 | from countryinfo import CountryInfo
3 |
4 | from FallenRobot import BOT_NAME, telethn
5 | from FallenRobot.events import register
6 |
7 |
8 | @register(pattern="^/country (.*)")
9 | async def msg(event):
10 | if event.fwd_from:
11 | return
12 | input_str = event.pattern_match.group(1)
13 | lol = input_str
14 | country = CountryInfo(lol)
15 | try:
16 | a = country.info()
17 | except:
18 | await event.reply("Country Not Available Currently")
19 | name = a.get("name")
20 | bb = a.get("altSpellings")
21 | hu = ""
22 | for p in bb:
23 | hu += p + ", "
24 |
25 | area = a.get("area")
26 | borders = ""
27 | hell = a.get("borders")
28 | for fk in hell:
29 | borders += fk + ", "
30 |
31 | call = ""
32 | WhAt = a.get("callingCodes")
33 | for what in WhAt:
34 | call += what + " "
35 |
36 | capital = a.get("capital")
37 | currencies = ""
38 | fker = a.get("currencies")
39 | for FKer in fker:
40 | currencies += FKer + ", "
41 |
42 | HmM = a.get("demonym")
43 | geo = a.get("geoJSON")
44 | pablo = geo.get("features")
45 | Pablo = pablo[0]
46 | PAblo = Pablo.get("geometry")
47 | EsCoBaR = PAblo.get("type")
48 | iso = ""
49 | iSo = a.get("ISO")
50 | for hitler in iSo:
51 | po = iSo.get(hitler)
52 | iso += po + ", "
53 | fla = iSo.get("alpha2")
54 | nox = fla.upper()
55 | okie = flag.flag(nox)
56 |
57 | languages = a.get("languages")
58 | lMAO = ""
59 | for lmao in languages:
60 | lMAO += lmao + ", "
61 |
62 | nonive = a.get("nativeName")
63 | waste = a.get("population")
64 | reg = a.get("region")
65 | sub = a.get("subregion")
66 | tik = a.get("timezones")
67 | tom = ""
68 | for jerry in tik:
69 | tom += jerry + ", "
70 |
71 | GOT = a.get("tld")
72 | lanester = ""
73 | for targaryen in GOT:
74 | lanester += targaryen + ", "
75 |
76 | wiki = a.get("wiki")
77 |
78 | caption = f"""Information Gathered Successfully
79 |
80 | Country Name : {name}
81 | Alternative Spellings : {hu}
82 | Country Area : {area} square kilometers
83 | Borders : {borders}
84 | Calling Codes : {call}
85 | Country's Capital : {capital}
86 | Country's currency : {currencies}
87 | Country's Flag : {okie}
88 | Demonym : {HmM}
89 | Country Type : {EsCoBaR}
90 | ISO Names : {iso}
91 | Languages : {lMAO}
92 | Native Name : {nonive}
93 | Population : {waste}
94 | Region : {reg}
95 | Sub Region : {sub}
96 | Time Zones : {tom}
97 | Top Level Domain : {lanester}
98 | Wikipedia : {wiki}
99 |
100 | Information Gathered By {BOT_NAME}
101 | """
102 |
103 | await telethn.send_message(
104 | event.chat_id,
105 | caption,
106 | parse_mode="HTML",
107 | link_preview=None,
108 | )
109 |
110 |
111 | __help__ = """
112 | I will give information about a country
113 |
114 | ❍ /country *:* Gathering info about given country
115 | """
116 |
117 | __mod_name__ = "Cᴏᴜɴᴛʀʏ"
118 |
--------------------------------------------------------------------------------
/FallenRobot/modules/couples.py:
--------------------------------------------------------------------------------
1 | import random
2 | from datetime import datetime
3 |
4 | from pyrogram import filters
5 | from pyrogram.enums import ChatType
6 |
7 | from FallenRobot import pbot
8 | from FallenRobot.utils.mongo import get_couple, save_couple
9 |
10 |
11 | # Date and time
12 | def dt():
13 | now = datetime.now()
14 | dt_string = now.strftime("%d/%m/%Y %H:%M")
15 | dt_list = dt_string.split(" ")
16 | return dt_list
17 |
18 |
19 | def dt_tom():
20 | a = (
21 | str(int(dt()[0].split("/")[0]) + 1)
22 | + "/"
23 | + dt()[0].split("/")[1]
24 | + "/"
25 | + dt()[0].split("/")[2]
26 | )
27 | return a
28 |
29 |
30 | today = str(dt()[0])
31 | tomorrow = str(dt_tom())
32 |
33 |
34 | @pbot.on_message(filters.command(["couple", "couples"]))
35 | async def couple(_, message):
36 | if message.chat.type == ChatType.PRIVATE:
37 | return await message.reply_text("This command only works in groups.")
38 | try:
39 | chat_id = message.chat.id
40 | is_selected = await get_couple(chat_id, today)
41 | if not is_selected:
42 | list_of_users = []
43 | async for i in pbot.get_chat_members(message.chat.id, limit=50):
44 | if not i.user.is_bot:
45 | list_of_users.append(i.user.id)
46 | if len(list_of_users) < 2:
47 | return await message.reply_text("Not enough users")
48 | c1_id = random.choice(list_of_users)
49 | c2_id = random.choice(list_of_users)
50 | while c1_id == c2_id:
51 | c1_id = random.choice(list_of_users)
52 | c1_mention = (await pbot.get_users(c1_id)).mention
53 | c2_mention = (await pbot.get_users(c2_id)).mention
54 |
55 | couple_selection_message = f"""**Couple of the day :**
56 |
57 | {c1_mention} + {c2_mention} = 😘
58 | __New couple of the day can be chosen at 12AM {tomorrow}__"""
59 | await pbot.send_message(message.chat.id, text=couple_selection_message)
60 | couple = {"c1_id": c1_id, "c2_id": c2_id}
61 | await save_couple(chat_id, today, couple)
62 |
63 | elif is_selected:
64 | c1_id = int(is_selected["c1_id"])
65 | c2_id = int(is_selected["c2_id"])
66 | c1_name = (await pbot.get_users(c1_id)).mention
67 | c2_name = (await pbot.get_users(c2_id)).mention
68 | couple_selection_message = f"""Couple of the day :
69 |
70 | {c1_name} + {c2_name} = 😘
71 | __New couple of the day can be chosen at 12AM {tomorrow}__"""
72 | await pbot.send_message(message.chat.id, text=couple_selection_message)
73 | except Exception as e:
74 | print(e)
75 | await message.reply_text(e)
76 |
77 |
78 | __help__ = """
79 | Choose couples in your chat
80 |
81 | ❍ /couple *:* Choose 2 users and send their name as couples in your chat.
82 | """
83 |
84 | __mod_name__ = "Cᴏᴜᴘʟᴇ"
85 |
--------------------------------------------------------------------------------
/FallenRobot/modules/currency_converter.py:
--------------------------------------------------------------------------------
1 | import requests
2 | from telegram import ParseMode, Update
3 | from telegram.ext import CallbackContext, CommandHandler
4 |
5 | from FallenRobot import CASH_API_KEY, dispatcher
6 |
7 |
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 | __mod_name__ = "Cᴀsʜ"
54 |
55 | __help__ = """
56 | Converts money from one exchange to another
57 |
58 | Usage: /cash amount from to
59 | Example: /cash 20 USD INR
60 | """
61 |
62 | CONVERTER_HANDLER = CommandHandler("cash", convert, run_async=True)
63 | dispatcher.add_handler(CONVERTER_HANDLER)
64 | __command_list__ = ["cash"]
65 |
66 | __handlers__ = [CONVERTER_HANDLER]
67 |
--------------------------------------------------------------------------------
/FallenRobot/modules/dbcleanup.py:
--------------------------------------------------------------------------------
1 | from time import sleep
2 |
3 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
4 | from telegram.error import BadRequest, Unauthorized
5 | from telegram.ext import CallbackContext, CallbackQueryHandler, CommandHandler
6 |
7 | import FallenRobot.modules.sql.global_bans_sql as gban_sql
8 | import FallenRobot.modules.sql.users_sql as user_sql
9 | from FallenRobot import DEV_USERS, OWNER_ID, dispatcher
10 | from FallenRobot.modules.helper_funcs.chat_status import dev_plus
11 |
12 |
13 | def get_invalid_chats(update: Update, context: CallbackContext, remove: bool = False):
14 | bot = context.bot
15 | chat_id = update.effective_chat.id
16 | chats = user_sql.get_all_chats()
17 | kicked_chats, progress = 0, 0
18 | chat_list = []
19 | progress_message = None
20 |
21 | for chat in chats:
22 | if ((100 * chats.index(chat)) / len(chats)) > progress:
23 | progress_bar = f"{progress}% completed in getting invalid chats."
24 | if progress_message:
25 | try:
26 | bot.editMessageText(
27 | progress_bar, chat_id, progress_message.message_id
28 | )
29 | except:
30 | pass
31 | else:
32 | progress_message = bot.sendMessage(chat_id, progress_bar)
33 | progress += 5
34 |
35 | cid = chat.chat_id
36 | sleep(0.1)
37 | try:
38 | bot.get_chat(cid, timeout=60)
39 | except (BadRequest, Unauthorized):
40 | kicked_chats += 1
41 | chat_list.append(cid)
42 | except:
43 | pass
44 |
45 | try:
46 | progress_message.delete()
47 | except:
48 | pass
49 |
50 | if not remove:
51 | return kicked_chats
52 | else:
53 | for muted_chat in chat_list:
54 | sleep(0.1)
55 | user_sql.rem_chat(muted_chat)
56 | return kicked_chats
57 |
58 |
59 | def get_invalid_gban(update: Update, context: CallbackContext, remove: bool = False):
60 | bot = context.bot
61 | banned = gban_sql.get_gban_list()
62 | ungbanned_users = 0
63 | ungban_list = []
64 |
65 | for user in banned:
66 | user_id = user["user_id"]
67 | sleep(0.1)
68 | try:
69 | bot.get_chat(user_id)
70 | except BadRequest:
71 | ungbanned_users += 1
72 | ungban_list.append(user_id)
73 | except:
74 | pass
75 |
76 | if not remove:
77 | return ungbanned_users
78 | else:
79 | for user_id in ungban_list:
80 | sleep(0.1)
81 | gban_sql.ungban_user(user_id)
82 | return ungbanned_users
83 |
84 |
85 | @dev_plus
86 | def dbcleanup(update: Update, context: CallbackContext):
87 | msg = update.effective_message
88 |
89 | msg.reply_text("Getting invalid chat count ...")
90 | invalid_chat_count = get_invalid_chats(update, context)
91 |
92 | msg.reply_text("Getting invalid gbanned count ...")
93 | invalid_gban_count = get_invalid_gban(update, context)
94 |
95 | reply = f"Total invalid chats - {invalid_chat_count}\n"
96 | reply += f"Total invalid gbanned users - {invalid_gban_count}"
97 |
98 | buttons = [[InlineKeyboardButton("Cleanup DB", callback_data="db_cleanup")]]
99 |
100 | update.effective_message.reply_text(
101 | reply, reply_markup=InlineKeyboardMarkup(buttons)
102 | )
103 |
104 |
105 | def callback_button(update: Update, context: CallbackContext):
106 | bot = context.bot
107 | query = update.callback_query
108 | message = query.message
109 | chat_id = update.effective_chat.id
110 | query_type = query.data
111 |
112 | admin_list = [OWNER_ID] + DEV_USERS
113 |
114 | bot.answer_callback_query(query.id)
115 |
116 | if query_type == "db_leave_chat":
117 | if query.from_user.id in admin_list:
118 | bot.editMessageText("Leaving chats ...", chat_id, message.message_id)
119 | chat_count = get_muted_chats(update, context, True)
120 | bot.sendMessage(chat_id, f"Left {chat_count} chats.")
121 | else:
122 | query.answer("You are not allowed to use this.")
123 | elif query_type == "db_cleanup":
124 | if query.from_user.id in admin_list:
125 | bot.editMessageText("Cleaning up DB ...", chat_id, message.message_id)
126 | invalid_chat_count = get_invalid_chats(update, context, True)
127 | invalid_gban_count = get_invalid_gban(update, context, True)
128 | reply = "Cleaned up {} chats and {} gbanned users from db.".format(
129 | invalid_chat_count, invalid_gban_count
130 | )
131 | bot.sendMessage(chat_id, reply)
132 | else:
133 | query.answer("You are not allowed to use this.")
134 |
135 |
136 | DB_CLEANUP_HANDLER = CommandHandler("dbcleanup", dbcleanup, run_async=True)
137 | BUTTON_HANDLER = CallbackQueryHandler(callback_button, pattern="db_.*", run_async=True)
138 |
139 | dispatcher.add_handler(DB_CLEANUP_HANDLER)
140 | dispatcher.add_handler(BUTTON_HANDLER)
141 |
142 | __mod_name__ = "DB Cleanup"
143 | __handlers__ = [DB_CLEANUP_HANDLER, BUTTON_HANDLER]
144 |
--------------------------------------------------------------------------------
/FallenRobot/modules/debug.py:
--------------------------------------------------------------------------------
1 | import datetime
2 | import os
3 |
4 | from telegram import Update
5 | from telegram.ext import CallbackContext, CommandHandler
6 | from telethon import events
7 |
8 | from FallenRobot import dispatcher, telethn
9 | from FallenRobot.modules.helper_funcs.chat_status import dev_plus
10 |
11 | DEBUG_MODE = False
12 |
13 |
14 | @dev_plus
15 | def debug(update: Update, context: CallbackContext):
16 | global DEBUG_MODE
17 | args = update.effective_message.text.split(None, 1)
18 | message = update.effective_message
19 | print(DEBUG_MODE)
20 | if len(args) > 1:
21 | if args[1] in ("yes", "on"):
22 | DEBUG_MODE = True
23 | message.reply_text("Debug mode is now on.")
24 | elif args[1] in ("no", "off"):
25 | DEBUG_MODE = False
26 | message.reply_text("Debug mode is now off.")
27 | else:
28 | if DEBUG_MODE:
29 | message.reply_text("Debug mode is currently on.")
30 | else:
31 | message.reply_text("Debug mode is currently off.")
32 |
33 |
34 | @telethn.on(events.NewMessage(pattern="[/!].*"))
35 | async def i_do_nothing_yes(event):
36 | global DEBUG_MODE
37 | if DEBUG_MODE:
38 | print(f"-{event.from_id} ({event.chat_id}) : {event.text}")
39 | if os.path.exists("updates.txt"):
40 | with open("updates.txt", "r") as f:
41 | text = f.read()
42 | with open("updates.txt", "w+") as f:
43 | f.write(text + f"\n-{event.from_id} ({event.chat_id}) : {event.text}")
44 | else:
45 | with open("updates.txt", "w+") as f:
46 | f.write(
47 | f"- {event.from_id} ({event.chat_id}) : {event.text} | {datetime.datetime.now()}"
48 | )
49 |
50 |
51 | @dev_plus
52 | def logs(update: Update, context: CallbackContext):
53 | user = update.effective_user
54 | with open("log.txt", "rb") as f:
55 | context.bot.send_document(document=f, filename=f.name, chat_id=user.id)
56 |
57 |
58 | LOG_HANDLER = CommandHandler("logs", logs, run_async=True)
59 | DEBUG_HANDLER = CommandHandler("debug", debug, run_async=True)
60 |
61 | dispatcher.add_handler(LOG_HANDLER)
62 | dispatcher.add_handler(DEBUG_HANDLER)
63 |
64 | __mod_name__ = "Debug"
65 | __command_list__ = ["debug"]
66 | __handlers__ = [DEBUG_HANDLER]
67 |
--------------------------------------------------------------------------------
/FallenRobot/modules/dev.py:
--------------------------------------------------------------------------------
1 | import os
2 | import subprocess
3 | import sys
4 | from contextlib import suppress
5 | from time import sleep
6 |
7 | from telegram import TelegramError, Update
8 | from telegram.error import Unauthorized
9 | from telegram.ext import CallbackContext, CommandHandler
10 |
11 | import FallenRobot
12 | from FallenRobot import dispatcher
13 | from FallenRobot.modules.helper_funcs.chat_status import dev_plus
14 |
15 |
16 | @dev_plus
17 | def allow_groups(update: Update, context: CallbackContext):
18 | args = context.args
19 | if not args:
20 | update.effective_message.reply_text(f"Current state: {FallenRobot.ALLOW_CHATS}")
21 | return
22 | if args[0].lower() in ["off", "no"]:
23 | FallenRobot.ALLOW_CHATS = True
24 | elif args[0].lower() in ["yes", "on"]:
25 | FallenRobot.ALLOW_CHATS = False
26 | else:
27 | update.effective_message.reply_text("Format: /lockdown Yes/No or Off/On")
28 | return
29 | update.effective_message.reply_text("Done! Lockdown value toggled.")
30 |
31 |
32 | @dev_plus
33 | def leave(update: Update, context: CallbackContext):
34 | bot = context.bot
35 | args = context.args
36 | if args:
37 | chat_id = str(args[0])
38 | try:
39 | bot.leave_chat(int(chat_id))
40 | except TelegramError:
41 | update.effective_message.reply_text(
42 | "Beep boop, I could not leave that group(dunno why tho)."
43 | )
44 | return
45 | with suppress(Unauthorized):
46 | update.effective_message.reply_text("Beep boop, I left that soup!.")
47 | else:
48 | update.effective_message.reply_text("Send a valid chat ID")
49 |
50 |
51 | @dev_plus
52 | def gitpull(update: Update, context: CallbackContext):
53 | sent_msg = update.effective_message.reply_text(
54 | "Pulling all changes from remote and then attempting to restart."
55 | )
56 | subprocess.Popen("git pull", stdout=subprocess.PIPE, shell=True)
57 |
58 | sent_msg_text = sent_msg.text + "\n\nChanges pulled...I guess.. Restarting in "
59 |
60 | for i in reversed(range(5)):
61 | sent_msg.edit_text(sent_msg_text + str(i + 1))
62 | sleep(1)
63 |
64 | sent_msg.edit_text("Restarted.")
65 |
66 | os.system("restart.bat")
67 | os.execv("start.bat", sys.argv)
68 |
69 |
70 | @dev_plus
71 | def restart(update: Update, context: CallbackContext):
72 | update.effective_message.reply_text(
73 | "Starting a new instance and shutting down this one"
74 | )
75 |
76 | os.system("restart.bat")
77 | os.execv("start.bat", sys.argv)
78 |
79 |
80 | LEAVE_HANDLER = CommandHandler("leave", leave, run_async=True)
81 | GITPULL_HANDLER = CommandHandler("gitpull", gitpull, run_async=True)
82 | RESTART_HANDLER = CommandHandler("reboot", restart, run_async=True)
83 | ALLOWGROUPS_HANDLER = CommandHandler("lockdown", allow_groups, run_async=True)
84 |
85 |
86 | dispatcher.add_handler(ALLOWGROUPS_HANDLER)
87 | dispatcher.add_handler(LEAVE_HANDLER)
88 | dispatcher.add_handler(GITPULL_HANDLER)
89 | dispatcher.add_handler(RESTART_HANDLER)
90 |
91 | __mod_name__ = "Dᴇᴠ"
92 |
93 | __handlers__ = [LEAVE_HANDLER, GITPULL_HANDLER, RESTART_HANDLER, ALLOWGROUPS_HANDLER]
94 |
--------------------------------------------------------------------------------
/FallenRobot/modules/encrypt.py:
--------------------------------------------------------------------------------
1 | import secureme
2 |
3 | from FallenRobot.events import register
4 |
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 |
18 | @register(pattern="^/decrypt ?(.*)")
19 | async def hmm(event):
20 | if event.reply_to_msg_id:
21 | lel = await event.get_reply_message()
22 | ok = lel.text
23 | else:
24 | ok = event.pattern_match.group(1)
25 | Text = ok
26 | k = secureme.decrypt(Text)
27 | await event.reply(k)
28 |
29 |
30 | __mod_name__ = "Tᴏᴏʟs"
31 |
32 | __help__ = """
33 |
34 | *ᴄᴏɴᴠᴇʀᴛs*
35 | ❍ /encrypt*:* ᴇɴᴄʀʏᴘᴛs ᴛʜᴇ ɢɪᴠᴇɴ ᴛᴇxᴛ
36 | ❍ /decrypt*:* ᴅᴇᴄʀʏᴘᴛs ᴘʀᴇᴠɪᴏᴜsʟʏ ᴇᴄʀʏᴘᴛᴇᴅ ᴛᴇxᴛ
37 | """
38 |
--------------------------------------------------------------------------------
/FallenRobot/modules/english.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | import requests
4 | from PyDictionary import PyDictionary
5 | from telethon import *
6 | from telethon.tl.types import *
7 |
8 | from FallenRobot.events import register
9 |
10 | API_KEY = "6ae0c3a0-afdc-4532-a810-82ded0054236"
11 | URL = "http://services.gingersoftware.com/Ginger/correct/json/GingerTheText"
12 |
13 |
14 | @register(pattern="^/spell(?: |$)(.*)")
15 | async def _(event):
16 | ctext = await event.get_reply_message()
17 | msg = ctext.text
18 | # print (msg)
19 | params = dict(lang="US", clientVersion="2.0", apiKey=API_KEY, text=msg)
20 |
21 | res = requests.get(URL, params=params)
22 | changes = json.loads(res.text).get("LightGingerTheTextResult")
23 | curr_string = ""
24 | prev_end = 0
25 |
26 | for change in changes:
27 | start = change.get("From")
28 | end = change.get("To") + 1
29 | suggestions = change.get("Suggestions")
30 | if suggestions:
31 | sugg_str = suggestions[0].get("Text")
32 | curr_string += msg[prev_end:start] + sugg_str
33 | prev_end = end
34 |
35 | curr_string += msg[prev_end:]
36 | await event.reply(curr_string)
37 |
38 |
39 | dictionary = PyDictionary()
40 |
41 |
42 | @register(pattern="^/define")
43 | async def _(event):
44 | text = event.text[len("/define ") :]
45 | word = f"{text}"
46 | let = dictionary.meaning(word)
47 | set = str(let)
48 | jet = set.replace("{", "")
49 | net = jet.replace("}", "")
50 | got = net.replace("'", "")
51 | await event.reply(got)
52 |
53 |
54 | @register(pattern="^/synonyms")
55 | async def _(event):
56 | text = event.text[len("/synonyms ") :]
57 | word = f"{text}"
58 | let = dictionary.synonym(word)
59 | set = str(let)
60 | jet = set.replace("{", "")
61 | net = jet.replace("}", "")
62 | got = net.replace("'", "")
63 | await event.reply(got)
64 |
65 |
66 | @register(pattern="^/antonyms")
67 | async def _(event):
68 | text = message.text[len("/antonyms ") :]
69 | word = f"{text}"
70 | let = dictionary.antonym(word)
71 | set = str(let)
72 | jet = set.replace("{", "")
73 | net = jet.replace("}", "")
74 | got = net.replace("'", "")
75 | await event.reply(got)
76 |
77 |
78 | __help__ = """
79 | ❍ /define *:* Type the word or expression you want to search\nFor example /define kill
80 | ❍ /spell*:* while replying to a message, will reply with a grammar corrected version
81 | ❍ /synonyms *:* Find the synonyms of a word
82 | ❍ /antonyms *:* Find the antonyms of a word
83 | """
84 |
85 | __mod_name__ = "Eɴɢʟɪsʜ"
86 |
--------------------------------------------------------------------------------
/FallenRobot/modules/error_handler.py:
--------------------------------------------------------------------------------
1 | import html
2 | import io
3 | import random
4 | import sys
5 | import traceback
6 |
7 | import pretty_errors
8 | import requests
9 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
10 | from telegram.ext import CallbackContext, CommandHandler
11 |
12 | from FallenRobot import DEV_USERS, OWNER_ID, dispatcher
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([[InlineKeyboardButton("ɴᴇᴋᴏʙɪɴ", url=url)]]),
99 | parse_mode="html",
100 | )
101 |
102 |
103 | def list_errors(update: Update, context: CallbackContext):
104 | if update.effective_user.id not in DEV_USERS:
105 | return
106 | e = {
107 | k: v for k, v in sorted(errors.items(), key=lambda item: item[1], reverse=True)
108 | }
109 | msg = "Errors List:\n"
110 | for x in e:
111 | msg += f"• {x}:
{e[x]} #{x.identifier}\n"
112 | msg += f"{len(errors)} have occurred since startup."
113 | if len(msg) > 4096:
114 | with open("errors_msg.txt", "w+") as f:
115 | f.write(msg)
116 | context.bot.send_document(
117 | update.effective_chat.id,
118 | open("errors_msg.txt", "rb"),
119 | caption=f"Too many errors have occured..",
120 | parse_mode="html",
121 | )
122 | return
123 | update.effective_message.reply_text(msg, parse_mode="html")
124 |
125 |
126 | dispatcher.add_error_handler(error_callback, run_async=True)
127 | dispatcher.add_handler(CommandHandler("errors", list_errors, run_async=True))
128 |
--------------------------------------------------------------------------------
/FallenRobot/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 telegram import ParseMode, Update
10 | from telegram.ext import CallbackContext, CommandHandler
11 |
12 | from FallenRobot import LOGGER, dispatcher
13 | from FallenRobot.modules.helper_funcs.chat_status import dev_plus
14 |
15 | namespaces = {}
16 |
17 |
18 | def namespace_of(chat, update, bot):
19 | if chat not in namespaces:
20 | namespaces[chat] = {
21 | "__builtins__": globals()["__builtins__"],
22 | "bot": bot,
23 | "effective_message": update.effective_message,
24 | "effective_user": update.effective_user,
25 | "effective_chat": update.effective_chat,
26 | "update": update,
27 | }
28 |
29 | return namespaces[chat]
30 |
31 |
32 | def log_input(update):
33 | user = update.effective_user.id
34 | chat = update.effective_chat.id
35 | LOGGER.info(f"IN: {update.effective_message.text} (user={user}, chat={chat})")
36 |
37 |
38 | def send(msg, bot, update):
39 | if len(str(msg)) > 2000:
40 | with io.BytesIO(str.encode(msg)) as out_file:
41 | out_file.name = "output.txt"
42 | bot.send_document(chat_id=update.effective_chat.id, document=out_file)
43 | else:
44 | LOGGER.info(f"OUT: '{msg}'")
45 | bot.send_message(
46 | chat_id=update.effective_chat.id,
47 | text=f"`{msg}`",
48 | parse_mode=ParseMode.MARKDOWN,
49 | )
50 |
51 |
52 | @dev_plus
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 | def execute(update: Update, context: CallbackContext):
60 | bot = context.bot
61 | send(do(exec, bot, update), bot, update)
62 |
63 |
64 | def cleanup_code(code):
65 | if code.startswith("```") and code.endswith("```"):
66 | return "\n".join(code.split("\n")[1:-1])
67 | return code.strip("` \n")
68 |
69 |
70 | def do(func, bot, update):
71 | log_input(update)
72 | content = update.message.text.split(" ", 1)[-1]
73 | body = cleanup_code(content)
74 | env = namespace_of(update.message.chat_id, update, bot)
75 |
76 | os.chdir(os.getcwd())
77 | with open(
78 | os.path.join(os.getcwd(), "FallenRobot/modules/helper_funcs/temp.txt"), "w"
79 | ) as temp:
80 | temp.write(body)
81 |
82 | stdout = io.StringIO()
83 |
84 | to_compile = f'def func():\n{textwrap.indent(body, " ")}'
85 |
86 | try:
87 | exec(to_compile, env)
88 | except Exception as e:
89 | return f"{e.__class__.__name__}: {e}"
90 |
91 | func = env["func"]
92 |
93 | try:
94 | with redirect_stdout(stdout):
95 | func_return = func()
96 | except Exception:
97 | value = stdout.getvalue()
98 | return f"{value}{traceback.format_exc()}"
99 | else:
100 | value = stdout.getvalue()
101 | result = None
102 | if func_return is None:
103 | if value:
104 | result = f"{value}"
105 | else:
106 | try:
107 | result = f"{repr(eval(body, env))}"
108 | except:
109 | pass
110 | else:
111 | result = f"{value}{func_return}"
112 | if result:
113 | return result
114 |
115 |
116 | @dev_plus
117 | def clear(update: Update, context: CallbackContext):
118 | bot = context.bot
119 | log_input(update)
120 | global namespaces
121 | if update.message.chat_id in namespaces:
122 | del namespaces[update.message.chat_id]
123 | send("Cleared locals.", bot, update)
124 |
125 |
126 | EVAL_HANDLER = CommandHandler(("e", "ev", "eva", "eval"), evaluate, run_async=True)
127 | EXEC_HANDLER = CommandHandler(("x", "ex", "exe", "exec", "py"), execute, run_async=True)
128 | CLEAR_HANDLER = CommandHandler("clearlocals", clear, run_async=True)
129 |
130 | dispatcher.add_handler(EVAL_HANDLER)
131 | dispatcher.add_handler(EXEC_HANDLER)
132 | dispatcher.add_handler(CLEAR_HANDLER)
133 |
134 | __mod_name__ = "Eᴠᴀʟ ᴍᴏᴅᴜʟᴇ"
135 |
--------------------------------------------------------------------------------
/FallenRobot/modules/get_common_chats.py:
--------------------------------------------------------------------------------
1 | import os
2 | from time import sleep
3 |
4 | from telegram import Update
5 | from telegram.error import BadRequest, RetryAfter, Unauthorized
6 | from telegram.ext import CallbackContext, CommandHandler, Filters
7 |
8 | from FallenRobot import OWNER_ID, dispatcher
9 | from FallenRobot.modules.helper_funcs.extraction import extract_user
10 | from FallenRobot.modules.sql.users_sql import get_user_com_chats
11 |
12 |
13 | def get_user_common_chats(update: Update, context: CallbackContext):
14 | bot, args = context.bot, context.args
15 | msg = update.effective_message
16 | user = extract_user(msg, args)
17 | if not user:
18 | msg.reply_text("I share no common chats with the void.")
19 | return
20 | common_list = get_user_com_chats(user)
21 | if not common_list:
22 | msg.reply_text("No common chats with this user!")
23 | return
24 | name = bot.get_chat(user).first_name
25 | text = f"Common chats with {name}\n"
26 | for chat in common_list:
27 | try:
28 | chat_name = bot.get_chat(chat).title
29 | sleep(0.3)
30 | text += f"• {chat_name}
\n"
31 | except BadRequest:
32 | pass
33 | except Unauthorized:
34 | pass
35 | except RetryAfter as e:
36 | sleep(e.retry_after)
37 |
38 | if len(text) < 4096:
39 | msg.reply_text(text, parse_mode="HTML")
40 | else:
41 | with open("common_chats.txt", "w") as f:
42 | f.write(text)
43 | with open("common_chats.txt", "rb") as f:
44 | msg.reply_document(f)
45 | os.remove("common_chats.txt")
46 |
47 |
48 | COMMON_CHATS_HANDLER = CommandHandler(
49 | "getchats", get_user_common_chats, filters=Filters.user(OWNER_ID), run_async=True
50 | )
51 |
52 | dispatcher.add_handler(COMMON_CHATS_HANDLER)
53 |
--------------------------------------------------------------------------------
/FallenRobot/modules/gettime.py:
--------------------------------------------------------------------------------
1 | import datetime
2 | from typing import List
3 |
4 | import requests
5 | from telegram import ParseMode, Update
6 | from telegram.ext import CallbackContext
7 |
8 | from FallenRobot import TIME_API_KEY, dispatcher
9 | from FallenRobot.modules.disable import DisableAbleCommandHandler
10 |
11 |
12 | def generate_time(to_find: str, findtype: List[str]) -> str:
13 | data = requests.get(
14 | f"https://api.timezonedb.com/v2.1/list-time-zone"
15 | f"?key={TIME_API_KEY}"
16 | f"&format=json"
17 | f"&fields=countryCode,countryName,zoneName,gmtOffset,timestamp,dst"
18 | ).json()
19 |
20 | for zone in data["zones"]:
21 | for eachtype in findtype:
22 | if to_find in zone[eachtype].lower():
23 | country_name = zone["countryName"]
24 | country_zone = zone["zoneName"]
25 | country_code = zone["countryCode"]
26 |
27 | if zone["dst"] == 1:
28 | daylight_saving = "Yes"
29 | else:
30 | daylight_saving = "No"
31 |
32 | date_fmt = r"%d-%m-%Y"
33 | time_fmt = r"%H:%M:%S"
34 | day_fmt = r"%A"
35 | gmt_offset = zone["gmtOffset"]
36 | timestamp = datetime.datetime.now(
37 | datetime.timezone.utc
38 | ) + datetime.timedelta(seconds=gmt_offset)
39 | current_date = timestamp.strftime(date_fmt)
40 | current_time = timestamp.strftime(time_fmt)
41 | current_day = timestamp.strftime(day_fmt)
42 |
43 | break
44 |
45 | try:
46 | result = (
47 | f"Country: {country_name}
\n"
48 | f"Zone Name: {country_zone}
\n"
49 | f"Country Code: {country_code}
\n"
50 | f"Daylight saving: {daylight_saving}
\n"
51 | f"Day: {current_day}
\n"
52 | f"Current Time: {current_time}
\n"
53 | f"Current Date: {current_date}
\n"
54 | 'Timezones: List here'
55 | )
56 | except:
57 | result = None
58 |
59 | return result
60 |
61 |
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 | __help__ = """
95 | ❍ /time *:* Gives information about a timezone.
96 | *Available queries:* Country Code/Country Name/Timezone Name
97 |
98 | ❍ ⏰ [ᴛɪᴍᴇᴢᴏɴᴇs ʟɪsᴛ](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)
99 |
100 | 💡 Ex:- /time IN *:* It will shows Indian current time and date..
101 | """
102 |
103 | TIME_HANDLER = DisableAbleCommandHandler("time", gettime, run_async=True)
104 |
105 | dispatcher.add_handler(TIME_HANDLER)
106 |
107 | __mod_name__ = "Tɪᴍᴇ"
108 | __command_list__ = ["time"]
109 | __handlers__ = [TIME_HANDLER]
110 |
--------------------------------------------------------------------------------
/FallenRobot/modules/gitinfo.py:
--------------------------------------------------------------------------------
1 | from aiohttp import ClientSession
2 | from pyrogram import filters
3 |
4 | from FallenRobot import pbot
5 | from FallenRobot.utils.errors import capture_err
6 |
7 |
8 | @pbot.on_message(filters.command("github"))
9 | @capture_err
10 | async def github(_, message):
11 | if len(message.command) != 2:
12 | return await message.reply_text("/git username")
13 | username = message.text.split(None, 1)[1]
14 | URL = f"https://api.github.com/users/{username}"
15 | async with ClientSession() as session:
16 | async with session.get(URL) as request:
17 | if request.status == 404:
18 | return await message.reply_text("404")
19 | result = await request.json()
20 | try:
21 | url = result["html_url"]
22 | name = result["name"]
23 | company = result["company"]
24 | bio = result["bio"]
25 | created_at = result["created_at"]
26 | avatar_url = result["avatar_url"]
27 | blog = result["blog"]
28 | location = result["location"]
29 | repositories = result["public_repos"]
30 | followers = result["followers"]
31 | following = result["following"]
32 | caption = f"""**Info Of {name}**
33 | **Username :** `{username}`
34 | **Bio :** `{bio}`
35 | **Profile Link :** [Here]({url})
36 | **Company :** `{company}`
37 | **Created On :** `{created_at}`
38 | **Repositories :** `{repositories}`
39 | **Blog :** `{blog}`
40 | **Location :** `{location}`
41 | **Followers :** `{followers}`
42 | **Following :** `{following}`"""
43 | except:
44 | print(str(e))
45 | await message.reply_photo(photo=avatar_url, caption=caption)
46 |
47 |
48 | __mod_name__ = "Gɪᴛʜᴜʙ"
49 |
50 | __help__ = """
51 | Provides you information about a github profile
52 |
53 | ❍ /github *:* Get information about a GitHub user.
54 | """
55 |
--------------------------------------------------------------------------------
/FallenRobot/modules/gps.py:
--------------------------------------------------------------------------------
1 | from geopy.geocoders import Nominatim
2 | from telethon import *
3 | from telethon.tl import *
4 |
5 | from FallenRobot import *
6 | from FallenRobot import telethn as tbot
7 | from FallenRobot.events import register
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="FallenRobot")
18 | geoloc = geolocator.geocode(args)
19 | gm = f"https://www.google.com/maps/search/{geoloc.latitude},{geoloc.longitude}"
20 | await tbot.send_file(
21 | event.chat_id,
22 | file=types.InputMediaGeoPoint(
23 | types.InputGeoPoint(float(geoloc.latitude), float(geoloc.longitude))
24 | ),
25 | )
26 | await event.reply(
27 | f"ᴏᴘᴇɴ ᴡɪᴛʜ : [🌏ɢᴏᴏɢʟᴇ ᴍᴀᴘs]({gm})",
28 | link_preview=False,
29 | )
30 | except:
31 | await event.reply("I can't find that")
32 |
33 |
34 | __help__ = """
35 | Sends you the gps location of the given query...
36 |
37 | ❍ /gps *:* Get gps location.
38 | """
39 |
40 | __mod_name__ = "Gᴘs"
41 |
--------------------------------------------------------------------------------
/FallenRobot/modules/group.py:
--------------------------------------------------------------------------------
1 | __help__ = """
2 | ❍ /setgtitle *:* Sets new chat title in your group.
3 | ❍ /setgpic*:* As a reply to file or photo to set group profile pic!
4 | ❍ /delgpic*:* Same as above but to remove group profile pic.
5 | ❍ /setsticker*:* As a reply to some sticker to set it as group sticker set!
6 | ❍ /setdescription *:* Sets new chat description in group.
7 | """
8 |
9 | __mod_name__ = "Gʀᴏᴜᴘ"
10 |
--------------------------------------------------------------------------------
/FallenRobot/modules/helper_funcs/__init__.py:
--------------------------------------------------------------------------------
1 | """Helpers, also known as Utilities"""
2 |
--------------------------------------------------------------------------------
/FallenRobot/modules/helper_funcs/admin_rights.py:
--------------------------------------------------------------------------------
1 | from telegram import Chat, User
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 |
--------------------------------------------------------------------------------
/FallenRobot/modules/helper_funcs/alternate.py:
--------------------------------------------------------------------------------
1 | from functools import wraps
2 |
3 | from telegram import ChatAction
4 | from telegram.error import BadRequest
5 |
6 |
7 | def send_message(message, text, *args, **kwargs):
8 | try:
9 | return message.reply_text(text, *args, **kwargs)
10 | except BadRequest as err:
11 | if str(err) == "Reply message not found":
12 | return message.reply_text(text, quote=False, *args, **kwargs)
13 |
14 |
15 | def typing_action(func):
16 | """Sends typing action while processing func command."""
17 |
18 | @wraps(func)
19 | def command_func(update, context, *args, **kwargs):
20 | context.bot.send_chat_action(
21 | chat_id=update.effective_chat.id, action=ChatAction.TYPING
22 | )
23 | return func(update, context, *args, **kwargs)
24 |
25 | return command_func
26 |
--------------------------------------------------------------------------------
/FallenRobot/modules/helper_funcs/filters.py:
--------------------------------------------------------------------------------
1 | from telegram import Message
2 | from telegram.ext import MessageFilter
3 |
4 | from FallenRobot import DEMONS, DEV_USERS, DRAGONS
5 |
6 |
7 | class CustomFilters(object):
8 | class _Supporters(MessageFilter):
9 | def filter(self, message: Message):
10 | return bool(message.from_user and message.from_user.id in DEMONS)
11 |
12 | support_filter = _Supporters()
13 |
14 | class Sudoers(MessageFilter):
15 | def filter(self, message: Message):
16 | return bool(message.from_user and message.from_user.id in DRAGONS)
17 |
18 | sudo_filter = Sudoers()
19 |
20 | class Developers(MessageFilter):
21 | def filter(self, message: Message):
22 | return bool(message.from_user and message.from_user.id in DEV_USERS)
23 |
24 | dev_filter = Developers()
25 |
26 | class _MimeType(MessageFilter):
27 | def __init__(self, mimetype):
28 | self.mime_type = mimetype
29 | self.name = "CustomFilters.mime_type({})".format(self.mime_type)
30 |
31 | def filter(self, message: Message):
32 | return bool(
33 | message.document and message.document.mime_type == self.mime_type,
34 | )
35 |
36 | mime_type = _MimeType
37 |
38 | class _HasText(MessageFilter):
39 | def filter(self, message: Message):
40 | return bool(
41 | message.text
42 | or message.sticker
43 | or message.photo
44 | or message.document
45 | or message.video,
46 | )
47 |
48 | has_text = _HasText()
49 |
--------------------------------------------------------------------------------
/FallenRobot/modules/helper_funcs/handlers.py:
--------------------------------------------------------------------------------
1 | from pyrate_limiter import (
2 | BucketFullException,
3 | Duration,
4 | Limiter,
5 | MemoryListBucket,
6 | RequestRate,
7 | )
8 | from telegram import Update
9 | from telegram.ext import CommandHandler, Filters, MessageHandler, RegexHandler
10 |
11 | import FallenRobot.modules.sql.blacklistusers_sql as sql
12 | from FallenRobot import ALLOW_EXCL, DEMONS, DEV_USERS, DRAGONS, TIGERS, WOLVES
13 |
14 | if ALLOW_EXCL:
15 | CMD_STARTERS = ("/", "!")
16 | else:
17 | CMD_STARTERS = "/"
18 |
19 |
20 | class AntiSpam:
21 | def __init__(self):
22 | self.whitelist = (
23 | (DEV_USERS or [])
24 | + (DRAGONS or [])
25 | + (WOLVES or [])
26 | + (DEMONS or [])
27 | + (TIGERS or [])
28 | )
29 | # 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.
30 | Duration.CUSTOM = 15 # Custom duration, 15 seconds
31 | self.sec_limit = RequestRate(6, Duration.CUSTOM) # 6 / Per 15 Seconds
32 | self.min_limit = RequestRate(20, Duration.MINUTE) # 20 / Per minute
33 | self.hour_limit = RequestRate(100, Duration.HOUR) # 100 / Per hour
34 | self.daily_limit = RequestRate(1000, Duration.DAY) # 1000 / Per day
35 | self.limiter = Limiter(
36 | self.sec_limit,
37 | self.min_limit,
38 | self.hour_limit,
39 | self.daily_limit,
40 | bucket_class=MemoryListBucket,
41 | )
42 |
43 | def check_user(self, user):
44 | """
45 | Return True if user is to be ignored else False
46 | """
47 | if user in self.whitelist:
48 | return False
49 | try:
50 | self.limiter.try_acquire(user)
51 | return False
52 | except BucketFullException:
53 | return True
54 |
55 |
56 | SpamChecker = AntiSpam()
57 | MessageHandlerChecker = AntiSpam()
58 |
59 |
60 | class CustomCommandHandler(CommandHandler):
61 | def __init__(self, command, callback, admin_ok=False, allow_edit=False, **kwargs):
62 | super().__init__(command, callback, **kwargs)
63 |
64 | if allow_edit is False:
65 | self.filters &= ~(
66 | Filters.update.edited_message | Filters.update.edited_channel_post
67 | )
68 |
69 | def check_update(self, update):
70 | if isinstance(update, Update) and update.effective_message:
71 | message = update.effective_message
72 |
73 | try:
74 | user_id = update.effective_user.id
75 | except:
76 | user_id = None
77 |
78 | if user_id:
79 | if sql.is_user_blacklisted(user_id):
80 | return False
81 |
82 | if message.text and len(message.text) > 1:
83 | fst_word = message.text.split(None, 1)[0]
84 | if len(fst_word) > 1 and any(
85 | fst_word.startswith(start) for start in CMD_STARTERS
86 | ):
87 | args = message.text.split()[1:]
88 | command = fst_word[1:].split("@")
89 | command.append(message.bot.username)
90 | if user_id == 1087968824:
91 | user_id = update.effective_chat.id
92 | if not (
93 | command[0].lower() in self.command
94 | and command[1].lower() == message.bot.username.lower()
95 | ):
96 | return None
97 | if SpamChecker.check_user(user_id):
98 | return None
99 | filter_result = self.filters(update)
100 | if filter_result:
101 | return args, filter_result
102 | else:
103 | return False
104 |
105 | def handle_update(self, update, dispatcher, check_result, context=None):
106 | if context:
107 | self.collect_additional_context(context, update, dispatcher, check_result)
108 | return self.callback(update, context)
109 | else:
110 | optional_args = self.collect_optional_args(dispatcher, update, check_result)
111 | return self.callback(dispatcher.bot, update, **optional_args)
112 |
113 | def collect_additional_context(self, context, update, dispatcher, check_result):
114 | if isinstance(check_result, bool):
115 | context.args = update.effective_message.text.split()[1:]
116 | else:
117 | context.args = check_result[0]
118 | if isinstance(check_result[1], dict):
119 | context.update(check_result[1])
120 |
121 |
122 | class CustomRegexHandler(RegexHandler):
123 | def __init__(self, pattern, callback, friendly="", **kwargs):
124 | super().__init__(pattern, callback, **kwargs)
125 |
126 |
127 | class CustomMessageHandler(MessageHandler):
128 | def __init__(self, filters, callback, friendly="", allow_edit=False, **kwargs):
129 | super().__init__(filters, callback, **kwargs)
130 | if allow_edit is False:
131 | self.filters &= ~(
132 | Filters.update.edited_message | Filters.update.edited_channel_post
133 | )
134 |
135 | def check_update(self, update):
136 | if isinstance(update, Update) and update.effective_message:
137 | return self.filters(update)
138 |
--------------------------------------------------------------------------------
/FallenRobot/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 |
26 |
27 | #
28 |
--------------------------------------------------------------------------------
/FallenRobot/modules/helper_funcs/telethn/__init__.py:
--------------------------------------------------------------------------------
1 | from FallenRobot import DEMONS, DEV_USERS, DRAGONS, 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 |
--------------------------------------------------------------------------------
/FallenRobot/modules/helper_funcs/telethn/chatstatus.py:
--------------------------------------------------------------------------------
1 | from telethon.tl.types import ChannelParticipantsAdmins
2 |
3 | from FallenRobot import DRAGONS
4 | from FallenRobot.modules.helper_funcs.telethn import IMMUNE_USERS, telethn
5 |
6 |
7 | async def user_is_ban_protected(user_id: int, message):
8 | status = False
9 | if message.is_private or user_id in (IMMUNE_USERS):
10 | return True
11 |
12 | async for user in telethn.iter_participants(
13 | message.chat_id, filter=ChannelParticipantsAdmins
14 | ):
15 | if user_id == user.id:
16 | status = True
17 | break
18 | return status
19 |
20 |
21 | async def user_is_admin(user_id: int, message):
22 | status = False
23 | if message.is_private:
24 | return True
25 |
26 | async for user in telethn.iter_participants(
27 | message.chat_id, filter=ChannelParticipantsAdmins
28 | ):
29 | if user_id == user.id or user_id in DRAGONS:
30 | status = True
31 | break
32 | return status
33 |
34 |
35 | async def is_user_admin(user_id: int, chat_id):
36 | status = False
37 | async for user in telethn.iter_participants(
38 | chat_id, filter=ChannelParticipantsAdmins
39 | ):
40 | if user_id == user.id or user_id in DRAGONS:
41 | status = True
42 | break
43 | return status
44 |
45 |
46 | async def fallen_is_admin(chat_id: int):
47 | status = False
48 | fallen = await telethn.get_me()
49 | async for user in telethn.iter_participants(
50 | chat_id, filter=ChannelParticipantsAdmins
51 | ):
52 | if fallen.id == user.id:
53 | status = True
54 | break
55 | return status
56 |
57 |
58 | async def is_user_in_chat(chat_id: int, user_id: int):
59 | status = False
60 | async for user in telethn.iter_participants(chat_id):
61 | if user_id == user.id:
62 | status = True
63 | break
64 | return status
65 |
66 |
67 | async def can_change_info(message):
68 | status = False
69 | if message.chat.admin_rights:
70 | status = message.chat.admin_rights.change_info
71 | return status
72 |
73 |
74 | async def can_ban_users(message):
75 | status = False
76 | if message.chat.admin_rights:
77 | status = message.chat.admin_rights.ban_users
78 | return status
79 |
80 |
81 | async def can_pin_messages(message):
82 | status = False
83 | if message.chat.admin_rights:
84 | status = message.chat.admin_rights.pin_messages
85 | return status
86 |
87 |
88 | async def can_invite_users(message):
89 | status = False
90 | if message.chat.admin_rights:
91 | status = message.chat.admin_rights.invite_users
92 | return status
93 |
94 |
95 | async def can_add_admins(message):
96 | status = False
97 | if message.chat.admin_rights:
98 | status = message.chat.admin_rights.add_admins
99 | return status
100 |
101 |
102 | async def can_delete_messages(message):
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 |
--------------------------------------------------------------------------------
/FallenRobot/modules/json.py:
--------------------------------------------------------------------------------
1 | import io
2 |
3 | from telethon import types
4 | from telethon.tl import functions
5 |
6 | from FallenRobot import telethn as tbot
7 | from FallenRobot.events import register
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 | @register(pattern="^/json$")
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(
29 | "🥴 ɴᴇᴇᴅ ᴀᴅᴍɪɴ ᴩᴏᴡᴇʀ ᴛᴏ ᴜsᴇ ᴛʜɪs ɪɴ ɢʀᴏᴜᴩs﹐ ʙᴜᴛ ʏᴏᴜ ᴄᴀɴ ᴜsᴇ ɪᴛ ɪɴ ᴍʏ ᴩᴍ."
30 | )
31 | return
32 |
33 | the_real_message = None
34 | reply_to_id = None
35 | if event.reply_to_msg_id:
36 | previous_message = await event.get_reply_message()
37 | the_real_message = previous_message.stringify()
38 | reply_to_id = event.reply_to_msg_id
39 | else:
40 | the_real_message = event.stringify()
41 | reply_to_id = event.message.id
42 | if len(the_real_message) > 4095:
43 | with io.BytesIO(str.encode(the_real_message)) as out_file:
44 | out_file.name = "json.text"
45 | await tbot.send_file(
46 | event.chat_id,
47 | out_file,
48 | force_document=True,
49 | allow_cache=False,
50 | reply_to=reply_to_id,
51 | )
52 | await event.delete()
53 | else:
54 | await event.reply("`{}`".format(the_real_message))
55 |
--------------------------------------------------------------------------------
/FallenRobot/modules/memify.py:
--------------------------------------------------------------------------------
1 | import os
2 | import textwrap
3 |
4 | from PIL import Image, ImageDraw, ImageFont
5 |
6 | from FallenRobot import telethn as bot
7 | from FallenRobot.events import register
8 |
9 |
10 | @register(pattern="^/mmf ?(.*)")
11 | async def handler(event):
12 | if event.fwd_from:
13 | return
14 |
15 | if not event.reply_to_msg_id:
16 | await event.reply("Provide Some Text To Draw!")
17 |
18 | return
19 |
20 | reply_message = await event.get_reply_message()
21 |
22 | if not reply_message.media:
23 | await event.reply("```Reply to a image/sticker.```")
24 |
25 | return
26 |
27 | file = await bot.download_media(reply_message)
28 |
29 | msg = await event.reply("```Memifying this image! ✊🏻 ```")
30 |
31 | text = str(event.pattern_match.group(1)).strip()
32 |
33 | if len(text) < 1:
34 | return await msg.reply("You might want to try `/mmf text`")
35 |
36 | meme = await drawText(file, text)
37 |
38 | await bot.send_file(event.chat_id, file=meme, force_document=False)
39 |
40 | await msg.delete()
41 |
42 | os.remove(meme)
43 |
44 |
45 | async def drawText(image_path, text):
46 | img = Image.open(image_path)
47 |
48 | os.remove(image_path)
49 |
50 | i_width, i_height = img.size
51 |
52 | if os.name == "nt":
53 | fnt = "ariel.ttf"
54 |
55 | else:
56 | fnt = "./FallenRobot/resources/default.ttf"
57 |
58 | m_font = ImageFont.truetype(fnt, int((70 / 640) * i_width))
59 |
60 | if ";" in text:
61 | upper_text, lower_text = text.split(";")
62 |
63 | else:
64 | upper_text = text
65 |
66 | lower_text = ""
67 |
68 | draw = ImageDraw.Draw(img)
69 |
70 | current_h, pad = 10, 5
71 |
72 | if upper_text:
73 | for u_text in textwrap.wrap(upper_text, width=15):
74 | u_width, u_height = draw.textsize(u_text, font=m_font)
75 |
76 | draw.text(
77 | xy=(((i_width - u_width) / 2) - 2, int((current_h / 640) * i_width)),
78 | text=u_text,
79 | font=m_font,
80 | fill=(0, 0, 0),
81 | )
82 |
83 | draw.text(
84 | xy=(((i_width - u_width) / 2) + 2, int((current_h / 640) * i_width)),
85 | text=u_text,
86 | font=m_font,
87 | fill=(0, 0, 0),
88 | )
89 |
90 | draw.text(
91 | xy=((i_width - u_width) / 2, int(((current_h / 640) * i_width)) - 2),
92 | text=u_text,
93 | font=m_font,
94 | fill=(0, 0, 0),
95 | )
96 |
97 | draw.text(
98 | xy=(((i_width - u_width) / 2), int(((current_h / 640) * i_width)) + 2),
99 | text=u_text,
100 | font=m_font,
101 | fill=(0, 0, 0),
102 | )
103 |
104 | draw.text(
105 | xy=((i_width - u_width) / 2, int((current_h / 640) * i_width)),
106 | text=u_text,
107 | font=m_font,
108 | fill=(255, 255, 255),
109 | )
110 |
111 | current_h += u_height + pad
112 |
113 | if lower_text:
114 | for l_text in textwrap.wrap(lower_text, width=15):
115 | u_width, u_height = draw.textsize(l_text, font=m_font)
116 |
117 | draw.text(
118 | xy=(
119 | ((i_width - u_width) / 2) - 2,
120 | i_height - u_height - int((20 / 640) * i_width),
121 | ),
122 | text=l_text,
123 | font=m_font,
124 | fill=(0, 0, 0),
125 | )
126 |
127 | draw.text(
128 | xy=(
129 | ((i_width - u_width) / 2) + 2,
130 | i_height - u_height - int((20 / 640) * i_width),
131 | ),
132 | text=l_text,
133 | font=m_font,
134 | fill=(0, 0, 0),
135 | )
136 |
137 | draw.text(
138 | xy=(
139 | (i_width - u_width) / 2,
140 | (i_height - u_height - int((20 / 640) * i_width)) - 2,
141 | ),
142 | text=l_text,
143 | font=m_font,
144 | fill=(0, 0, 0),
145 | )
146 |
147 | draw.text(
148 | xy=(
149 | (i_width - u_width) / 2,
150 | (i_height - u_height - int((20 / 640) * i_width)) + 2,
151 | ),
152 | text=l_text,
153 | font=m_font,
154 | fill=(0, 0, 0),
155 | )
156 |
157 | draw.text(
158 | xy=(
159 | (i_width - u_width) / 2,
160 | i_height - u_height - int((20 / 640) * i_width),
161 | ),
162 | text=l_text,
163 | font=m_font,
164 | fill=(255, 255, 255),
165 | )
166 |
167 | current_h += u_height + pad
168 |
169 | image_name = "memify.webp"
170 |
171 | webp_file = os.path.join(image_name)
172 |
173 | img.save(webp_file, "webp")
174 |
175 | return webp_file
176 |
177 |
178 | __mod_name__ = "mmf"
179 |
--------------------------------------------------------------------------------
/FallenRobot/modules/misc.py:
--------------------------------------------------------------------------------
1 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode, Update
2 | from telegram.ext import CallbackContext, CommandHandler, Filters
3 |
4 | from FallenRobot import dispatcher
5 | from FallenRobot.modules.disable import DisableAbleCommandHandler
6 | from FallenRobot.modules.helper_funcs.chat_status import user_admin
7 |
8 | MARKDOWN_HELP = f"""
9 | Markdown is a very powerful formatting tool supported by telegram. {dispatcher.bot.first_name} has some enhancements, to make sure that \
10 | saved messages are correctly parsed, and to allow you to create buttons.
11 |
12 | • _italic_
: wrapping text with '_' will produce italic text
13 | • *bold*
: wrapping text with '*' will produce bold text
14 | • `code`
: wrapping text with '`' will produce monospaced text, also known as 'code'
15 | • [sometext](someURL)
: this will create a link - the message will just show sometext
, \
16 | and tapping on it will open the page at someURL
.
17 | Example:[test](example.com)
18 |
19 | • [buttontext](buttonurl:someURL)
: this is a special enhancement to allow users to have telegram \
20 | buttons in their markdown. buttontext
will be what is displayed on the button, and someurl
\
21 | will be the url which is opened.
22 | Example: [This is a button](buttonurl:example.com)
23 |
24 | If you want multiple buttons on the same line, use :same, as such:
25 | [one](buttonurl://example.com)
26 | [two](buttonurl://google.com:same)
27 | This will create two buttons on a single line, instead of one button per line.
28 |
29 | Keep in mind that your message MUST contain some text other than just a button!
30 | """
31 |
32 |
33 | @user_admin
34 | def echo(update: Update, context: CallbackContext):
35 | args = update.effective_message.text.split(None, 1)
36 | message = update.effective_message
37 |
38 | if message.reply_to_message:
39 | message.reply_to_message.reply_text(
40 | args[1], parse_mode="MARKDOWN", disable_web_page_preview=True
41 | )
42 | else:
43 | message.reply_text(
44 | args[1], quote=False, parse_mode="MARKDOWN", disable_web_page_preview=True
45 | )
46 | message.delete()
47 |
48 |
49 | def markdown_help_sender(update: Update):
50 | update.effective_message.reply_text(MARKDOWN_HELP, parse_mode=ParseMode.HTML)
51 | update.effective_message.reply_text(
52 | "Try forwarding the following message to me, and you'll see, and Use #test!"
53 | )
54 | update.effective_message.reply_text(
55 | "/save test This is a markdown test. _italics_, *bold*, code, "
56 | "[URL](example.com) [button](buttonurl:github.com) "
57 | "[button2](buttonurl://google.com:same)"
58 | )
59 |
60 |
61 | def markdown_help(update: Update, context: CallbackContext):
62 | if update.effective_chat.type != "private":
63 | update.effective_message.reply_text(
64 | "Contact me in pm",
65 | reply_markup=InlineKeyboardMarkup(
66 | [
67 | [
68 | InlineKeyboardButton(
69 | "Markdown help",
70 | url=f"t.me/{context.bot.username}?start=markdownhelp",
71 | )
72 | ]
73 | ]
74 | ),
75 | )
76 | return
77 | markdown_help_sender(update)
78 |
79 |
80 | __help__ = """
81 | *Available commands:*
82 | *Markdown:*
83 | ❍ /markdownhelp*:* quick summary of how markdown works in telegram - can only be called in private chats
84 | *React:*
85 | ❍ /react*:* Reacts with a random reaction
86 | *Urban Dictonary:*
87 | ❍ /ud *:* Type the word or expression you want to search use
88 | *Wikipedia:*
89 | ❍ /wiki *:* wikipedia your query
90 | """
91 |
92 | ECHO_HANDLER = DisableAbleCommandHandler(
93 | "echo", echo, filters=Filters.chat_type.groups, run_async=True
94 | )
95 | MD_HELP_HANDLER = CommandHandler("markdownhelp", markdown_help, run_async=True)
96 |
97 | dispatcher.add_handler(ECHO_HANDLER)
98 | dispatcher.add_handler(MD_HELP_HANDLER)
99 |
100 | __mod_name__ = "Exᴛʀᴀs"
101 | __command_list__ = ["id", "echo"]
102 | __handlers__ = [
103 | ECHO_HANDLER,
104 | MD_HELP_HANDLER,
105 | ]
106 |
--------------------------------------------------------------------------------
/FallenRobot/modules/nightmode.py:
--------------------------------------------------------------------------------
1 | from apscheduler.schedulers.asyncio import AsyncIOScheduler
2 | from telethon import functions, types
3 | from telethon.tl.types import ChatBannedRights
4 |
5 | from FallenRobot import BOT_NAME
6 | from FallenRobot import telethn as tbot
7 | from FallenRobot.events import register
8 | from FallenRobot.modules.sql.night_mode_sql import (
9 | add_nightmode,
10 | get_all_chat_id,
11 | is_nightmode_indb,
12 | rmnightmode,
13 | )
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 | elif isinstance(chat, types.InputPeerChat):
25 | ui = await tbot.get_peer_id(user)
26 | ps = (
27 | await tbot(functions.messages.GetFullChatRequest(chat.chat_id))
28 | ).full_chat.participants.participants
29 | return isinstance(
30 | next((p for p in ps if p.user_id == ui), None),
31 | (types.ChatParticipantAdmin, types.ChatParticipantCreator),
32 | )
33 | else:
34 | return None
35 |
36 |
37 | hehes = ChatBannedRights(
38 | until_date=None,
39 | send_messages=True,
40 | send_media=True,
41 | send_stickers=True,
42 | send_gifs=True,
43 | send_games=True,
44 | send_inline=True,
45 | send_polls=True,
46 | invite_users=True,
47 | pin_messages=True,
48 | change_info=True,
49 | )
50 | openhehe = ChatBannedRights(
51 | until_date=None,
52 | send_messages=False,
53 | send_media=False,
54 | send_stickers=False,
55 | send_gifs=False,
56 | send_games=False,
57 | send_inline=False,
58 | send_polls=False,
59 | invite_users=True,
60 | pin_messages=True,
61 | change_info=True,
62 | )
63 |
64 |
65 | @register(pattern="^/nightmode")
66 | async def close_ws(event):
67 | if event.is_group:
68 | if not (await is_register_admin(event.input_chat, event.message.sender_id)):
69 | await event.reply("🤦🏻♂️You are not admin so you can't use this command...")
70 | return
71 |
72 | if not event.is_group:
73 | await event.reply("You Can Only Enable Night Mode in Groups.")
74 | return
75 | if is_nightmode_indb(str(event.chat_id)):
76 | await event.reply("This Chat is Has Already Enabled Night Mode.")
77 | return
78 | add_nightmode(str(event.chat_id))
79 | await event.reply(
80 | f"Added Chat {event.chat.title} With Id {event.chat_id} To Database. **This Group Will Be Closed On 12Am(IST) And Will Opened On 06Am(IST)**"
81 | )
82 |
83 |
84 | @register(pattern="^/rmnight")
85 | async def disable_ws(event):
86 | if event.is_group:
87 | if not (await is_register_admin(event.input_chat, event.message.sender_id)):
88 | await event.reply("🤦🏻♂️You are not admin so you can't use this command...")
89 | return
90 |
91 | if not event.is_group:
92 | await event.reply("You Can Only Disable Night Mode in Groups.")
93 | return
94 | if not is_nightmode_indb(str(event.chat_id)):
95 | await event.reply("This Chat is Has Not Enabled Night Mode.")
96 | return
97 | rmnightmode(str(event.chat_id))
98 | await event.reply(
99 | f"Removed Chat {event.chat.title} With Id {event.chat_id} From Database."
100 | )
101 |
102 |
103 | async def job_close():
104 | ws_chats = get_all_chat_id()
105 | if len(ws_chats) == 0:
106 | return
107 | for warner in ws_chats:
108 | try:
109 | await tbot.send_message(
110 | int(warner.chat_id),
111 | f"**Night Mode Started**\n\n`Group Is Closing Till 6 Am, Only admins can messages in this chat.`\n\n__Powered By {BOT_NAME}__",
112 | )
113 | await tbot(
114 | functions.messages.EditChatDefaultBannedRightsRequest(
115 | peer=int(warner.chat_id), banned_rights=hehes
116 | )
117 | )
118 | except Exception as e:
119 | logger.info(f"Unable To Close Group {warner} - {e}")
120 |
121 |
122 | # Run everyday at 12am
123 | scheduler = AsyncIOScheduler(timezone="Asia/Kolkata")
124 | scheduler.add_job(job_close, trigger="cron", hour=23, minute=59)
125 | scheduler.start()
126 |
127 |
128 | async def job_open():
129 | ws_chats = get_all_chat_id()
130 | if len(ws_chats) == 0:
131 | return
132 | for warner in ws_chats:
133 | try:
134 | await tbot.send_message(
135 | int(warner.chat_id),
136 | f"**Night Mode Ended**\n\n`Group is opening again now everyone can send messages in this chat.`\n__Powered By {BOT_NAME}__",
137 | )
138 | await tbot(
139 | functions.messages.EditChatDefaultBannedRightsRequest(
140 | peer=int(warner.chat_id), banned_rights=openhehe
141 | )
142 | )
143 | except Exception as e:
144 | logger.info(f"Unable To Open Group {warner.chat_id} - {e}")
145 |
146 |
147 | # Run everyday at 06
148 | scheduler = AsyncIOScheduler(timezone="Asia/Kolkata")
149 | scheduler.add_job(job_open, trigger="cron", hour=6, minute=1)
150 | scheduler.start()
151 |
152 | __help__ = """
153 | *Admins Only*
154 |
155 | ❍ /nightmode*:* Adds Group to NightMode Chats
156 | ❍ /rmnight*:* Removes Group From NightMode Chats
157 |
158 | *Note:* Night Mode chats get Automatically closed at 12 am(IST) and Automatically openned at 6 am(IST) to Prevent Night Spams.
159 | """
160 |
161 | __mod_name__ = "Nɪɢʜᴛ"
162 |
--------------------------------------------------------------------------------
/FallenRobot/modules/paste.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import os
3 | import re
4 |
5 | import aiofiles
6 | from aiohttp import ClientSession
7 | from pykeyboard import InlineKeyboard
8 | from pyrogram import filters
9 | from pyrogram.types import InlineKeyboardButton
10 |
11 | from FallenRobot import pbot as app
12 | from FallenRobot.utils.errors import capture_err
13 | from FallenRobot.utils.pastebin import paste
14 |
15 | pattern = re.compile(r"^text/|json$|yaml$|xml$|toml$|x-sh$|x-shellscript$")
16 |
17 |
18 | async def isPreviewUp(preview: str) -> bool:
19 | for _ in range(7):
20 | try:
21 | async with ClientSession().head(preview, timeout=2) as resp:
22 | status = resp.status
23 | size = resp.content_length
24 | except asyncio.exceptions.TimeoutError:
25 | return False
26 | if status == 404 or (status == 200 and size == 0):
27 | await asyncio.sleep(0.4)
28 | else:
29 | return True if status == 200 else False
30 | return False
31 |
32 |
33 | @app.on_message(filters.command("paste"))
34 | @capture_err
35 | async def paste_func(_, message):
36 | if not message.reply_to_message:
37 | return await message.reply_text("Reply To A Message With /paste")
38 | m = await message.reply_text("ᴘᴀsᴛɪɴɢ......")
39 | if message.reply_to_message.text:
40 | content = str(message.reply_to_message.text)
41 | elif message.reply_to_message.document:
42 | document = message.reply_to_message.document
43 | if document.file_size > 1048576:
44 | return await m.edit("You can only paste files smaller than 1MB.")
45 | if not pattern.search(document.mime_type):
46 | return await m.edit("Only text files can be pasted.")
47 | doc = await message.reply_to_message.download()
48 | async with aiofiles.open(doc, mode="r") as f:
49 | content = await f.read()
50 | os.remove(doc)
51 | link = await paste(content)
52 | preview = link + "/preview.png"
53 | button = InlineKeyboard(row_width=1)
54 | button.add(InlineKeyboardButton(text="ᴘᴀsᴛᴇ ʟɪɴᴋ", url=link))
55 |
56 | if await isPreviewUp(preview):
57 | try:
58 | await message.reply_photo(photo=preview, quote=False, reply_markup=button)
59 | return await m.delete()
60 | except Exception:
61 | pass
62 | return await m.edit(link)
63 |
64 |
65 | __mod_name__ = "Pᴀsᴛᴇ"
66 | __help__ = """
67 | Pastes the given file and shows you the result
68 |
69 | ❍ /paste *:* Reply to a text file
70 | """
71 |
--------------------------------------------------------------------------------
/FallenRobot/modules/ping.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | from telegram import ParseMode, Update
4 | from telegram.ext import CallbackContext
5 |
6 | from FallenRobot import StartTime, dispatcher
7 | from FallenRobot.modules.disable import DisableAbleCommandHandler
8 |
9 |
10 | def get_readable_time(seconds: int) -> str:
11 | count = 0
12 | ping_time = ""
13 | time_list = []
14 | time_suffix_list = ["s", "ᴍ", "ʜ", "ᴅᴀʏs"]
15 |
16 | while count < 4:
17 | count += 1
18 | if count < 3:
19 | remainder, result = divmod(seconds, 60)
20 | else:
21 | remainder, result = divmod(seconds, 24)
22 | if seconds == 0 and remainder == 0:
23 | break
24 | time_list.append(int(result))
25 | seconds = int(remainder)
26 |
27 | for x in range(len(time_list)):
28 | time_list[x] = str(time_list[x]) + time_suffix_list[x]
29 | if len(time_list) == 4:
30 | ping_time += time_list.pop() + ", "
31 |
32 | time_list.reverse()
33 | ping_time += ":".join(time_list)
34 |
35 | return ping_time
36 |
37 |
38 | def ping(update: Update, context: CallbackContext):
39 | msg = update.effective_message
40 |
41 | start_time = time.time()
42 | message = msg.reply_text("🏓 ᴘɪɴɢɪɴɢ ʙᴀʙʏ....")
43 | end_time = time.time()
44 | telegram_ping = str(round((end_time - start_time) * 1000, 3)) + " ms"
45 | uptime = get_readable_time((time.time() - StartTime))
46 |
47 | message.edit_text(
48 | "ɪ ᴀᴍ ᴀʟɪᴠᴇ ʙᴀʙʏ🥀✨\n"
49 | "ᴛɪᴍᴇ ᴛᴀᴋᴇɴ: {}
\n"
50 | "ᴜᴘᴛɪᴍᴇ: {}
".format(telegram_ping, uptime),
51 | parse_mode=ParseMode.HTML,
52 | )
53 |
54 |
55 | PING_HANDLER = DisableAbleCommandHandler("ping", ping, run_async=True)
56 | dispatcher.add_handler(PING_HANDLER)
57 |
58 | __command_list__ = ["ping"]
59 |
60 | __handlers__ = [PING_HANDLER]
61 |
--------------------------------------------------------------------------------
/FallenRobot/modules/purge.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | from telethon import events
4 |
5 | from FallenRobot import telethn
6 | from FallenRobot.modules.helper_funcs.telethn.chatstatus import (
7 | can_delete_messages,
8 | user_is_admin,
9 | )
10 |
11 |
12 | async def purge_messages(event):
13 | start = time.perf_counter()
14 | if event.from_id is None:
15 | return
16 |
17 | if not await user_is_admin(
18 | user_id=event.sender_id, message=event
19 | ) and event.from_id not in [1087968824]:
20 | await event.reply("Only Admins are allowed to use this command")
21 | return
22 |
23 | if not await can_delete_messages(message=event):
24 | await event.reply("Can't seem to purge the message")
25 | return
26 |
27 | reply_msg = await event.get_reply_message()
28 | if not reply_msg:
29 | await event.reply("Reply to a message to select where to start purging from.")
30 | return
31 | messages = []
32 | message_id = reply_msg.id
33 | delete_to = event.message.id
34 |
35 | messages.append(event.reply_to_msg_id)
36 | for msg_id in range(message_id, delete_to + 1):
37 | messages.append(msg_id)
38 | if len(messages) == 100:
39 | await event.client.delete_messages(event.chat_id, messages)
40 | messages = []
41 |
42 | try:
43 | await event.client.delete_messages(event.chat_id, messages)
44 | except:
45 | pass
46 | time_ = time.perf_counter() - start
47 | text = f"`Purged Successfully in {time_:0.2f} Seconds.`"
48 | await event.respond(text, parse_mode="markdown")
49 |
50 |
51 | async def delete_messages(event):
52 | if event.from_id is None:
53 | return
54 |
55 | if not await user_is_admin(
56 | user_id=event.sender_id, message=event
57 | ) and event.from_id not in [1087968824]:
58 | await event.reply("Only Admins are allowed to use this command")
59 | return
60 |
61 | if not await can_delete_messages(message=event):
62 | await event.reply("Can't seem to delete this?")
63 | return
64 |
65 | message = await event.get_reply_message()
66 | if not message:
67 | await event.reply("Whadya want to delete?")
68 | return
69 | chat = await event.get_input_chat()
70 | del_message = [message, event.message]
71 | await event.client.delete_messages(chat, del_message)
72 |
73 |
74 | __help__ = """
75 | ❍ /del*:* deletes the message you replied to
76 | ❍ /purge*:* deletes all messages between this and the replied to message.
77 | """
78 |
79 | PURGE_HANDLER = purge_messages, events.NewMessage(pattern="^[!/]purge$")
80 | DEL_HANDLER = delete_messages, events.NewMessage(pattern="^[!/]del$")
81 |
82 | telethn.add_event_handler(*PURGE_HANDLER)
83 | telethn.add_event_handler(*DEL_HANDLER)
84 |
85 | __mod_name__ = "Pᴜʀɢᴇ"
86 | __command_list__ = ["del", "purge"]
87 | __handlers__ = [PURGE_HANDLER, DEL_HANDLER]
88 |
--------------------------------------------------------------------------------
/FallenRobot/modules/reactions.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 | from telegram import Update
4 | from telegram.ext import CallbackContext
5 |
6 | from FallenRobot import dispatcher
7 | from FallenRobot.modules.disable import DisableAbleCommandHandler
8 |
9 | reactions = [
10 | "( ͡° ͜ʖ ͡°)",
11 | "( . •́ _ʖ •̀ .)",
12 | "( ಠ ͜ʖ ಠ)",
13 | "( ͡ ͜ʖ ͡ )",
14 | "(ʘ ͜ʖ ʘ)",
15 | "ヾ(´〇`)ノ♪♪♪",
16 | "ヽ(o´∀`)ノ♪♬",
17 | "♪♬((d⌒ω⌒b))♬♪",
18 | "└(^^)┐",
19 | "( ̄▽ ̄)/♫•*¨*•.¸¸♪",
20 | "ヾ(⌐■_■)ノ♪",
21 | "乁( • ω •乁)",
22 | "♬♫♪◖(● o ●)◗♪♫♬",
23 | "(っ˘ڡ˘ς)",
24 | "( ˘▽˘)っ♨",
25 | "( ・ω・)⊃-[二二]",
26 | "(*´ー`)旦 旦( ̄ω ̄*)",
27 | "(  ̄▽ ̄)[] [](≧▽≦ )",
28 | "(* ̄▽ ̄)旦 且(´∀`*)",
29 | "(ノ ˘_˘)ノ ζ|||ζ ζ|||ζ ζ|||ζ",
30 | "(ノ°∀°)ノ⌒・*:.。. .。.:*・゜゚・*☆",
31 | "(⊃。•́‿•̀。)⊃━✿✿✿✿✿✿",
32 | "(∩` ロ ´)⊃━炎炎炎炎炎",
33 | "( ・∀・)・・・--------☆",
34 | "( -ω-)/占~~~~~",
35 | "○∞∞∞∞ヽ(^ー^ )",
36 | "(*^^)/~~~~~~~~~~◎",
37 | "(((  ̄□)_/",
38 | "(メ ̄▽ ̄)︻┳═一",
39 | "ヽ( ・∀・)ノ_θ彡☆Σ(ノ `Д´)ノ",
40 | "(*`0´)θ☆(メ°皿°)ノ",
41 | "(; -_-)――――――C<―_-)",
42 | "ヽ(>_<ヽ) ―⊂|=0ヘ(^‿^ )",
43 | "(҂` ロ ´)︻デ═一 \(º □ º l|l)/",
44 | "/( .□.)\ ︵╰(°益°)╯︵ /(.□. /)",
45 | "(`⌒*)O-(`⌒´Q)",
46 | "(っ•﹏•)っ ✴==≡눈٩(`皿´҂)ง",
47 | "ヾ(・ω・)メ(・ω・)ノ",
48 | "(*^ω^)八(⌒▽⌒)八(-‿‿- )ヽ",
49 | "ヽ( ⌒ω⌒)人(=^‥^= )ノ",
50 | "。*:☆(・ω・人・ω・)。:゜☆。",
51 | "(°(°ω(°ω°(☆ω☆)°ω°)ω°)°)",
52 | "(っ˘▽˘)(˘▽˘)˘▽˘ς)",
53 | "(*^ω^)人(^ω^*)",
54 | "\(▽ ̄ \ ( ̄▽ ̄) /  ̄▽)/",
55 | "( ̄Θ ̄)",
56 | "\( ˋ Θ ´ )/",
57 | "( ´(00)ˋ )",
58 | "\( ̄(oo) ̄)/",
59 | "/(≧ x ≦)\",
60 | "/(=・ x ・=)\",
61 | "(=^・ω・^=)",
62 | "(= ; ェ ; =)",
63 | "(=⌒‿‿⌒=)",
64 | "(^• ω •^)",
65 | "ଲ(ⓛ ω ⓛ)ଲ",
66 | "ଲ(ⓛ ω ⓛ)ଲ",
67 | "(^◔ᴥ◔^)",
68 | "[(--)]..zzZ",
69 | "( ̄o ̄) zzZZzzZZ",
70 | "(_ _*) Z z z",
71 | "☆ミ(o*・ω・)ノ",
72 | "ε=ε=ε=ε=┌(; ̄▽ ̄)┘",
73 | "ε===(っ≧ω≦)っ",
74 | "__φ(..)",
75 | "ヾ( `ー´)シφ__",
76 | "( ^▽^)ψ__",
77 | "|・ω・)",
78 | "|д・)",
79 | "┬┴┬┴┤・ω・)ノ",
80 | "|・д・)ノ",
81 | "(* ̄ii ̄)",
82 | "(^〃^)",
83 | "m(_ _)m",
84 | "人(_ _*)",
85 | "(シ. .)シ",
86 | "(^_~)",
87 | "(>ω^)",
88 | "(^_<)〜☆",
89 | "(^_<)",
90 | "(づ ̄ ³ ̄)づ",
91 | "(⊃。•́‿•̀。)⊃",
92 | "⊂(´• ω •`⊂)",
93 | "(*・ω・)ノ",
94 | "(^-^*)/",
95 | "ヾ(*'▽'*)",
96 | "(^0^)ノ",
97 | "(*°ー°)ノ",
98 | "( ̄ω ̄)/",
99 | "(≧▽≦)/",
100 | "w(°o°)w",
101 | "(⊙_⊙)",
102 | "(°ロ°) !",
103 | "∑(O_O;)",
104 | "(¬_¬)",
105 | "(¬_¬ )",
106 | "(↼_↼)",
107 | "( ̄ω ̄;)",
108 | "┐('~`;)┌",
109 | "(・_・;)",
110 | "(@_@)",
111 | "(•ิ_•ิ)?",
112 | "ヽ(ー_ー )ノ",
113 | "┐( ̄ヘ ̄)┌",
114 | "┐( ̄~ ̄)┌",
115 | "┐( ´ д ` )┌",
116 | "╮(︶▽︶)╭",
117 | "ᕕ( ᐛ )ᕗ",
118 | "(ノωヽ)",
119 | "(″ロ゛)",
120 | "(/ω\)",
121 | "(((><)))",
122 | "~(>_<~)",
123 | "(×_×)",
124 | "(×﹏×)",
125 | "(ノ_<。)",
126 | "(μ_μ)",
127 | "o(TヘTo)",
128 | "( ゚,_ゝ`)",
129 | "( ╥ω╥ )",
130 | "(/ˍ・、)",
131 | "(つω`。)",
132 | "(T_T)",
133 | "o(〒﹏〒)o",
134 | "(#`Д´)",
135 | "(・`ω´・)",
136 | "( `ε´ )",
137 | "(メ` ロ ´)",
138 | "Σ(▼□▼メ)",
139 | "(҂ `з´ )",
140 | "٩(╬ʘ益ʘ╬)۶",
141 | "↑_(ΦwΦ)Ψ",
142 | "(ノಥ益ಥ)ノ",
143 | "(#><)",
144 | "(; ̄Д ̄)",
145 | "(¬_¬;)",
146 | "(^^#)",
147 | "( ̄︿ ̄)",
148 | "ヾ(  ̄O ̄)ツ",
149 | "(ᗒᗣᗕ)՞",
150 | "(ノ_<。)ヾ(´ ▽ ` )",
151 | "ヽ( ̄ω ̄(。。 )ゝ",
152 | "(ノ_;)ヾ(´ ∀ ` )",
153 | "(´-ω-`( _ _ )",
154 | "(⌒_⌒;)",
155 | "(*/_\)",
156 | "( ◡‿◡ *)",
157 | "(//ω//)",
158 | "( ̄▽ ̄*)ゞ",
159 | "(„ಡωಡ„)",
160 | "(ノ´ з `)ノ",
161 | "(♡-_-♡)",
162 | "(─‿‿─)♡",
163 | "(´ ω `♡)",
164 | "(ღ˘⌣˘ღ)",
165 | "(´• ω •`) ♡",
166 | "╰(*´︶`*)╯♡",
167 | "(≧◡≦) ♡",
168 | "♡ (˘▽˘>ԅ( ˘⌣˘)",
169 | "σ(≧ε≦σ) ♡",
170 | "(˘∀˘)/(μ‿μ) ❤",
171 | "Σ>―(〃°ω°〃)♡→",
172 | "(* ^ ω ^)",
173 | "(o^▽^o)",
174 | "ヽ(・∀・)ノ",
175 | "(o・ω・o)",
176 | "(^人^)",
177 | "( ´ ω ` )",
178 | "(´• ω •`)",
179 | "╰(▔∀▔)╯",
180 | "(✯◡✯)",
181 | "(⌒‿⌒)",
182 | "(*°▽°*)",
183 | "(´。• ᵕ •。`)",
184 | "ヽ(>∀<☆)ノ",
185 | "\( ̄▽ ̄)/",
186 | "(o˘◡˘o)",
187 | "(╯✧▽✧)╯",
188 | "( ‾́ ◡ ‾́ )",
189 | "(๑˘︶˘๑)",
190 | "(´・ᴗ・ ` )",
191 | "( ͡° ʖ̯ ͡°)",
192 | "( ఠ ͟ʖ ఠ)",
193 | "( ಥ ʖ̯ ಥ)",
194 | "(≖ ͜ʖ≖)",
195 | "ヘ( ̄ω ̄ヘ)",
196 | "(ノ≧∀≦)ノ",
197 | "└( ̄- ̄└))",
198 | "┌(^^)┘",
199 | "(^_^♪)",
200 | "(〜 ̄△ ̄)〜",
201 | "(「• ω •)「",
202 | "( ˘ ɜ˘) ♬♪♫",
203 | "( o˘◡˘o) ┌iii┐",
204 | "♨o(>_<)o♨",
205 | "( ・・)つ―{}@{}@{}-",
206 | "(*´з`)口゚。゚口(・∀・ )",
207 | "( *^^)o∀*∀o(^^* )",
208 | "-●●●-c(・・ )",
209 | "(ノ≧∀≦)ノ ‥…━━━★",
210 | "╰( ͡° ͜ʖ ͡° )つ──☆*:・゚",
211 | "(∩ᄑ_ᄑ)⊃━☆゚*・。*・:≡( ε:)",
212 | ]
213 |
214 |
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, run_async=True)
225 |
226 | dispatcher.add_handler(REACT_HANDLER)
227 |
228 | __command_list__ = ["react"]
229 | __handlers__ = [REACT_HANDLER]
230 |
--------------------------------------------------------------------------------
/FallenRobot/modules/sed.py:
--------------------------------------------------------------------------------
1 | import sre_constants
2 |
3 | import regex
4 | import telegram
5 | from telegram import Update
6 | from telegram.ext import CallbackContext, Filters
7 |
8 | from FallenRobot import LOGGER, dispatcher
9 | from FallenRobot.modules.disable import DisableAbleMessageHandler
10 | from FallenRobot.modules.helper_funcs.regex_helper import infinite_loop_check
11 |
12 | DELIMITERS = ("/", ":", "|", "_")
13 |
14 |
15 | def separate_sed(sed_string):
16 | if (
17 | len(sed_string) >= 3
18 | and sed_string[1] in DELIMITERS
19 | and sed_string.count(sed_string[1]) >= 2
20 | ):
21 | delim = sed_string[1]
22 | start = counter = 2
23 | while counter < len(sed_string):
24 | if sed_string[counter] == "\\":
25 | counter += 1
26 |
27 | elif sed_string[counter] == delim:
28 | replace = sed_string[start:counter]
29 | counter += 1
30 | start = counter
31 | break
32 |
33 | counter += 1
34 |
35 | else:
36 | return None
37 |
38 | while counter < len(sed_string):
39 | if (
40 | sed_string[counter] == "\\"
41 | and counter + 1 < len(sed_string)
42 | and sed_string[counter + 1] == delim
43 | ):
44 | sed_string = sed_string[:counter] + sed_string[counter + 1 :]
45 |
46 | elif sed_string[counter] == delim:
47 | replace_with = sed_string[start:counter]
48 | counter += 1
49 | break
50 |
51 | counter += 1
52 | else:
53 | return replace, sed_string[start:], ""
54 |
55 | flags = ""
56 | if counter < len(sed_string):
57 | flags = sed_string[counter:]
58 | return replace, replace_with, flags.lower()
59 |
60 |
61 | def sed(update: Update, context: CallbackContext):
62 | sed_result = separate_sed(update.effective_message.text)
63 | if sed_result and update.effective_message.reply_to_message:
64 | if update.effective_message.reply_to_message.text:
65 | to_fix = update.effective_message.reply_to_message.text
66 | elif update.effective_message.reply_to_message.caption:
67 | to_fix = update.effective_message.reply_to_message.caption
68 | else:
69 | return
70 |
71 | repl, repl_with, flags = sed_result
72 | if not repl:
73 | update.effective_message.reply_to_message.reply_text(
74 | "You're trying to replace... " "nothing with something?"
75 | )
76 | return
77 |
78 | try:
79 | try:
80 | check = regex.match(repl, to_fix, flags=regex.IGNORECASE, timeout=5)
81 | except TimeoutError:
82 | return
83 | if check and check.group(0).lower() == to_fix.lower():
84 | update.effective_message.reply_to_message.reply_text(
85 | "Hey everyone, {} is trying to make "
86 | "me say stuff I don't wanna "
87 | "say!".format(update.effective_user.first_name)
88 | )
89 | return
90 | if infinite_loop_check(repl):
91 | update.effective_message.reply_text(
92 | "I'm afraid I can't run that regex."
93 | )
94 | return
95 | if "i" in flags and "g" in flags:
96 | text = regex.sub(
97 | repl, repl_with, to_fix, flags=regex.I, timeout=3
98 | ).strip()
99 | elif "i" in flags:
100 | text = regex.sub(
101 | repl, repl_with, to_fix, count=1, flags=regex.I, timeout=3
102 | ).strip()
103 | elif "g" in flags:
104 | text = regex.sub(repl, repl_with, to_fix, timeout=3).strip()
105 | else:
106 | text = regex.sub(repl, repl_with, to_fix, count=1, timeout=3).strip()
107 | except TimeoutError:
108 | update.effective_message.reply_text("Timeout")
109 | return
110 | except sre_constants.error:
111 | LOGGER.warning(update.effective_message.text)
112 | LOGGER.exception("SRE constant error")
113 | update.effective_message.reply_text("Do you even sed? Apparently not.")
114 | return
115 |
116 | # empty string errors -_-
117 | if len(text) >= telegram.MAX_MESSAGE_LENGTH:
118 | update.effective_message.reply_text(
119 | "The result of the sed command was too long for \
120 | telegram!"
121 | )
122 | elif text:
123 | update.effective_message.reply_to_message.reply_text(text)
124 |
125 |
126 | __mod_name__ = "Sed/Regex"
127 |
128 | SED_HANDLER = DisableAbleMessageHandler(
129 | Filters.regex(r"s([{}]).*?\1.*".format("".join(DELIMITERS))),
130 | sed,
131 | friendly="sed",
132 | run_async=True,
133 | )
134 |
135 | dispatcher.add_handler(SED_HANDLER)
136 |
--------------------------------------------------------------------------------
/FallenRobot/modules/shell.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 |
3 | from telegram import ParseMode, Update
4 | from telegram.ext import CallbackContext, CommandHandler
5 |
6 | from FallenRobot import LOGGER, dispatcher
7 | from FallenRobot.modules.helper_funcs.chat_status import dev_plus
8 |
9 |
10 | @dev_plus
11 | def shell(update: Update, context: CallbackContext):
12 | message = update.effective_message
13 | cmd = message.text.split(" ", 1)
14 | if len(cmd) == 1:
15 | message.reply_text("No command to execute was given.")
16 | return
17 | cmd = cmd[1]
18 | process = subprocess.Popen(
19 | cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True
20 | )
21 | stdout, stderr = process.communicate()
22 | reply = ""
23 | stderr = stderr.decode()
24 | stdout = stdout.decode()
25 | if stdout:
26 | reply += f"*Stdout*\n`{stdout}`\n"
27 | LOGGER.info(f"Shell - {cmd} - {stdout}")
28 | if stderr:
29 | reply += f"*Stderr*\n`{stderr}`\n"
30 | LOGGER.error(f"Shell - {cmd} - {stderr}")
31 | if len(reply) > 3000:
32 | with open("shell_output.txt", "w") as file:
33 | file.write(reply)
34 | with open("shell_output.txt", "rb") as doc:
35 | context.bot.send_document(
36 | document=doc,
37 | filename=doc.name,
38 | reply_to_message_id=message.message_id,
39 | chat_id=message.chat_id,
40 | )
41 | else:
42 | message.reply_text(reply, parse_mode=ParseMode.MARKDOWN)
43 |
44 |
45 | SHELL_HANDLER = CommandHandler(["sh"], shell, run_async=True)
46 |
47 | dispatcher.add_handler(SHELL_HANDLER)
48 |
49 | __mod_name__ = "Shell"
50 |
51 | __command_list__ = ["sh"]
52 | __handlers__ = [SHELL_HANDLER]
53 |
--------------------------------------------------------------------------------
/FallenRobot/modules/source.py:
--------------------------------------------------------------------------------
1 | from platform import python_version as y
2 |
3 | from pyrogram import __version__ as z
4 | from pyrogram import filters
5 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message
6 | from telegram import __version__ as o
7 | from telethon import __version__ as s
8 |
9 | from FallenRobot import BOT_NAME, BOT_USERNAME, OWNER_ID, START_IMG, pbot
10 |
11 |
12 | @pbot.on_message(filters.command(["repo", "source"]))
13 | async def repo(_, message: Message):
14 | await message.reply_photo(
15 | photo=START_IMG,
16 | caption=f"""**ʜᴇʏ {message.from_user.mention},
17 |
18 | ɪ ᴀᴍ [{BOT_NAME}](https://t.me/{BOT_USERNAME})**
19 |
20 | **» ᴍʏ ᴅᴇᴠᴇʟᴏᴘᴇʀ :** ™° 🫧 🇴 🇽 𝐘 𝐆 𝐄 𝐍
21 | **» ᴩʏᴛʜᴏɴ ᴠᴇʀsɪᴏɴ :** `{y()}`
22 | **» ʟɪʙʀᴀʀʏ ᴠᴇʀsɪᴏɴ :** `{o}`
23 | **» ᴛᴇʟᴇᴛʜᴏɴ ᴠᴇʀsɪᴏɴ :** `{s}`
24 | **» ᴘʏʀᴏɢʀᴀᴍ ᴠᴇʀsɪᴏɴ :** `{z}`
25 | """,
26 | reply_markup=InlineKeyboardMarkup(
27 | [
28 | [
29 | InlineKeyboardButton("🌺 𝙳𝚎𝚟𝚎𝚕𝚘𝚙𝚎𝚁 🌺", user_id=OWNER_ID),
30 | InlineKeyboardButton(
31 | "❄️ 𝙱𝚠𝚊𝚗𝚍𝚊𝚛𝙻𝚘𝚔 ❄️",
32 | url="https://t.me/BWANDARLOK",
33 | ),
34 | ]
35 | ]
36 | ),
37 | )
38 |
39 |
40 | __mod_name__ = "Rᴇᴩᴏ"
41 |
--------------------------------------------------------------------------------
/FallenRobot/modules/speed_test.py:
--------------------------------------------------------------------------------
1 | import speedtest
2 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode, Update
3 | from telegram.ext import CallbackContext, CallbackQueryHandler
4 |
5 | from FallenRobot import DEV_USERS, dispatcher
6 | from FallenRobot.modules.disable import DisableAbleCommandHandler
7 | from FallenRobot.modules.helper_funcs.chat_status import dev_plus
8 |
9 |
10 | def convert(speed):
11 | return round(int(speed) / 1048576, 2)
12 |
13 |
14 | @dev_plus
15 | def speedtestxyz(update: Update, context: CallbackContext):
16 | buttons = [
17 | [
18 | InlineKeyboardButton("ɪᴍᴀɢᴇ", callback_data="speedtest_image"),
19 | InlineKeyboardButton("ᴛᴇxᴛ", callback_data="speedtest_text"),
20 | ]
21 | ]
22 | update.effective_message.reply_text(
23 | "sᴩᴇᴇᴅᴛᴇsᴛ ᴍᴏᴅᴇ", reply_markup=InlineKeyboardMarkup(buttons)
24 | )
25 |
26 |
27 | def speedtestxyz_callback(update: Update, context: CallbackContext):
28 | query = update.callback_query
29 |
30 | if query.from_user.id in DEV_USERS:
31 | msg = update.effective_message.edit_text("ʀᴜɴɴɪɴɢ ᴀ sᴩᴇᴇᴅᴛᴇsᴛ...")
32 | speed = speedtest.Speedtest()
33 | speed.get_best_server()
34 | speed.download()
35 | speed.upload()
36 | replymsg = "sᴩᴇᴇᴅᴛᴇsᴛ ʀᴇsᴜʟᴛ"
37 |
38 | if query.data == "speedtest_image":
39 | speedtest_image = speed.results.share()
40 | update.effective_message.reply_photo(
41 | photo=speedtest_image, caption=replymsg
42 | )
43 | msg.delete()
44 |
45 | elif query.data == "speedtest_text":
46 | result = speed.results.dict()
47 | replymsg += f"\nDownload: `{convert(result['download'])}Mb/s`\nUpload: `{convert(result['upload'])}Mb/s`\nPing: `{result['ping']}`"
48 | update.effective_message.edit_text(replymsg, parse_mode=ParseMode.MARKDOWN)
49 | else:
50 | return
51 |
52 |
53 | SPEED_TEST_HANDLER = DisableAbleCommandHandler(
54 | "speedtest", speedtestxyz, run_async=True
55 | )
56 | SPEED_TEST_CALLBACKHANDLER = CallbackQueryHandler(
57 | speedtestxyz_callback, pattern="speedtest_.*", run_async=True
58 | )
59 |
60 | dispatcher.add_handler(SPEED_TEST_HANDLER)
61 | dispatcher.add_handler(SPEED_TEST_CALLBACKHANDLER)
62 |
63 | __help__ = """
64 | » /speedtest *:* Runs a speedtest and check the server speed.
65 | """
66 |
67 | __mod_name__ = "SᴘᴇᴇᴅTᴇsᴛ"
68 |
69 | __command_list__ = ["speedtest"]
70 | __handlers__ = [SPEED_TEST_HANDLER, SPEED_TEST_CALLBACKHANDLER]
71 |
--------------------------------------------------------------------------------
/FallenRobot/modules/sql/__init__.py:
--------------------------------------------------------------------------------
1 | from sqlalchemy import create_engine
2 | from sqlalchemy.ext.declarative import declarative_base
3 | from sqlalchemy.orm import scoped_session, sessionmaker
4 |
5 | from FallenRobot import DB_URI
6 | from FallenRobot import LOGGER as log
7 |
8 | if DB_URI and DB_URI.startswith("postgres://"):
9 | DB_URI = DB_URI.replace("postgres://", "postgresql://", 1)
10 |
11 |
12 | def start() -> scoped_session:
13 | engine = create_engine(DB_URI, client_encoding="utf8")
14 | log.info("[PostgreSQL] Connecting to database......")
15 | BASE.metadata.bind = engine
16 | BASE.metadata.create_all(engine)
17 | return scoped_session(sessionmaker(bind=engine, autoflush=False))
18 |
19 |
20 | BASE = declarative_base()
21 | try:
22 | SESSION = start()
23 | except Exception as e:
24 | log.exception(f"[PostgreSQL] Failed to connect due to {e}")
25 | exit()
26 |
27 | log.info("[PostgreSQL] Connection successful, session started.")
28 |
--------------------------------------------------------------------------------
/FallenRobot/modules/sql/afk_sql.py:
--------------------------------------------------------------------------------
1 | import threading
2 |
3 | from sqlalchemy import BigInteger, Boolean, Column, UnicodeText
4 |
5 | from FallenRobot.modules.sql import BASE, SESSION
6 |
7 |
8 | class AFK(BASE):
9 | __tablename__ = "afk_users"
10 |
11 | user_id = Column(BigInteger, primary_key=True)
12 | is_afk = Column(Boolean)
13 | reason = Column(UnicodeText)
14 |
15 | def __init__(self, user_id, reason="", is_afk=True):
16 | self.user_id = user_id
17 | self.reason = reason
18 | self.is_afk = is_afk
19 |
20 | def __repr__(self):
21 | return "afk_status for {}".format(self.user_id)
22 |
23 |
24 | AFK.__table__.create(checkfirst=True)
25 | INSERTION_LOCK = threading.RLock()
26 |
27 | AFK_USERS = {}
28 |
29 |
30 | def is_afk(user_id):
31 | return user_id in AFK_USERS
32 |
33 |
34 | def check_afk_status(user_id):
35 | try:
36 | return SESSION.query(AFK).get(user_id)
37 | finally:
38 | SESSION.close()
39 |
40 |
41 | def set_afk(user_id, reason=""):
42 | with INSERTION_LOCK:
43 | curr = SESSION.query(AFK).get(user_id)
44 | if not curr:
45 | curr = AFK(user_id, reason, True)
46 | else:
47 | curr.is_afk = True
48 |
49 | AFK_USERS[user_id] = reason
50 |
51 | SESSION.add(curr)
52 | SESSION.commit()
53 |
54 |
55 | def rm_afk(user_id):
56 | with INSERTION_LOCK:
57 | curr = SESSION.query(AFK).get(user_id)
58 | if curr:
59 | if user_id in AFK_USERS: # sanity check
60 | del AFK_USERS[user_id]
61 |
62 | SESSION.delete(curr)
63 | SESSION.commit()
64 | return True
65 |
66 | SESSION.close()
67 | return False
68 |
69 |
70 | def toggle_afk(user_id, reason=""):
71 | with INSERTION_LOCK:
72 | curr = SESSION.query(AFK).get(user_id)
73 | if not curr:
74 | curr = AFK(user_id, reason, True)
75 | elif curr.is_afk:
76 | curr.is_afk = False
77 | elif not curr.is_afk:
78 | curr.is_afk = True
79 | SESSION.add(curr)
80 | SESSION.commit()
81 |
82 |
83 | def __load_afk_users():
84 | global AFK_USERS
85 | try:
86 | all_afk = SESSION.query(AFK).all()
87 | AFK_USERS = {user.user_id: user.reason for user in all_afk if user.is_afk}
88 | finally:
89 | SESSION.close()
90 |
91 |
92 | __load_afk_users()
93 |
--------------------------------------------------------------------------------
/FallenRobot/modules/sql/antiflood_sql.py:
--------------------------------------------------------------------------------
1 | import threading
2 |
3 | from sqlalchemy import BigInteger, Column, String, UnicodeText
4 |
5 | from FallenRobot.modules.sql import BASE, SESSION
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(BigInteger)
16 | count = Column(BigInteger, default=DEF_COUNT)
17 | limit = Column(BigInteger, 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(BigInteger, 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 |
--------------------------------------------------------------------------------
/FallenRobot/modules/sql/approve_sql.py:
--------------------------------------------------------------------------------
1 | import threading
2 |
3 | from sqlalchemy import Column, String
4 | from sqlalchemy.sql.sqltypes import BigInteger
5 |
6 | from FallenRobot.modules.sql import BASE, SESSION
7 |
8 |
9 | class Approvals(BASE):
10 | __tablename__ = "approval"
11 | chat_id = Column(String(14), primary_key=True)
12 | user_id = Column(BigInteger, primary_key=True)
13 |
14 | def __init__(self, chat_id, user_id):
15 | self.chat_id = str(chat_id) # ensure string
16 | self.user_id = user_id
17 |
18 | def __repr__(self):
19 | return "" % self.user_id
20 |
21 |
22 | Approvals.__table__.create(checkfirst=True)
23 |
24 | APPROVE_INSERTION_LOCK = threading.RLock()
25 |
26 |
27 | def approve(chat_id, user_id):
28 | with APPROVE_INSERTION_LOCK:
29 | approve_user = Approvals(str(chat_id), user_id)
30 | SESSION.add(approve_user)
31 | SESSION.commit()
32 |
33 |
34 | def is_approved(chat_id, user_id):
35 | try:
36 | return SESSION.query(Approvals).get((str(chat_id), user_id))
37 | finally:
38 | SESSION.close()
39 |
40 |
41 | def disapprove(chat_id, user_id):
42 | with APPROVE_INSERTION_LOCK:
43 | disapprove_user = SESSION.query(Approvals).get((str(chat_id), user_id))
44 | if disapprove_user:
45 | SESSION.delete(disapprove_user)
46 | SESSION.commit()
47 | return True
48 | else:
49 | SESSION.close()
50 | return False
51 |
52 |
53 | def list_approved(chat_id):
54 | try:
55 | return (
56 | SESSION.query(Approvals)
57 | .filter(Approvals.chat_id == str(chat_id))
58 | .order_by(Approvals.user_id.asc())
59 | .all()
60 | )
61 | finally:
62 | SESSION.close()
63 |
--------------------------------------------------------------------------------
/FallenRobot/modules/sql/blacklistusers_sql.py:
--------------------------------------------------------------------------------
1 | import threading
2 |
3 | from sqlalchemy import Column, String, UnicodeText
4 |
5 | from FallenRobot.modules.sql import BASE, SESSION
6 |
7 |
8 | class BlacklistUsers(BASE):
9 | __tablename__ = "blacklistusers"
10 | user_id = Column(String(14), primary_key=True)
11 | reason = Column(UnicodeText)
12 |
13 | def __init__(self, user_id, reason=None):
14 | self.user_id = user_id
15 | self.reason = reason
16 |
17 |
18 | BlacklistUsers.__table__.create(checkfirst=True)
19 |
20 | BLACKLIST_LOCK = threading.RLock()
21 | BLACKLIST_USERS = set()
22 |
23 |
24 | def blacklist_user(user_id, reason=None):
25 | with BLACKLIST_LOCK:
26 | user = SESSION.query(BlacklistUsers).get(str(user_id))
27 | if not user:
28 | user = BlacklistUsers(str(user_id), reason)
29 | else:
30 | user.reason = reason
31 |
32 | SESSION.add(user)
33 | SESSION.commit()
34 | __load_blacklist_userid_list()
35 |
36 |
37 | def unblacklist_user(user_id):
38 | with BLACKLIST_LOCK:
39 | user = SESSION.query(BlacklistUsers).get(str(user_id))
40 | if user:
41 | SESSION.delete(user)
42 |
43 | SESSION.commit()
44 | __load_blacklist_userid_list()
45 |
46 |
47 | def get_reason(user_id):
48 | user = SESSION.query(BlacklistUsers).get(str(user_id))
49 | rep = ""
50 | if user:
51 | rep = user.reason
52 |
53 | SESSION.close()
54 | return rep
55 |
56 |
57 | def is_user_blacklisted(user_id):
58 | return user_id in BLACKLIST_USERS
59 |
60 |
61 | def __load_blacklist_userid_list():
62 | global BLACKLIST_USERS
63 | try:
64 | BLACKLIST_USERS = {int(x.user_id) for x in SESSION.query(BlacklistUsers).all()}
65 | finally:
66 | SESSION.close()
67 |
68 |
69 | __load_blacklist_userid_list()
70 |
--------------------------------------------------------------------------------
/FallenRobot/modules/sql/chatbot_sql.py:
--------------------------------------------------------------------------------
1 | import threading
2 |
3 | from sqlalchemy import Column, String
4 |
5 | from FallenRobot.modules.sql import BASE, SESSION
6 |
7 |
8 | class FallenChats(BASE):
9 | __tablename__ = "fallen_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 |
16 | FallenChats.__table__.create(checkfirst=True)
17 | INSERTION_LOCK = threading.RLock()
18 |
19 |
20 | def is_fallen(chat_id):
21 | try:
22 | chat = SESSION.query(FallenChats).get(str(chat_id))
23 | return bool(chat)
24 | finally:
25 | SESSION.close()
26 |
27 |
28 | def set_fallen(chat_id):
29 | with INSERTION_LOCK:
30 | fallenchat = SESSION.query(FallenChats).get(str(chat_id))
31 | if not fallenchat:
32 | fallenchat = FallenChats(str(chat_id))
33 | SESSION.add(fallenchat)
34 | SESSION.commit()
35 |
36 |
37 | def rem_fallen(chat_id):
38 | with INSERTION_LOCK:
39 | fallenchat = SESSION.query(FallenChats).get(str(chat_id))
40 | if fallenchat:
41 | SESSION.delete(fallenchat)
42 | SESSION.commit()
43 |
--------------------------------------------------------------------------------
/FallenRobot/modules/sql/disable_sql.py:
--------------------------------------------------------------------------------
1 | import threading
2 |
3 | from sqlalchemy import Column, String, UnicodeText, distinct, func
4 |
5 | from FallenRobot.modules.sql import BASE, SESSION
6 |
7 |
8 | class Disable(BASE):
9 | __tablename__ = "disabled_commands"
10 | chat_id = Column(String(14), primary_key=True)
11 | command = Column(UnicodeText, primary_key=True)
12 |
13 | def __init__(self, chat_id, command):
14 | self.chat_id = chat_id
15 | self.command = command
16 |
17 | def __repr__(self):
18 | return "Disabled cmd {} in {}".format(self.command, self.chat_id)
19 |
20 |
21 | Disable.__table__.create(checkfirst=True)
22 | DISABLE_INSERTION_LOCK = threading.RLock()
23 |
24 | DISABLED = {}
25 |
26 |
27 | def disable_command(chat_id, disable):
28 | with DISABLE_INSERTION_LOCK:
29 | disabled = SESSION.query(Disable).get((str(chat_id), disable))
30 |
31 | if not disabled:
32 | DISABLED.setdefault(str(chat_id), set()).add(disable)
33 |
34 | disabled = Disable(str(chat_id), disable)
35 | SESSION.add(disabled)
36 | SESSION.commit()
37 | return True
38 |
39 | SESSION.close()
40 | return False
41 |
42 |
43 | def enable_command(chat_id, enable):
44 | with DISABLE_INSERTION_LOCK:
45 | disabled = SESSION.query(Disable).get((str(chat_id), enable))
46 |
47 | if disabled:
48 | if enable in DISABLED.get(str(chat_id)): # sanity check
49 | DISABLED.setdefault(str(chat_id), set()).remove(enable)
50 |
51 | SESSION.delete(disabled)
52 | SESSION.commit()
53 | return True
54 |
55 | SESSION.close()
56 | return False
57 |
58 |
59 | def is_command_disabled(chat_id, cmd):
60 | return str(cmd).lower() in DISABLED.get(str(chat_id), set())
61 |
62 |
63 | def get_all_disabled(chat_id):
64 | return DISABLED.get(str(chat_id), set())
65 |
66 |
67 | def num_chats():
68 | try:
69 | return SESSION.query(func.count(distinct(Disable.chat_id))).scalar()
70 | finally:
71 | SESSION.close()
72 |
73 |
74 | def num_disabled():
75 | try:
76 | return SESSION.query(Disable).count()
77 | finally:
78 | SESSION.close()
79 |
80 |
81 | def migrate_chat(old_chat_id, new_chat_id):
82 | with DISABLE_INSERTION_LOCK:
83 | chats = SESSION.query(Disable).filter(Disable.chat_id == str(old_chat_id)).all()
84 | for chat in chats:
85 | chat.chat_id = str(new_chat_id)
86 | SESSION.add(chat)
87 |
88 | if str(old_chat_id) in DISABLED:
89 | DISABLED[str(new_chat_id)] = DISABLED.get(str(old_chat_id), set())
90 |
91 | SESSION.commit()
92 |
93 |
94 | def __load_disabled_commands():
95 | global DISABLED
96 | try:
97 | all_chats = SESSION.query(Disable).all()
98 | for chat in all_chats:
99 | DISABLED.setdefault(chat.chat_id, set()).add(chat.command)
100 |
101 | finally:
102 | SESSION.close()
103 |
104 |
105 | __load_disabled_commands()
106 |
--------------------------------------------------------------------------------
/FallenRobot/modules/sql/global_bans_sql.py:
--------------------------------------------------------------------------------
1 | import threading
2 |
3 | from sqlalchemy import BigInteger, Boolean, Column, String, UnicodeText
4 |
5 | from FallenRobot.modules.sql import BASE, SESSION
6 |
7 |
8 | class GloballyBannedUsers(BASE):
9 | __tablename__ = "gbans"
10 | user_id = Column(BigInteger, primary_key=True)
11 | name = Column(UnicodeText, nullable=False)
12 | reason = Column(UnicodeText)
13 |
14 | def __init__(self, user_id, name, reason=None):
15 | self.user_id = user_id
16 | self.name = name
17 | self.reason = reason
18 |
19 | def __repr__(self):
20 | return "".format(self.name, self.user_id)
21 |
22 | def to_dict(self):
23 | return {"user_id": self.user_id, "name": self.name, "reason": self.reason}
24 |
25 |
26 | class GbanSettings(BASE):
27 | __tablename__ = "gban_settings"
28 | chat_id = Column(String(14), primary_key=True)
29 | setting = Column(Boolean, default=True, nullable=False)
30 |
31 | def __init__(self, chat_id, enabled):
32 | self.chat_id = str(chat_id)
33 | self.setting = enabled
34 |
35 | def __repr__(self):
36 | return "".format(self.chat_id, self.setting)
37 |
38 |
39 | GloballyBannedUsers.__table__.create(checkfirst=True)
40 | GbanSettings.__table__.create(checkfirst=True)
41 |
42 | GBANNED_USERS_LOCK = threading.RLock()
43 | GBAN_SETTING_LOCK = threading.RLock()
44 | GBANNED_LIST = set()
45 | GBANSTAT_LIST = set()
46 |
47 |
48 | def gban_user(user_id, name, reason=None):
49 | with GBANNED_USERS_LOCK:
50 | user = SESSION.query(GloballyBannedUsers).get(user_id)
51 | if not user:
52 | user = GloballyBannedUsers(user_id, name, reason)
53 | else:
54 | user.name = name
55 | user.reason = reason
56 |
57 | SESSION.merge(user)
58 | SESSION.commit()
59 | __load_gbanned_userid_list()
60 |
61 |
62 | def update_gban_reason(user_id, name, reason=None):
63 | with GBANNED_USERS_LOCK:
64 | user = SESSION.query(GloballyBannedUsers).get(user_id)
65 | if not user:
66 | return None
67 | old_reason = user.reason
68 | user.name = name
69 | user.reason = reason
70 |
71 | SESSION.merge(user)
72 | SESSION.commit()
73 | return old_reason
74 |
75 |
76 | def ungban_user(user_id):
77 | with GBANNED_USERS_LOCK:
78 | user = SESSION.query(GloballyBannedUsers).get(user_id)
79 | if user:
80 | SESSION.delete(user)
81 |
82 | SESSION.commit()
83 | __load_gbanned_userid_list()
84 |
85 |
86 | def is_user_gbanned(user_id):
87 | return user_id in GBANNED_LIST
88 |
89 |
90 | def get_gbanned_user(user_id):
91 | try:
92 | return SESSION.query(GloballyBannedUsers).get(user_id)
93 | finally:
94 | SESSION.close()
95 |
96 |
97 | def get_gban_list():
98 | try:
99 | return [x.to_dict() for x in SESSION.query(GloballyBannedUsers).all()]
100 | finally:
101 | SESSION.close()
102 |
103 |
104 | def enable_gbans(chat_id):
105 | with GBAN_SETTING_LOCK:
106 | chat = SESSION.query(GbanSettings).get(str(chat_id))
107 | if not chat:
108 | chat = GbanSettings(chat_id, True)
109 |
110 | chat.setting = True
111 | SESSION.add(chat)
112 | SESSION.commit()
113 | if str(chat_id) in GBANSTAT_LIST:
114 | GBANSTAT_LIST.remove(str(chat_id))
115 |
116 |
117 | def disable_gbans(chat_id):
118 | with GBAN_SETTING_LOCK:
119 | chat = SESSION.query(GbanSettings).get(str(chat_id))
120 | if not chat:
121 | chat = GbanSettings(chat_id, False)
122 |
123 | chat.setting = False
124 | SESSION.add(chat)
125 | SESSION.commit()
126 | GBANSTAT_LIST.add(str(chat_id))
127 |
128 |
129 | def does_chat_gban(chat_id):
130 | return str(chat_id) not in GBANSTAT_LIST
131 |
132 |
133 | def num_gbanned_users():
134 | return len(GBANNED_LIST)
135 |
136 |
137 | def __load_gbanned_userid_list():
138 | global GBANNED_LIST
139 | try:
140 | GBANNED_LIST = {x.user_id for x in SESSION.query(GloballyBannedUsers).all()}
141 | finally:
142 | SESSION.close()
143 |
144 |
145 | def __load_gban_stat_list():
146 | global GBANSTAT_LIST
147 | try:
148 | GBANSTAT_LIST = {
149 | x.chat_id for x in SESSION.query(GbanSettings).all() if not x.setting
150 | }
151 | finally:
152 | SESSION.close()
153 |
154 |
155 | def migrate_chat(old_chat_id, new_chat_id):
156 | with GBAN_SETTING_LOCK:
157 | chat = SESSION.query(GbanSettings).get(str(old_chat_id))
158 | if chat:
159 | chat.chat_id = new_chat_id
160 | SESSION.add(chat)
161 |
162 | SESSION.commit()
163 |
164 |
165 | # Create in memory userid to avoid disk access
166 | __load_gbanned_userid_list()
167 | __load_gban_stat_list()
168 |
--------------------------------------------------------------------------------
/FallenRobot/modules/sql/log_channel_sql.py:
--------------------------------------------------------------------------------
1 | import threading
2 |
3 | from sqlalchemy import Column, String, distinct, func
4 |
5 | from FallenRobot.modules.sql import BASE, SESSION
6 |
7 |
8 | class GroupLogs(BASE):
9 | __tablename__ = "log_channels"
10 | chat_id = Column(String(14), primary_key=True)
11 | log_channel = Column(String(14), nullable=False)
12 |
13 | def __init__(self, chat_id, log_channel):
14 | self.chat_id = str(chat_id)
15 | self.log_channel = str(log_channel)
16 |
17 |
18 | GroupLogs.__table__.create(checkfirst=True)
19 |
20 | LOGS_INSERTION_LOCK = threading.RLock()
21 |
22 | CHANNELS = {}
23 |
24 |
25 | def set_chat_log_channel(chat_id, log_channel):
26 | with LOGS_INSERTION_LOCK:
27 | res = SESSION.query(GroupLogs).get(str(chat_id))
28 | if res:
29 | res.log_channel = log_channel
30 | else:
31 | res = GroupLogs(chat_id, log_channel)
32 | SESSION.add(res)
33 |
34 | CHANNELS[str(chat_id)] = log_channel
35 | SESSION.commit()
36 |
37 |
38 | def get_chat_log_channel(chat_id):
39 | return CHANNELS.get(str(chat_id))
40 |
41 |
42 | def stop_chat_logging(chat_id):
43 | with LOGS_INSERTION_LOCK:
44 | res = SESSION.query(GroupLogs).get(str(chat_id))
45 | if res:
46 | if str(chat_id) in CHANNELS:
47 | del CHANNELS[str(chat_id)]
48 |
49 | log_channel = res.log_channel
50 | SESSION.delete(res)
51 | SESSION.commit()
52 | return log_channel
53 |
54 |
55 | def num_logchannels():
56 | try:
57 | return SESSION.query(func.count(distinct(GroupLogs.chat_id))).scalar()
58 | finally:
59 | SESSION.close()
60 |
61 |
62 | def migrate_chat(old_chat_id, new_chat_id):
63 | with LOGS_INSERTION_LOCK:
64 | chat = SESSION.query(GroupLogs).get(str(old_chat_id))
65 | if chat:
66 | chat.chat_id = str(new_chat_id)
67 | SESSION.add(chat)
68 | if str(old_chat_id) in CHANNELS:
69 | CHANNELS[str(new_chat_id)] = CHANNELS.get(str(old_chat_id))
70 |
71 | SESSION.commit()
72 |
73 |
74 | def __load_log_channels():
75 | global CHANNELS
76 | try:
77 | all_chats = SESSION.query(GroupLogs).all()
78 | CHANNELS = {chat.chat_id: chat.log_channel for chat in all_chats}
79 | finally:
80 | SESSION.close()
81 |
82 |
83 | __load_log_channels()
84 |
--------------------------------------------------------------------------------
/FallenRobot/modules/sql/night_mode_sql.py:
--------------------------------------------------------------------------------
1 | from sqlalchemy import Column, String
2 |
3 | from FallenRobot.modules.sql import BASE, SESSION
4 |
5 |
6 | class Nightmode(BASE):
7 | __tablename__ = "nightmode"
8 | chat_id = Column(String(14), primary_key=True)
9 |
10 | def __init__(self, chat_id):
11 | self.chat_id = chat_id
12 |
13 |
14 | Nightmode.__table__.create(checkfirst=True)
15 |
16 |
17 | def add_nightmode(chat_id: str):
18 | nightmoddy = Nightmode(str(chat_id))
19 | SESSION.add(nightmoddy)
20 | SESSION.commit()
21 |
22 |
23 | def rmnightmode(chat_id: str):
24 | rmnightmoddy = SESSION.query(Nightmode).get(str(chat_id))
25 | if rmnightmoddy:
26 | SESSION.delete(rmnightmoddy)
27 | SESSION.commit()
28 |
29 |
30 | def get_all_chat_id():
31 | stark = SESSION.query(Nightmode).all()
32 | SESSION.close()
33 | return stark
34 |
35 |
36 | def is_nightmode_indb(chat_id: str):
37 | try:
38 | s__ = SESSION.query(Nightmode).get(str(chat_id))
39 | if s__:
40 | return str(s__.chat_id)
41 | finally:
42 | SESSION.close()
43 |
--------------------------------------------------------------------------------
/FallenRobot/modules/sql/reporting_sql.py:
--------------------------------------------------------------------------------
1 | import threading
2 | from typing import Union
3 |
4 | from sqlalchemy import BigInteger, Boolean, Column, String
5 |
6 | from FallenRobot.modules.sql import BASE, SESSION
7 |
8 |
9 | class ReportingUserSettings(BASE):
10 | __tablename__ = "user_report_settings"
11 | user_id = Column(BigInteger, primary_key=True)
12 | should_report = Column(Boolean, default=True)
13 |
14 | def __init__(self, user_id):
15 | self.user_id = user_id
16 |
17 | def __repr__(self):
18 | return "".format(self.user_id)
19 |
20 |
21 | class ReportingChatSettings(BASE):
22 | __tablename__ = "chat_report_settings"
23 | chat_id = Column(String(14), primary_key=True)
24 | should_report = Column(Boolean, default=True)
25 |
26 | def __init__(self, chat_id):
27 | self.chat_id = str(chat_id)
28 |
29 | def __repr__(self):
30 | return "".format(self.chat_id)
31 |
32 |
33 | ReportingUserSettings.__table__.create(checkfirst=True)
34 | ReportingChatSettings.__table__.create(checkfirst=True)
35 |
36 | CHAT_LOCK = threading.RLock()
37 | USER_LOCK = threading.RLock()
38 |
39 |
40 | def chat_should_report(chat_id: Union[str, int]) -> bool:
41 | try:
42 | chat_setting = SESSION.query(ReportingChatSettings).get(str(chat_id))
43 | if chat_setting:
44 | return chat_setting.should_report
45 | return False
46 | finally:
47 | SESSION.close()
48 |
49 |
50 | def user_should_report(user_id: int) -> bool:
51 | try:
52 | user_setting = SESSION.query(ReportingUserSettings).get(user_id)
53 | if user_setting:
54 | return user_setting.should_report
55 | return True
56 | finally:
57 | SESSION.close()
58 |
59 |
60 | def set_chat_setting(chat_id: Union[int, str], setting: bool):
61 | with CHAT_LOCK:
62 | chat_setting = SESSION.query(ReportingChatSettings).get(str(chat_id))
63 | if not chat_setting:
64 | chat_setting = ReportingChatSettings(chat_id)
65 |
66 | chat_setting.should_report = setting
67 | SESSION.add(chat_setting)
68 | SESSION.commit()
69 |
70 |
71 | def set_user_setting(user_id: int, setting: bool):
72 | with USER_LOCK:
73 | user_setting = SESSION.query(ReportingUserSettings).get(user_id)
74 | if not user_setting:
75 | user_setting = ReportingUserSettings(user_id)
76 |
77 | user_setting.should_report = setting
78 | SESSION.add(user_setting)
79 | SESSION.commit()
80 |
81 |
82 | def migrate_chat(old_chat_id, new_chat_id):
83 | with CHAT_LOCK:
84 | chat_notes = (
85 | SESSION.query(ReportingChatSettings)
86 | .filter(ReportingChatSettings.chat_id == str(old_chat_id))
87 | .all()
88 | )
89 | for note in chat_notes:
90 | note.chat_id = str(new_chat_id)
91 | SESSION.commit()
92 |
--------------------------------------------------------------------------------
/FallenRobot/modules/sql/rss_sql.py:
--------------------------------------------------------------------------------
1 | import threading
2 |
3 | from sqlalchemy import BigInteger, Column, UnicodeText
4 |
5 | from FallenRobot.modules.sql import BASE, SESSION
6 |
7 |
8 | class RSS(BASE):
9 | __tablename__ = "rss_feed"
10 | id = Column(BigInteger, primary_key=True)
11 | chat_id = Column(UnicodeText, nullable=False)
12 | feed_link = Column(UnicodeText)
13 | old_entry_link = Column(UnicodeText)
14 |
15 | def __init__(self, chat_id, feed_link, old_entry_link):
16 | self.chat_id = chat_id
17 | self.feed_link = feed_link
18 | self.old_entry_link = old_entry_link
19 |
20 | def __repr__(self):
21 | return "".format(
22 | self.chat_id, self.feed_link, self.old_entry_link
23 | )
24 |
25 |
26 | RSS.__table__.create(checkfirst=True)
27 | INSERTION_LOCK = threading.RLock()
28 |
29 |
30 | def check_url_availability(tg_chat_id, tg_feed_link):
31 | try:
32 | return (
33 | SESSION.query(RSS)
34 | .filter(RSS.feed_link == tg_feed_link, RSS.chat_id == tg_chat_id)
35 | .all()
36 | )
37 | finally:
38 | SESSION.close()
39 |
40 |
41 | def add_url(tg_chat_id, tg_feed_link, tg_old_entry_link):
42 | with INSERTION_LOCK:
43 | action = RSS(tg_chat_id, tg_feed_link, tg_old_entry_link)
44 |
45 | SESSION.add(action)
46 | SESSION.commit()
47 |
48 |
49 | def remove_url(tg_chat_id, tg_feed_link):
50 | with INSERTION_LOCK:
51 | # this loops to delete any possible duplicates for the same TG User ID, TG Chat ID and link
52 | for row in check_url_availability(tg_chat_id, tg_feed_link):
53 | # add the action to the DB query
54 | SESSION.delete(row)
55 |
56 | SESSION.commit()
57 |
58 |
59 | def get_urls(tg_chat_id):
60 | try:
61 | return SESSION.query(RSS).filter(RSS.chat_id == tg_chat_id).all()
62 | finally:
63 | SESSION.close()
64 |
65 |
66 | def get_all():
67 | try:
68 | return SESSION.query(RSS).all()
69 | finally:
70 | SESSION.close()
71 |
72 |
73 | def update_url(row_id, new_entry_links):
74 | with INSERTION_LOCK:
75 | row = SESSION.query(RSS).get(row_id)
76 |
77 | # set the new old_entry_link with the latest update from the RSS Feed
78 | row.old_entry_link = new_entry_links[0]
79 |
80 | # commit the changes to the DB
81 | SESSION.commit()
82 |
--------------------------------------------------------------------------------
/FallenRobot/modules/sql/rules_sql.py:
--------------------------------------------------------------------------------
1 | import threading
2 |
3 | from sqlalchemy import Column, String, UnicodeText, distinct, func
4 |
5 | from FallenRobot.modules.sql import BASE, SESSION
6 |
7 |
8 | class Rules(BASE):
9 | __tablename__ = "rules"
10 | chat_id = Column(String(14), primary_key=True)
11 | rules = Column(UnicodeText, default="")
12 |
13 | def __init__(self, chat_id):
14 | self.chat_id = chat_id
15 |
16 | def __repr__(self):
17 | return "".format(self.chat_id, self.rules)
18 |
19 |
20 | Rules.__table__.create(checkfirst=True)
21 |
22 | INSERTION_LOCK = threading.RLock()
23 |
24 |
25 | def set_rules(chat_id, rules_text):
26 | with INSERTION_LOCK:
27 | rules = SESSION.query(Rules).get(str(chat_id))
28 | if not rules:
29 | rules = Rules(str(chat_id))
30 | rules.rules = rules_text
31 |
32 | SESSION.add(rules)
33 | SESSION.commit()
34 |
35 |
36 | def get_rules(chat_id):
37 | rules = SESSION.query(Rules).get(str(chat_id))
38 | ret = ""
39 | if rules:
40 | ret = rules.rules
41 |
42 | SESSION.close()
43 | return ret
44 |
45 |
46 | def num_chats():
47 | try:
48 | return SESSION.query(func.count(distinct(Rules.chat_id))).scalar()
49 | finally:
50 | SESSION.close()
51 |
52 |
53 | def migrate_chat(old_chat_id, new_chat_id):
54 | with INSERTION_LOCK:
55 | chat = SESSION.query(Rules).get(str(old_chat_id))
56 | if chat:
57 | chat.chat_id = str(new_chat_id)
58 | SESSION.commit()
59 |
--------------------------------------------------------------------------------
/FallenRobot/modules/sql/userinfo_sql.py:
--------------------------------------------------------------------------------
1 | import threading
2 |
3 | from sqlalchemy import BigInteger, Column, UnicodeText
4 |
5 | from FallenRobot.modules.sql import BASE, SESSION
6 |
7 |
8 | class UserInfo(BASE):
9 | __tablename__ = "userinfo"
10 | user_id = Column(BigInteger, primary_key=True)
11 | info = Column(UnicodeText)
12 |
13 | def __init__(self, user_id, info):
14 | self.user_id = user_id
15 | self.info = info
16 |
17 | def __repr__(self):
18 | return "" % self.user_id
19 |
20 |
21 | class UserBio(BASE):
22 | __tablename__ = "userbio"
23 | user_id = Column(BigInteger, primary_key=True)
24 | bio = Column(UnicodeText)
25 |
26 | def __init__(self, user_id, bio):
27 | self.user_id = user_id
28 | self.bio = bio
29 |
30 | def __repr__(self):
31 | return "" % self.user_id
32 |
33 |
34 | UserInfo.__table__.create(checkfirst=True)
35 | UserBio.__table__.create(checkfirst=True)
36 |
37 | INSERTION_LOCK = threading.RLock()
38 |
39 |
40 | def get_user_me_info(user_id):
41 | userinfo = SESSION.query(UserInfo).get(user_id)
42 | SESSION.close()
43 | if userinfo:
44 | return userinfo.info
45 | return None
46 |
47 |
48 | def set_user_me_info(user_id, info):
49 | with INSERTION_LOCK:
50 | userinfo = SESSION.query(UserInfo).get(user_id)
51 | if userinfo:
52 | userinfo.info = info
53 | else:
54 | userinfo = UserInfo(user_id, info)
55 | SESSION.add(userinfo)
56 | SESSION.commit()
57 |
58 |
59 | def get_user_bio(user_id):
60 | userbio = SESSION.query(UserBio).get(user_id)
61 | SESSION.close()
62 | if userbio:
63 | return userbio.bio
64 | return None
65 |
66 |
67 | def set_user_bio(user_id, bio):
68 | with INSERTION_LOCK:
69 | userbio = SESSION.query(UserBio).get(user_id)
70 | if userbio:
71 | userbio.bio = bio
72 | else:
73 | userbio = UserBio(user_id, bio)
74 |
75 | SESSION.add(userbio)
76 | SESSION.commit()
77 |
--------------------------------------------------------------------------------
/FallenRobot/modules/tagall.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 |
3 | from telethon import events
4 | from telethon.errors import UserNotParticipantError
5 | from telethon.tl.functions.channels import GetParticipantRequest
6 | from telethon.tl.types import ChannelParticipantAdmin, ChannelParticipantCreator
7 |
8 | from FallenRobot import telethn as client
9 |
10 | spam_chats = []
11 |
12 |
13 | @client.on(events.NewMessage(pattern="^/tagall ?(.*)"))
14 | @client.on(events.NewMessage(pattern="^@all ?(.*)"))
15 | async def mentionall(event):
16 | chat_id = event.chat_id
17 | if event.is_private:
18 | return await event.respond(
19 | "__This command can be use in groups and channels!__"
20 | )
21 |
22 | is_admin = False
23 | try:
24 | partici_ = await client(GetParticipantRequest(event.chat_id, event.sender_id))
25 | except UserNotParticipantError:
26 | is_admin = False
27 | else:
28 | if isinstance(
29 | partici_.participant, (ChannelParticipantAdmin, ChannelParticipantCreator)
30 | ):
31 | is_admin = True
32 | if not is_admin:
33 | return await event.respond("__Only admins can mention all!__")
34 |
35 | if event.pattern_match.group(1) and event.is_reply:
36 | return await event.respond("__Give me one argument!__")
37 | elif event.pattern_match.group(1):
38 | mode = "text_on_cmd"
39 | msg = event.pattern_match.group(1)
40 | elif event.is_reply:
41 | mode = "text_on_reply"
42 | msg = await event.get_reply_message()
43 | if msg == None:
44 | return await event.respond(
45 | "__I can't mention members for older messages! (messages which are sent before I'm added to group)__"
46 | )
47 | else:
48 | return await event.respond(
49 | "__Reply to a message or give me some text to mention others!__"
50 | )
51 |
52 | spam_chats.append(chat_id)
53 | usrnum = 0
54 | usrtxt = ""
55 | async for usr in client.iter_participants(chat_id):
56 | if not chat_id in spam_chats:
57 | break
58 | usrnum += 1
59 | usrtxt += f"[{usr.first_name}](tg://user?id={usr.id}), "
60 | if usrnum == 5:
61 | if mode == "text_on_cmd":
62 | txt = f"{msg}\n{usrtxt}"
63 | await client.send_message(chat_id, txt)
64 | elif mode == "text_on_reply":
65 | await msg.reply(usrtxt)
66 | await asyncio.sleep(3)
67 | usrnum = 0
68 | usrtxt = ""
69 | try:
70 | spam_chats.remove(chat_id)
71 | except:
72 | pass
73 |
74 |
75 | @client.on(events.NewMessage(pattern="^/cancel$"))
76 | async def cancel_spam(event):
77 | if not event.chat_id in spam_chats:
78 | return await event.respond("__There is no proccess on going...__")
79 | is_admin = False
80 | try:
81 | partici_ = await client(GetParticipantRequest(event.chat_id, event.sender_id))
82 | except UserNotParticipantError:
83 | is_admin = False
84 | else:
85 | if isinstance(
86 | partici_.participant, (ChannelParticipantAdmin, ChannelParticipantCreator)
87 | ):
88 | is_admin = True
89 | if not is_admin:
90 | return await event.respond("__Only admins can execute this command!__")
91 |
92 | else:
93 | try:
94 | spam_chats.remove(event.chat_id)
95 | except:
96 | pass
97 | return await event.respond("__Stopped mention.__")
98 |
99 |
100 | __mod_name__ = "Tᴀɢ Aʟʟ"
101 | __help__ = """
102 | *Only for admins*
103 |
104 | ❍ /tagall or @all '(reply to message or add another message) To mention all members in your group, without exception.'
105 | """
106 |
--------------------------------------------------------------------------------
/FallenRobot/modules/telegraph.py:
--------------------------------------------------------------------------------
1 | import os
2 | from datetime import datetime
3 |
4 | from PIL import Image
5 | from telegraph import Telegraph, exceptions, upload_file
6 |
7 | from FallenRobot import telethn as tbot
8 | from FallenRobot.events import register
9 |
10 | Anonymous = "Fallen"
11 |
12 | TMP_DOWNLOAD_DIRECTORY = "./"
13 | telegraph = Telegraph()
14 | r = telegraph.create_account(short_name=Anonymous)
15 | auth_url = r["auth_url"]
16 |
17 |
18 | @register(pattern="^/tg(m|t) ?(.*)")
19 | async def _(event):
20 | if event.fwd_from:
21 | return
22 | optional_title = event.pattern_match.group(2)
23 | if event.reply_to_msg_id:
24 | start = datetime.now()
25 | r_message = await event.get_reply_message()
26 | input_str = event.pattern_match.group(1)
27 | if input_str == "m":
28 | downloaded_file_name = await tbot.download_media(
29 | r_message, TMP_DOWNLOAD_DIRECTORY
30 | )
31 | end = datetime.now()
32 | ms = (end - start).seconds
33 | h = await event.reply(
34 | "Downloaded to {} in {} seconds.".format(downloaded_file_name, ms)
35 | )
36 | if downloaded_file_name.endswith((".webp")):
37 | resize_image(downloaded_file_name)
38 | try:
39 | start = datetime.now()
40 | media_urls = upload_file(downloaded_file_name)
41 | except exceptions.TelegraphException as exc:
42 | await h.edit("ERROR: " + str(exc))
43 | os.remove(downloaded_file_name)
44 | else:
45 | end = datetime.now()
46 | (end - start).seconds
47 | os.remove(downloaded_file_name)
48 | await h.edit(
49 | "Uploaded to https://te.legra.ph{})".format(media_urls[0]),
50 | link_preview=True,
51 | )
52 | elif input_str == "t":
53 | user_object = await tbot.get_entity(r_message.sender_id)
54 | title_of_page = user_object.first_name # + " " + user_object.last_name
55 | # apparently, all Users do not have last_name field
56 | if optional_title:
57 | title_of_page = optional_title
58 | page_content = r_message.message
59 | if r_message.media:
60 | if page_content != "":
61 | title_of_page = page_content
62 | downloaded_file_name = await tbot.download_media(
63 | r_message, TMP_DOWNLOAD_DIRECTORY
64 | )
65 | m_list = None
66 | with open(downloaded_file_name, "rb") as fd:
67 | m_list = fd.readlines()
68 | for m in m_list:
69 | page_content += m.decode("UTF-8") + "\n"
70 | os.remove(downloaded_file_name)
71 | page_content = page_content.replace("\n", "
")
72 | response = telegraph.create_page(title_of_page, html_content=page_content)
73 | end = datetime.now()
74 | ms = (end - start).seconds
75 | await event.reply(
76 | "Pasted to https://telegra.ph/{} in {} seconds.".format(
77 | response["path"], ms
78 | ),
79 | link_preview=True,
80 | )
81 | else:
82 | await event.reply("Reply to a message to get a permanent telegra.ph link.")
83 |
84 |
85 | def resize_image(image):
86 | im = Image.open(image)
87 | im.save(image, "PNG")
88 |
89 |
90 | __help__ = """
91 | ❍ /tgm :Get Telegraph Link Of Replied Media
92 | ❍ /tgt :Get Telegraph Link of Replied Text
93 | ❍ /tgt [custom name]: Get telegraph link of replied text with custom name.
94 | """
95 |
96 | __mod_name__ = "T-Gʀᴀᴘʜ"
97 |
--------------------------------------------------------------------------------
/FallenRobot/modules/tiny.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | import cv2
4 | from PIL import Image
5 |
6 | from FallenRobot import telethn as tbot
7 | from FallenRobot.events import register
8 |
9 |
10 | @register(pattern="^/tiny ?(.*)")
11 | async def _(event):
12 | reply = await event.get_reply_message()
13 | if not (reply and (reply.media)):
14 | await event.reply("`Please reply to a sticker`")
15 | return
16 | kontol = await event.reply("`Processing tiny...`")
17 | ik = await tbot.download_media(reply)
18 | im1 = Image.open("FallenRobot/resources/blank_background.png")
19 | if ik.endswith(".tgs"):
20 | await tbot.download_media(reply, "blank_background.tgs")
21 | os.system("lottie_convert.py blank_background.tgs json.json")
22 | json = open("json.json", "r")
23 | jsn = json.read()
24 | jsn = jsn.replace("512", "2000")
25 | ("json.json", "w").write(jsn)
26 | os.system("lottie_convert.py json.json blank_background.tgs")
27 | file = "blank_background.tgs"
28 | os.remove("json.json")
29 | elif ik.endswith((".gif", ".mp4")):
30 | iik = cv2.VideoCapture(ik)
31 | busy = iik.read()
32 | cv2.imwrite("i.png", busy)
33 | fil = "i.png"
34 | im = Image.open(fil)
35 | z, d = im.size
36 | if z == d:
37 | xxx, yyy = 200, 200
38 | else:
39 | t = z + d
40 | a = z / t
41 | b = d / t
42 | aa = (a * 100) - 50
43 | bb = (b * 100) - 50
44 | xxx = 200 + 5 * aa
45 | yyy = 200 + 5 * bb
46 | k = im.resize((int(xxx), int(yyy)))
47 | k.save("k.png", format="PNG", optimize=True)
48 | im2 = Image.open("k.png")
49 | back_im = im1.copy()
50 | back_im.paste(im2, (150, 0))
51 | back_im.save("o.webp", "WEBP", quality=95)
52 | file = "o.webp"
53 | os.remove(fil)
54 | os.remove("k.png")
55 | else:
56 | im = Image.open(ik)
57 | z, d = im.size
58 | if z == d:
59 | xxx, yyy = 200, 200
60 | else:
61 | t = z + d
62 | a = z / t
63 | b = d / t
64 | aa = (a * 100) - 50
65 | bb = (b * 100) - 50
66 | xxx = 200 + 5 * aa
67 | yyy = 200 + 5 * bb
68 | k = im.resize((int(xxx), int(yyy)))
69 | k.save("k.png", format="PNG", optimize=True)
70 | im2 = Image.open("k.png")
71 | back_im = im1.copy()
72 | back_im.paste(im2, (150, 0))
73 | back_im.save("o.webp", "WEBP", quality=95)
74 | file = "o.webp"
75 | os.remove("k.png")
76 | await tbot.send_file(event.chat_id, file, reply_to=event.reply_to_msg_id)
77 | await kontol.delete()
78 | os.remove(file)
79 | os.remove(ik)
80 |
81 |
82 | __mod_name__ = "Tɪɴʏ"
83 | __help__ = """
84 | ❍ /tiny*:* reply a sticker and see magic
85 | """
86 |
--------------------------------------------------------------------------------
/FallenRobot/modules/translator.py:
--------------------------------------------------------------------------------
1 | from gpytranslate import SyncTranslator
2 | from telegram import ParseMode, Update
3 | from telegram.ext import CallbackContext
4 |
5 | from FallenRobot import dispatcher
6 | from FallenRobot.modules.disable import DisableAbleCommandHandler
7 |
8 | trans = SyncTranslator()
9 |
10 |
11 | def totranslate(update: Update, context: CallbackContext) -> None:
12 | message = update.effective_message
13 | reply_msg = message.reply_to_message
14 | if not reply_msg:
15 | message.reply_text(
16 | "Reply to messages or write messages from other languages for translating into the intended language\n\n"
17 | "Example: `/tr en-hi` to translate from English to Hindi\n"
18 | "Or use: `/tr en` for automatic detection and translating it into english.\n"
19 | "Click here to see [List of available Language Codes](https://te.legra.ph/LANGUAGE-CODES-05-23-2).",
20 | parse_mode="markdown",
21 | disable_web_page_preview=True,
22 | )
23 | return
24 | if reply_msg.caption:
25 | to_translate = reply_msg.caption
26 | elif reply_msg.text:
27 | to_translate = reply_msg.text
28 | try:
29 | args = message.text.split()[1].lower()
30 | if "//" in args:
31 | source = args.split("//")[0]
32 | dest = args.split("//")[1]
33 | else:
34 | source = trans.detect(to_translate)
35 | dest = args
36 | except IndexError:
37 | source = trans.detect(to_translate)
38 | dest = "en"
39 | translation = trans(to_translate, sourcelang=source, targetlang=dest)
40 | reply = (
41 | f"ᴛʀᴀɴsʟᴀᴛᴇᴅ ғʀᴏᴍ {source} ᴛᴏ {dest} :\n"
42 | f"{translation.text}
"
43 | )
44 |
45 | message.reply_text(reply, parse_mode=ParseMode.HTML)
46 |
47 |
48 | __help__ = """
49 | ❍ /tr or /tl (language code) as reply to a long message
50 | *Example:*
51 | ❍ /tr en*:* translates something to english
52 | ❍ /tr hi-en*:* translates hindi to english
53 |
54 | [ʟᴀɴɢᴜᴀɢᴇ ᴄᴏᴅᴇs](https://te.legra.ph/LANGUAGE-CODES-05-23-2)
55 | """
56 | __mod_name__ = "Tʀᴀɴsʟᴀᴛᴏʀ"
57 |
58 | TRANSLATE_HANDLER = DisableAbleCommandHandler(["tr", "tl"], totranslate, run_async=True)
59 |
60 | dispatcher.add_handler(TRANSLATE_HANDLER)
61 |
62 | __command_list__ = ["tr", "tl"]
63 | __handlers__ = [TRANSLATE_HANDLER]
64 |
--------------------------------------------------------------------------------
/FallenRobot/modules/truth_and_dare.py:
--------------------------------------------------------------------------------
1 | import requests
2 | from telegram import Update
3 | from telegram.ext import CallbackContext
4 |
5 | from FallenRobot import dispatcher
6 | from FallenRobot.modules.disable import DisableAbleCommandHandler
7 |
8 |
9 | def truth(update: Update, context: CallbackContext):
10 | truth = requests.get(f"https://api.truthordarebot.xyz/v1/truth").json()["question"]
11 | update.effective_message.reply_text(truth)
12 |
13 |
14 | def dare(update: Update, context: CallbackContext):
15 | dare = requests.get(f"https://api.truthordarebot.xyz/v1/dare").json()["question"]
16 | update.effective_message.reply_text(dare)
17 |
18 |
19 | TRUTH_HANDLER = DisableAbleCommandHandler("truth", truth, run_async=True)
20 | DARE_HANDLER = DisableAbleCommandHandler("dare", dare, run_async=True)
21 |
22 | dispatcher.add_handler(TRUTH_HANDLER)
23 | dispatcher.add_handler(DARE_HANDLER)
24 |
25 |
26 | __help__ = """
27 | *Truth & Dare*
28 |
29 | ❍ /truth *:* Sends a random truth string.
30 | ❍ /dare *:* Sends a random dare string.
31 | """
32 |
33 | __mod_name__ = "Tʀᴜᴛʜ-Dᴀʀᴇ"
34 |
--------------------------------------------------------------------------------
/FallenRobot/modules/ud.py:
--------------------------------------------------------------------------------
1 | import requests
2 | from telegram import ParseMode, Update
3 | from telegram.ext import CallbackContext
4 |
5 | from FallenRobot import dispatcher
6 | from FallenRobot.modules.disable import DisableAbleCommandHandler
7 |
8 |
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, run_async=True)
23 |
24 | dispatcher.add_handler(UD_HANDLER)
25 |
26 | __help__ = """
27 | » /ud (text) *:* Searchs the given text on Urban Dictionary and sends you the information.
28 | """
29 | __mod_name__ = "Uʀʙᴀɴ D"
30 |
31 | __command_list__ = ["ud"]
32 | __handlers__ = [UD_HANDLER]
33 |
--------------------------------------------------------------------------------
/FallenRobot/modules/wallpaper.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 | import requests
4 | from pyrogram import filters
5 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message
6 |
7 | from FallenRobot import pbot
8 |
9 | ##TO-DO
10 |
11 |
12 | @pbot.on_message(filters.command(["wall", "wallpaper"]))
13 | async def wall(_, message: Message):
14 | try:
15 | text = message.text.split(None, 1)[1]
16 | except IndexError:
17 | text = None
18 | if not text:
19 | return await message.reply_text("`Please give some query to search.`")
20 | m = await message.reply_text("`Searching for wallpapers...`")
21 | try:
22 | url = requests.get(f"https://api.safone.me/wall?query={text}").json()["results"]
23 | ran = random.randint(0, 3)
24 | await message.reply_photo(
25 | photo=url[ran]["imageUrl"],
26 | caption=f"🥀 **ʀᴇǫᴜᴇsᴛᴇᴅ ʙʏ :** {message.from_user.mention}",
27 | reply_markup=InlineKeyboardMarkup(
28 | [
29 | [InlineKeyboardButton("ʟɪɴᴋ", url=url[ran]["imageUrl"])],
30 | ]
31 | ),
32 | )
33 | await m.delete()
34 | except Exception as e:
35 | await m.edit_text(
36 | f"`ᴡᴀʟʟᴘᴀᴘᴇʀ ɴᴏᴛ ғᴏᴜɴᴅ ғᴏʀ : `{text}`",
37 | )
38 |
--------------------------------------------------------------------------------
/FallenRobot/modules/weather.py:
--------------------------------------------------------------------------------
1 | import io
2 |
3 | import aiohttp
4 | from telethon.tl import functions, types
5 |
6 | from FallenRobot import telethn as tbot
7 | from FallenRobot.events import register
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 | @register(pattern="^/weather (.*)")
23 | async def _(event):
24 | if event.fwd_from:
25 | return
26 |
27 | sample_url = "https://wttr.in/{}.png"
28 | input_str = event.pattern_match.group(1)
29 | async with aiohttp.ClientSession() as session:
30 | response_api_zero = await session.get(sample_url.format(input_str))
31 | response_api = await response_api_zero.read()
32 | with io.BytesIO(response_api) as out_file:
33 | await event.reply(file=out_file)
34 |
35 |
36 | __help__ = """
37 | I can find weather of all cities
38 |
39 | ❍ /weather *:* Advanced weather module, usage same as /weather
40 | ❍ /weather moon*:* Get the current status of moon
41 | """
42 |
43 | __mod_name__ = "Wᴇᴀᴛʜᴇʀ"
44 |
--------------------------------------------------------------------------------
/FallenRobot/modules/webshot.py:
--------------------------------------------------------------------------------
1 | from base64 import b64decode
2 | from inspect import getfullargspec
3 | from io import BytesIO
4 |
5 | from pyrogram import filters
6 | from pyrogram.types import Message
7 |
8 | from FallenRobot import pbot as app
9 | from FallenRobot.utils.post import post
10 |
11 |
12 | async def take_screenshot(url: str, full: bool = False):
13 | url = "https://" + url if not url.startswith("http") else url
14 | payload = {
15 | "url": url,
16 | "width": 1920,
17 | "height": 1080,
18 | "scale": 1,
19 | "format": "jpeg",
20 | }
21 | if full:
22 | payload["full"] = True
23 | data = await post(
24 | "https://webscreenshot.vercel.app/api",
25 | data=payload,
26 | )
27 | if "image" not in data:
28 | return None
29 | b = data["image"].replace("data:image/jpeg;base64,", "")
30 | file = BytesIO(b64decode(b))
31 | file.name = "webss.jpg"
32 | return file
33 |
34 |
35 | async def eor(msg: Message, **kwargs):
36 | func = (
37 | (msg.edit_text if msg.from_user.is_self else msg.reply)
38 | if msg.from_user
39 | else msg.reply
40 | )
41 | spec = getfullargspec(func.__wrapped__).args
42 | return await func(**{k: v for k, v in kwargs.items() if k in spec})
43 |
44 |
45 | @app.on_message(filters.command(["webss", "ss", "webshot"]))
46 | async def take_ss(_, message: Message):
47 | if len(message.command) < 2:
48 | return await eor(message, text="ɢɪᴠᴇ ᴀ ᴜʀʟ ᴛᴏ ғᴇᴛᴄʜ sᴄʀᴇᴇɴsʜᴏᴛ.")
49 |
50 | if len(message.command) == 2:
51 | url = message.text.split(None, 1)[1]
52 | full = False
53 | elif len(message.command) == 3:
54 | url = message.text.split(None, 2)[1]
55 | full = message.text.split(None, 2)[2].lower().strip() in [
56 | "yes",
57 | "y",
58 | "1",
59 | "true",
60 | ]
61 | else:
62 | return await eor(message, text="ɪɴᴠᴀʟɪᴅ ᴄᴏᴍᴍᴀɴᴅ.")
63 |
64 | m = await eor(message, text="ᴄᴀᴘᴛᴜʀɪɴɢ sᴄʀᴇᴇɴsʜᴏᴛ...")
65 |
66 | try:
67 | photo = await take_screenshot(url, full)
68 | if not photo:
69 | return await m.edit("ғᴀɪʟᴇᴅ ᴛᴏ ᴛᴀᴋᴇ sᴄʀᴇᴇɴsʜᴏᴛ.")
70 |
71 | m = await m.edit("ᴜᴘʟᴏᴀᴅɪɴɢ...")
72 |
73 | if not full:
74 | await message.reply_document(photo)
75 | else:
76 | await message.reply_document(photo)
77 | await m.delete()
78 | except Exception as e:
79 | await m.edit(str(e))
80 |
81 |
82 | __help__ = """
83 | » /webss *:* Sends the screenshot of the given url.
84 | """
85 | __mod_name__ = "Wᴇʙsʜᴏᴛ"
86 |
--------------------------------------------------------------------------------
/FallenRobot/modules/wiki.py:
--------------------------------------------------------------------------------
1 | import wikipedia
2 | from telegram import ParseMode, Update
3 | from telegram.ext import CallbackContext
4 | from wikipedia.exceptions import DisambiguationError, PageError
5 |
6 | from FallenRobot import dispatcher
7 | from FallenRobot.modules.disable import DisableAbleCommandHandler
8 |
9 |
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, run_async=True)
56 |
57 | dispatcher.add_handler(WIKI_HANDLER)
58 |
59 | __help__ = """
60 | » /wiki (text) *:* Searchs about the given text on wikipedia.
61 | """
62 | __mod_name__ = "Wɪᴋɪ"
63 |
--------------------------------------------------------------------------------
/FallenRobot/modules/writetool.py:
--------------------------------------------------------------------------------
1 | import requests
2 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode, Update
3 | from telegram.ext import CallbackContext
4 |
5 | from FallenRobot import BOT_NAME, BOT_USERNAME, dispatcher
6 | from FallenRobot.modules.disable import DisableAbleCommandHandler
7 |
8 |
9 | def handwrite(update: Update, context: CallbackContext):
10 | message = update.effective_message
11 | if message.reply_to_message:
12 | text = message.reply_to_message.text
13 | else:
14 | text = update.effective_message.text.split(None, 1)[1]
15 | m = message.reply_text("Writing the text...")
16 | req = requests.get(f"https://api.sdbots.tk/write?text={text}").url
17 | message.reply_photo(
18 | photo=req,
19 | caption=f"""
20 | Successfully Written Text 💘
21 |
22 | ✨ **Written By :** [{BOT_NAME}](https://t.me/{BOT_USERNAME})
23 | 🥀 **Requested by :** {update.effective_user.first_name}
24 | ❄ **Link :** `{req}`""",
25 | parse_mode=ParseMode.MARKDOWN,
26 | reply_markup=InlineKeyboardMarkup(
27 | [
28 | [
29 | InlineKeyboardButton("• ᴛᴇʟᴇɢʀᴀᴩʜ •", url=req),
30 | ],
31 | ]
32 | ),
33 | )
34 | m.delete()
35 |
36 |
37 | __help__ = """
38 | Writes the given text on white page with a pen 🖊
39 |
40 | ❍ /write *:*Writes the given text.
41 | """
42 |
43 | WRITE_HANDLER = DisableAbleCommandHandler("write", handwrite, run_async=True)
44 | dispatcher.add_handler(WRITE_HANDLER)
45 |
46 | __mod_name__ = "WʀɪᴛᴇTᴏᴏʟ"
47 |
48 | __command_list__ = ["write"]
49 | __handlers__ = [WRITE_HANDLER]
50 |
--------------------------------------------------------------------------------
/FallenRobot/modules/zombies.py:
--------------------------------------------------------------------------------
1 | from asyncio import sleep
2 |
3 | from pyrogram import filters
4 | from pyrogram.types import Message
5 |
6 | from FallenRobot import pbot
7 | from FallenRobot.utils.admins import can_restrict
8 |
9 |
10 | @pbot.on_message(filters.command(["zombies", "ghosts"]))
11 | @can_restrict
12 | async def ban_zombies(_, message: Message):
13 | del_zom = 0
14 | no_z = "`0 deleted accounts found in this chat.`"
15 | try:
16 | clean = message.text.split(None, 1)[1]
17 | except:
18 | clean = None
19 | if clean != "clean":
20 | check = await message.reply_text("`Searching for deleted accounts...`")
21 | async for user in pbot.get_chat_members(message.chat.id):
22 | if user.user.is_deleted:
23 | del_zom += 1
24 | await sleep(1)
25 | if del_zom > 0:
26 | return await check.edit_text(
27 | f"`{del_zom}` found in this chat.\nClean them by /zombies clean"
28 | )
29 | else:
30 | return await check.edit_text(no_z)
31 | cleaner = await message.reply_text("`Cleaning deleted accounts from this chat...`")
32 | deleted_u = []
33 | banned = 0
34 | failed = 0
35 | async for user in pbot.get_chat_members(message.chat.id):
36 | if user.user.is_deleted:
37 | deleted_u.append(int(user.user.id))
38 | if len(deleted_u) > 0:
39 | for deleted in deleted_u:
40 | try:
41 | await message.chat.ban_member(deleted)
42 | banned += 1
43 | except:
44 | continue
45 | failed += 1
46 | return await cleaner.edit_text(
47 | f"Cleaned `{banned}` zombies from this chat.\nFailed to remove `{failed}` admin zombies."
48 | )
49 | else:
50 | return await check.edit_text(no_z)
51 |
52 |
53 | __help__ = """
54 | *Remove Deleted Accounts*
55 |
56 | ❍ /zombies *:* Starts searching for deleted accounts in the group.
57 | ❍ /zombies clean *:* Removes the deleted accounts from the group.
58 | """
59 |
60 | __mod_name__ = "Zᴏᴍʙɪᴇ"
61 |
--------------------------------------------------------------------------------
/FallenRobot/resources/blank_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/blank_background.png
--------------------------------------------------------------------------------
/FallenRobot/resources/default.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/default.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fallen.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fallen.jpg
--------------------------------------------------------------------------------
/FallenRobot/resources/fglitch.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fglitch.gif
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/AVENGEANCE HEROIC AVENGER AT.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/AVENGEANCE HEROIC AVENGER AT.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/AVENGEANCE HEROIC AVENGER AT.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/AVENGEANCE HEROIC AVENGER AT.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/AVENGEANCE HEROIC AVENGER BI.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/AVENGEANCE HEROIC AVENGER BI.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Big Space.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Big Space.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/CRAWLER-RegularDEMO.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/CRAWLER-RegularDEMO.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/CROWNT.TTF:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/CROWNT.TTF
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Chopsic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Chopsic.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Crozzoe-Personal-Use.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Crozzoe-Personal-Use.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/DIGIT.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/DIGIT.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Damages-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Damages-Italic.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Damages.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Damages.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Damages3D-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Damages3D-Italic.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Damages3D.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Damages3D.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Damages3DFilled-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Damages3DFilled-Italic.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Damages3DFilled.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Damages3DFilled.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Damar Kurung.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Damar Kurung.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Damar Kurung.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Damar Kurung.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Dark Ministry.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Dark Ministry.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Dark Seed.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Dark Seed.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Dark.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Dark.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Dash-Dermo.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Dash-Dermo.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Dead Revolution.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Dead Revolution.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/DezertDemoDash.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/DezertDemoDash.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/DezertDemoItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/DezertDemoItalic.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/DezertDemoItalicDash.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/DezertDemoItalicDash.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/DezertDemoOutline.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/DezertDemoOutline.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/DezertDemoOutlineDash.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/DezertDemoOutlineDash.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/DezertDemoRegular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/DezertDemoRegular.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/DisposableDroidBB_bld.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/DisposableDroidBB_bld.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/DragonForcE.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/DragonForcE.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Dramaga Demo.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Dramaga Demo.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Dramaga Demo.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Dramaga Demo.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Dreamscar.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Dreamscar.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/EVILDEAD.TTF:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/EVILDEAD.TTF
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Europhonic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Europhonic.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Exorcista_-Jed_40.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Exorcista_-Jed_40.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Fire Flight FREE.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Fire Flight FREE.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Fire Flight FREE.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Fire Flight FREE.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/FontRemix.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/FontRemix.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/FontRemix2.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/FontRemix2.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Friend Head.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Friend Head.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Frostbite Boss Fight.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Frostbite Boss Fight.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Fucking Hostile.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Fucking Hostile.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/GRAMES.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/GRAMES.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Gang Wolfik.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Gang Wolfik.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Garda.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Garda.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Garreng-Personal-Use.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Garreng-Personal-Use.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Geizer.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Geizer.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Georgent.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Georgent.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Georgent.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Georgent.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Hallowed Grad.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Hallowed Grad.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Harker Bold Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Harker Bold Italic.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Harker Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Harker Italic.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Maghrib.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Maghrib.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/ObelixProB-cyr Alfi Stefa.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/ObelixProB-cyr Alfi Stefa.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/RealFast Alfi Stefa.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/RealFast Alfi Stefa.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Roboto-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Roboto-Italic.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Roboto-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Roboto-Medium.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/TruenoBlkOl.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/TruenoBlkOl.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/TruenoRg.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/TruenoRg.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/TruenoRgIt.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/TruenoRgIt.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/TruenoSBdIt.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/TruenoSBdIt.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/Vendetta.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/Vendetta.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/digital.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/digital.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/elric.TTF:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/elric.TTF
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/font.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/font.otf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/fontx.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/fontx.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/hawkmoon.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/hawkmoon.ttf
--------------------------------------------------------------------------------
/FallenRobot/resources/fonts/monumentextended-regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRADHAN474/managerbot/ed974ff6a42a8a18d8255a39f0a92b5c46aa2c4c/FallenRobot/resources/fonts/monumentextended-regular.otf
--------------------------------------------------------------------------------
/FallenRobot/utils/admins.py:
--------------------------------------------------------------------------------
1 | from typing import Callable
2 |
3 | from pyrogram.enums import ChatMemberStatus
4 | from pyrogram.types import Message
5 |
6 | from FallenRobot import DEV_USERS, pbot
7 |
8 |
9 | def can_restrict(func: Callable) -> Callable:
10 | async def non_admin(_, message: Message):
11 | if message.from_user.id in DEV_USERS:
12 | return await func(_, message)
13 |
14 | check = await pbot.get_chat_member(message.chat.id, message.from_user.id)
15 | if check.status not in [ChatMemberStatus.OWNER, ChatMemberStatus.ADMINISTRATOR]:
16 | return await message.reply_text(
17 | "» ʏᴏᴜ'ʀᴇ ɴᴏᴛ ᴀɴ ᴀᴅᴍɪɴ ʙᴀʙʏ, ᴘʟᴇᴀsᴇ sᴛᴀʏ ɪɴ ʏᴏᴜʀ ʟɪᴍɪᴛs."
18 | )
19 |
20 | admin = (
21 | await pbot.get_chat_member(message.chat.id, message.from_user.id)
22 | ).privileges
23 | if admin.can_restrict_members:
24 | return await func(_, message)
25 | else:
26 | return await message.reply_text(
27 | "`You don't have permissions to restrict users in this chat."
28 | )
29 |
30 | return non_admin
31 |
--------------------------------------------------------------------------------
/FallenRobot/utils/errors.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import traceback
3 | from functools import wraps
4 |
5 | from pyrogram.errors.exceptions.forbidden_403 import ChatWriteForbidden
6 |
7 | from FallenRobot import OWNER_ID, pbot
8 |
9 |
10 | def split_limits(text):
11 | if len(text) < 2048:
12 | return [text]
13 |
14 | lines = text.splitlines(True)
15 | small_msg = ""
16 | result = []
17 | for line in lines:
18 | if len(small_msg) + len(line) < 2048:
19 | small_msg += line
20 | else:
21 | result.append(small_msg)
22 | small_msg = line
23 |
24 | result.append(small_msg)
25 |
26 | return result
27 |
28 |
29 | def capture_err(func):
30 | @wraps(func)
31 | async def capture(client, message, *args, **kwargs):
32 | try:
33 | return await func(client, message, *args, **kwargs)
34 | except ChatWriteForbidden:
35 | return
36 | except Exception as err:
37 | exc_type, exc_obj, exc_tb = sys.exc_info()
38 | errors = traceback.format_exception(
39 | exc_type,
40 | value=exc_obj,
41 | tb=exc_tb,
42 | )
43 | error_feedback = split_limits(
44 | "**ERROR** | `{}` | `{}`\n\n```{}```\n\n```{}```\n".format(
45 | 0 if not message.from_user else message.from_user.id,
46 | 0 if not message.chat else message.chat.id,
47 | message.text or message.caption,
48 | "".join(errors),
49 | ),
50 | )
51 | for x in error_feedback:
52 | await pbot.send_message(OWNER_ID, x)
53 | raise err
54 |
55 | return capture
56 |
--------------------------------------------------------------------------------
/FallenRobot/utils/functions.py:
--------------------------------------------------------------------------------
1 | from io import BytesIO
2 |
3 | from aiohttp import ClientSession
4 |
5 |
6 | async def make_carbon(code):
7 | url = "https://carbonara.solopov.dev/api/cook"
8 | async with ClientSession().post(url, json={"code": code}) as resp:
9 | image = BytesIO(await resp.read())
10 | image.name = "carbon.png"
11 | return image
12 |
--------------------------------------------------------------------------------
/FallenRobot/utils/mongo.py:
--------------------------------------------------------------------------------
1 | from motor.motor_asyncio import AsyncIOMotorClient as MongoCli
2 |
3 | from FallenRobot import MONGO_DB_URI
4 |
5 | mongo = MongoCli(MONGO_DB_URI)
6 | db = mongo.FallenRobot
7 |
8 | coupledb = db.couple
9 |
10 |
11 | async def _get_lovers(chat_id: int):
12 | lovers = await coupledb.find_one({"chat_id": chat_id})
13 | if lovers:
14 | lovers = lovers["couple"]
15 | else:
16 | lovers = {}
17 | return lovers
18 |
19 |
20 | async def get_couple(chat_id: int, date: str):
21 | lovers = await _get_lovers(chat_id)
22 | if date in lovers:
23 | return lovers[date]
24 | else:
25 | return False
26 |
27 |
28 | async def save_couple(chat_id: int, date: str, couple: dict):
29 | lovers = await _get_lovers(chat_id)
30 | lovers[date] = couple
31 | await coupledb.update_one(
32 | {"chat_id": chat_id},
33 | {"$set": {"couple": lovers}},
34 | upsert=True,
35 | )
36 |
--------------------------------------------------------------------------------
/FallenRobot/utils/pastebin.py:
--------------------------------------------------------------------------------
1 | import socket
2 | from asyncio import get_running_loop
3 | from functools import partial
4 |
5 |
6 | def _netcat(host, port, content):
7 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
8 | s.connect((host, port))
9 | s.sendall(content.encode())
10 | s.shutdown(socket.SHUT_WR)
11 | while True:
12 | data = s.recv(4096).decode("utf-8").strip("\n\x00")
13 | if not data:
14 | break
15 | return data
16 | s.close()
17 |
18 |
19 | async def paste(content):
20 | loop = get_running_loop()
21 | link = await loop.run_in_executor(None, partial(_netcat, "ezup.dev", 9999, content))
22 | return link
23 |
--------------------------------------------------------------------------------
/FallenRobot/utils/post.py:
--------------------------------------------------------------------------------
1 | from aiohttp import ClientSession
2 |
3 |
4 | async def post(url: str, *args, **kwargs):
5 | async with ClientSession().post(url, *args, **kwargs) as resp:
6 | try:
7 | data = await resp.json()
8 | except Exception:
9 | data = await resp.text()
10 | return data
11 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 AnonymousX1025
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | worker: python3 -m FallenRobot
2 |
--------------------------------------------------------------------------------
/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 module.
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
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "™° 🫧 🇴 🇽 𝐘 𓃭 🇷 𝐎𝐁𝐎𝐓 ⃟⛦⃕͜༆",
3 | "description": "Telegram Group Management Bot.",
4 | "logo": "https://graph.org/file/79b2347e9834e02510895.jpg",
5 | "keywords": [
6 | "telegram",
7 | "modular",
8 | "group",
9 | "manager",
10 | "Fallen"
11 | ],
12 | "repository": "https://github.com/PRADHAN474/managerbot",
13 | "stack": "heroku-22",
14 | "addons": [
15 | {
16 | "options": {
17 | "version": "12"
18 | },
19 | "plan": "heroku-postgresql"
20 | }
21 | ],
22 | "env": {
23 | "API_ID": {
24 | "description": "Get this value from my.telegram.org/apps.",
25 | "required": true,
26 | "value": "28365981"
27 | },
28 | "API_HASH": {
29 | "description": "Get this value from my.telegram.org/apps.",
30 | "required": true,
31 | "value": "3c382f8e3f46ffd6cd9526d2aebc4c3a"
32 | },
33 | "ALLOW_EXCL": {
34 | "description": "Set this to True if you want ! to be a command prefix along with /. Recommended is True",
35 | "value": "True"
36 | },
37 | "CASH_API_KEY": {
38 | "description": "Required for currency converter. Get yours from https://www.alphavantage.co/support/#api-key",
39 | "required": true,
40 | "value": "KZOKAC9RSH0YORF9"
41 | },
42 | "DEL_CMDS": {
43 | "description": "Set this to True if you want to delete command messages from users who don't have the perms to run that command.",
44 | "value": "True"
45 | },
46 | "ENV": {
47 | "description": "Setting this to ANYTHING will enable environment variables. Leave it as it is",
48 | "required": true,
49 | "value": "True"
50 | },
51 | "EVENT_LOGS": {
52 | "description": "Event logs channel to note down important bot level events, recommend to make this public. ex: '-123456'",
53 | "required": true,
54 | "value": ""
55 | },
56 | "MONGO_DB_URI": {
57 | "description": "Required for database connections.",
58 | "required": true,
59 | "value": ""
60 | },
61 | "OWNER_ID": {
62 | "description": "Your user ID as an integer.",
63 | "required": false,
64 | "value": "5059737154"
65 | },
66 | "START_IMG": {
67 | "description": "Telegraph link of the image which will be shown at start command.",
68 | "required": true,
69 | "value": "https://graph.org/file/79b2347e9834e02510895.jpg"
70 | },
71 | "SUPPORT_CHAT": {
72 | "description": "Your Telegram support group chat username where your users will go and bother you with shit But be like: MyGroupChatUsernameBlah. If this ever points to Fallen Support than consider you made an enemy.",
73 | "required": false,
74 | "value": "BWANDARLOK"
75 | },
76 | "TIME_API_KEY": {
77 | "description": "Required for timezone information. Get yours from https://timezonedb.com/api",
78 | "required": true,
79 | "value": "B9Y6LCIU7C29"
80 | },
81 | "TOKEN": {
82 | "description": "Get bot token from @BotFather on TG",
83 | "required": true,
84 | "value": ""
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/heroku.yml:
--------------------------------------------------------------------------------
1 | build:
2 | docker:
3 | worker: Dockerfile
4 | run:
5 | worker: python3 -m FallenRobot
6 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | aiofiles==23.1.0
2 | aiohttp==3.8.5
3 | apscheduler==3.6.3
4 | asyncio==3.4.3
5 | beautifulsoup4==4.12.2
6 | bing_image_downloader==1.1.2
7 | bleach==6.0.0
8 | bs4==0.0.1
9 | cachetools==4.2.2
10 | countryinfo==0.1.2
11 | currencyconverter==0.17.9
12 | dateparser==1.1.8
13 | emoji==2.6.0
14 | emoji-country-flag==1.3.2
15 | feedparser==6.0.10
16 | future==0.18.3
17 | geopy==2.3.0
18 | gpytranslate==1.5.1
19 | hachoir==3.2.0
20 | html2text==2020.1.16
21 | jikanpy==4.3.2
22 | lxml==4.9.3
23 | markdown2==2.4.9
24 | motor==3.2.0
25 | opencv-python-headless==4.8.0.74
26 | pillow==10.0.0
27 | pretty_errors==1.2.25
28 | psutil==5.9.5
29 | psycopg2-binary==2.9.6
30 | pydictionary==2.0.1
31 | pykeyboard==0.1.5
32 | pynewtonmath==1.0.1
33 | pyrate-limiter==2.10.0
34 | pyrogram==2.0.106
35 | python-telegram-bot==13.15
36 | regex==2023.6.3
37 | requests==2.31.0
38 | secureme==0.0.4
39 | search_engine_parser==0.6.8
40 | speedtest-cli==2.1.3
41 | sqlalchemy==1.4.46
42 | telegraph==2.2.0
43 | telethon==1.29.1
44 | tgcrypto==1.2.5
45 | wikipedia==1.4.0
46 |
--------------------------------------------------------------------------------
/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.10.12
2 |
--------------------------------------------------------------------------------
/start.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | TITLE Fallen Robot
3 | :: Enables virtual env mode and then starts Fallen
4 | env\scripts\activate.bat && py -m FallenRobot
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 FallenRobot
31 | net start FallenRobot
32 |
--------------------------------------------------------------------------------