This commit is contained in:
AbhiTheModder
2023-02-09 11:55:47 +05:30
parent e8087d9c93
commit 3e8520b0f5
17 changed files with 2888 additions and 2956 deletions

View File

@@ -14,7 +14,7 @@
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://makeapullrequest.com)
</p>
#### _A Simple, Fast, Customizable Userbot for Telegram._
#### _A Simple, Fast, Customizable Userbot for Telegram made after Dragon-Userbot abandoned._
<h1>Installation</h1>

View File

@@ -1,18 +1,18 @@
#  Moon-Userbot - telegram userbot
#  Copyright (C) 2020-present Moon Userbot Organization
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
#  This program is free software: you can redistribute it and/or modify
#  it is under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import datetime
import sys
@@ -21,51 +21,46 @@ from pyrogram import Client
from utils import config
if __name__ == "__main__":
app = Client(
"my_account",
api_id = config.api_id,
api_hash = config.api_hash,
hide_password = True,
test_mode = config.test_server,
)
app = Client(
"my_account",
api_id=config.api_id,
api_hash=config.api_hash,
hide_password=True,
test_mode=config.test_server,
)
if config.db_type in ["mongo", "mongodb"]:
from pymongo import MongoClient, errors
if config.db_type in ["mongo", "mongodb"]:
from pymongo import MongoClient, errors
db = MongoClient(config.db_url)
try:
db.server_info()
except errors.ConnectionFailure as e:
raise RuntimeError(
"MongoDB server isn't available! "
f"Provided url:  {
config.db_url
}. "
"Enter valid URL and restart installation"
) from e
db = MongoClient(config.db_url)
try:
db.server_info()
except errors.ConnectionFailure as e:
raise RuntimeError(
"MongoDB server isn't available! "
f"Provided url: {config.db_url}. "
"Enter valid URL and restart installation"
) from e
install_type = sys.argv[1] if len(sys.argv) > 1 else "3"
if install_type == "1":
restart = "pm2 restart Moon"
elif install_type == "2":
restart = "sudo systemctl restart Moon"
else :
restart = "cd Moon-Userbot/ && python main.py"
install_type = sys.argv[1] if len(sys.argv) > 1 else "3"
if install_type == "1":
restart = "pm2 restart Moon"
elif install_type == "2":
restart = "sudo systemctl restart Moon"
else:
restart = "cd Moon-Userbot/ && python main.py"
app.start()
try:
app.send_message(
"me",
f"<b>[ {
datetime.datetime.now()}] Moon-Userbot launched! \n"
"Channel: @moonuserbot\n"
"Custom modules: @moonub_modules\n"
"Chat [RU]: @moonub_chat\n"
f"For restart, enter:</b>\n"
f"<code> {
restart
}</code>",
)
except Exception:
pass
app.stop()
app.start()
try:
app.send_message(
"me",
f"<b>[{datetime.datetime.now()}] Moon-Userbot launched! \n"
"Channel: @moonuserbot\n"
"Custom modules: @moonub_modules\n"
"Chat [RU]: @moonub_chat\n"
f"For restart, enter:</b>\n"
f"<code>{restart}</code>",
)
except Exception:
pass
app.stop()

View File

@@ -1,159 +1,164 @@
#!/bin/bash
if command -v termux-setup-storage; then
echo For termux, please use https://raw.githubusercontent.com/The-MoonTg-project/Moon-Userbot/main/termux-install.sh
exit 1
echo For termux, please use https://raw.githubusercontent.com/The-MoonTg-project/Moon-Userbot/main/termux-install.sh
exit 1
fi
if [[$UID != 0]]; then
echo Please run this script as root
exit 1
if [[ $UID != 0 ]]; then
echo Please run this script as root
exit 1
fi
apt update -y
apt install python3 python3-pip git ffmpeg wget gnupg -y || exit 2
su -c "python3 -m pip install -U pip" $SUDO_USER
su -c "python3 -m pip install -U wheel pillow" $SUDO_USER
su -c "python3 -m pip install -U pip" $SUDO_USER
su -c "python3 -m pip install -U wheel pillow" $SUDO_USER
if [[-d "Moon-Userbot"]]; then
cd Moon-Userbot
elif [[-f ".env.dist"]] && [[-f "main.py"]] && [[-d "modules"]]; then
:
if [[ -d "Moon-Userbot" ]]; then
cd Moon-Userbot
elif [[ -f ".env.dist" ]] && [[ -f "main.py" ]] && [[ -d "modules" ]]; then
:
else
git clone https://github.com/The-MoonTg-project/Moon-Userbot || exit 2
cd Moon-Userbot || exit 2
git clone https://github.com/The-MoonTg-project/Moon-Userbot || exit 2
cd Moon-Userbot || exit 2
fi
if [[-f ".env"]] && [[-f "my_account.session"]]; then
echo "It seems that Moon-Userbot is already installed. Exiting..."
exit
if [[ -f ".env" ]] && [[ -f "my_account.session" ]]; then
echo "It seems that Moon-Userbot is already installed. Exiting..."
exit
fi
su -c "python3 -m pip install -U -r requirements.txt" $SUDO_USER || exit 2
su -c "python3 -m pip install -U -r requirements.txt" $SUDO_USER || exit 2
echo
echo "Enter API_ID and API_HASH"
echo "You can get it here -> https://my.telegram.org/apps"
echo "Leave empty to use defaults (please note that default keys significantly increases your ban chances)"
read -r -p "API_ID > " api_id
echo "Enter API_ID and API_HASH"
echo "You can get it here -> https://my.telegram.org/"
echo "Leave empty to use defaults (please note that default keys significantly increases your ban chances)"
read -r -p "API_ID > " api_id
if [[$api_id = ""]]; then
api_id = "2040"
api_hash = "b18441a1ff607e10a989891a5462e627"
if [[ $api_id = "" ]]; then
api_id="2040"
api_hash="b18441a1ff607e10a989891a5462e627"
else
read -r -p "API_HASH > " api_hash
read -r -p "API_HASH > " api_hash
fi
echo
echo "Choose database type:"
echo "[1] MongoDB db_url"
echo "[2] MongoDB localhost"
echo "[3] Sqlite (default)"
read -r -p "> " db_type
echo "Choose database type:"
echo "[1] MongoDB db_url"
echo "[2] MongoDB localhost"
echo "[3] Sqlite (default)"
read -r -p "> " db_type
echo
case $db_type in
1)
echo "Please enter db_url"
echo "You can get it here -> "
read -r -p "> " db_url
db_name = Moon_Userbot
db_type = mongodb
;;
2)
if systemctl status mongodb; then
wget -qO - https://www.mongodb.org/static/pgp/server-5.0.asc | apt-key add -
source /etc/os-release
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu $ {
UBUNTU_CODENAME
}/mongodb-org/5.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-5.0.list
apt update
apt install mongodb -y
systemctl daemon-reload
systemctl enable mongodb
fi
systemctl start mongodb
1)
echo "Please enter db_url"
echo "You can get it here -> https://mongodb.com/atlas"
read -r -p "> " db_url
db_name=Moon_Userbot
db_type=mongodb
;;
2)
if systemctl status mongodb; then
wget -qO - https://www.mongodb.org/static/pgp/server-5.0.asc | apt-key add -
source /etc/os-release
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu ${UBUNTU_CODENAME}/mongodb-org/5.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-5.0.list
apt update
apt install mongodb -y
systemctl daemon-reload
systemctl enable mongodb
fi
systemctl start mongodb
db_url = mongodb://localhost:27017
db_name = Moon_Userbot
db_type = mongodb
;;
*)
db_name = db.sqlite3
db_type = sqlite3
;;
db_url=mongodb://localhost:27017
db_name=Moon_Userbot
db_type=mongodb
;;
*)
db_name=db.sqlite3
db_type=sqlite3
;;
esac
cat > .env << EOL
API_ID=${api_id}
API_HASH=${api_hash}
# sqlite/sqlite3 or mongo/mongodb
DATABASE_TYPE=${db_type}
# file name for sqlite3, database name for mongodb
DATABASE_NAME=${db_name}
# only for mongodb
DATABASE_URL=${db_url}
EOL
chown -R $SUDO_USER:$SUDO_USER .
echo
echo "Choose installation type:"
echo "[1] PM2"
echo "[2] Systemd service"
echo "[3] Custom (default)"
read -r -p "> " install_type
su -c "python3 install.py ${install_type}" $SUDO_USER || exit 3
case $install_type in
  1)
    if ! command -v pm2; then
      curl -fsSL https://deb.nodesource.com/setup_17.x | bash
      apt install nodejs -y
      npm install pm2 -g
      su -c "pm2 startup" $SUDO_USER
      env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u $SUDO_USER --hp /home/$SUDO_USER
    fi
    su -c "pm2 start main.py --name Moon --interpreter python3" $SUDO_USER
    su -c "pm2 save" $SUDO_USER
    echo
    echo "============================"
    echo "Great! Moon-Userbot installed successfully and running now!"
    echo "Installation type: PM2"
    echo "Start with: \"pm2 start Moon\""
    echo "Stop with: \"pm2 stop Moon\""
    echo "Process name: Moon"
    echo "============================"
    ;;
  2)
    cat > /etc/systemd/system/Moon.service << EOL
[Unit]
Description=Service for Moon Userbot
[Service]
Type=simple
ExecStart=$(which python3) ${PWD}/main.py
WorkingDirectory=${PWD}
Restart=always
User=${SUDO_USER}
Group=${SUDO_USER}
[Install]
WantedBy=multi-user.target
EOL
    systemctl daemon-reload
    systemctl start Moon
    systemctl enable Moon
    echo
    echo "============================"
    echo "Great! Moon-Userbot installed successfully and running now!"
    echo "Installation type: Systemd service"
    echo "Start with: \"sudo systemctl start Moon\""
    echo "Stop with: \"sudo systemctl stop Moon\""
    echo "============================"
    ;;
  *)
    echo
    echo "============================"
    echo "Great! Moon-Userbot installed successfully!"
    echo "Installation type: Custom"
    echo "Start with: \"python3 main.py\""
    echo "============================"
    ;;
esac
chown -R $SUDO_USER:$SUDO_USER .
API_ID=${api_id}
API_HASH=${api_hash}
# sqlite/sqlite3 or mongo/mongodb
DATABASE_TYPE=${db_type}
# file name for sqlite3, database name for mongodb
DATABASE_NAME=${db_name}
# only for mongodb
DATABASE_URL=${db_url}
EOL
chown -R $SUDO_USER:$SUDO_USER .
echo
echo "Choose installation type:"
echo "[1] PM2"
echo "[2] Systemd service"
echo "[3] Custom (default)"
read -r -p "> " install_type
su -c "python3 install.py ${install_type}" $SUDO_USER || exit 3
case $install_type in
1)
if ! command -v pm2; then
curl -fsSL https://deb.nodesource.com/setup_17.x | bash
apt install nodejs -y
npm install pm2 -g
su -c "pm2 startup" $SUDO_USER
env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u $SUDO_USER --hp /home/$SUDO_USER
fi
su -c "pm2 start main.py --name Moon --interpreter python3" $SUDO_USER
su -c "pm2 save" $SUDO_USER
echo
echo "============================"
echo "Great! Moon-Userbot installed successfully and running now!"
echo "Installation type: PM2"
echo "Start with: \"pm2 start Moon\""
echo "Stop with: \"pm2 stop Moon\""
echo "Process name: Moon"
echo "============================"
;;
2)
cat > /etc/systemd/system/Moon.service << EOL
[Unit]
Description=Service for Moon Userbot
[Service]
Type=simple
ExecStart=$(which python3) ${PWD}/main.py
WorkingDirectory=${PWD}
Restart=always
User=${SUDO_USER}
Group=${SUDO_USER}
[Install]
WantedBy=multi-user.target
EOL
systemctl daemon-reload
systemctl start Moon
systemctl enable Moon
echo
echo "============================"
echo "Great! Moon-Userbot installed successfully and running now!"
echo "Installation type: Systemd service"
echo "Start with: \"sudo systemctl start Moon\""
echo "Stop with: \"sudo systemctl stop Moon\""
echo "============================"
;;
*)
echo
echo "============================"
echo "Great! Moon-Userbot installed successfully!"
echo "Installation type: Custom"
echo "Start with: \"python3 main.py\""
echo "============================"
;;
esac
chown -R $SUDO_USER:$SUDO_USER .

273
main.py
View File

@@ -1,18 +1,18 @@
#  Moon-Userbot - telegram userbot
#  Copyright (C) 2020-present Moon Userbot Organization
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
#  This program is free software: you can redistribute it and/or modify
#  it is under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import sqlite3
import subprocess
@@ -25,162 +25,135 @@ from importlib import import_module
import logging
import platform
logging.basicConfig(level = logging.INFO)
logging.basicConfig(level=logging.INFO)
DeleteAccount.__new__ = None
if __name__ == "__main__":
script_path = os.path.dirname(os.path.realpath(__file__))
if script_path != os.getcwd():
os.chdir(script_path)
script_path = os.path.dirname(os.path.realpath(__file__))
if script_path != os.getcwd():
os.chdir(script_path)
if os.path.exists("./config.ini.old") and not os.path.exists("./.env"):
logging.warning("Old config.ini file detected! Converting to .env...")
import configparser
if os.path.exists("./config.ini.old") and not os.path.exists("./.env"):
logging.warning("Old config.ini file detected! Converting to .env...")
import configparser
parser = configparser.ConfigParser()
parser.read("./config.ini.old")
db_url = parser.get("pyrogram", "db_url")
db_name = parser.get("db", "db_name")
parser = configparser.ConfigParser()
parser.read("./config.ini.old")
db_url = parser.get("pyrogram", "db_url")
db_name = parser.get("db", "db_name")
with open(".env.dist") as f:
env_text = f.read().format(
db_url = db_url,
db_name = db_name,
db_type = "mongodb",
)
with open(".env.dist") as f:
env_text = f.read().format(
db_url=db_url,
db_name=db_name,
db_type="mongodb",
)
with open(".env", "w") as f:
f.write(env_text)
with open(".env", "w") as f:
f.write(env_text)
os.remove("./config.ini.old")
os.remove("./config.ini.old")
logging.warning("Old config file has been successfully converted")
logging.warning("Old config file has been successfully converted")
from utils.db import db
from utils.misc import gitrepo, userbot_version
from utils.scripts import restart
from utils import config
from utils.db import db
from utils.misc import gitrepo, userbot_version
from utils.scripts import restart
from utils import config
app = Client(
"my_account",
api_id = config.api_id,
api_hash = config.api_hash,
hide_password = True,
workdir = script_path,
app_version = userbot_version,
device_model = f"Moon-Userbot @  {
gitrepo.head.commit.hexsha[:7]}",
system_version = platform.version() + " " + platform.machine(),
sleep_threshold = 30,
test_mode = config.test_server,
parse_mode = "html",
)
app = Client(
"my_account",
api_id=config.api_id,
api_hash=config.api_hash,
hide_password=True,
workdir=script_path,
app_version=userbot_version,
device_model=f"Moon-Userbot @ {gitrepo.head.commit.hexsha[:7]}",
system_version=platform.version() + " " + platform.machine(),
sleep_threshold=30,
test_mode=config.test_server,
parse_mode="html",
)
try:
app.start()
except sqlite3.OperationalError as e:
if str(e) == "database is locked" and os.name == "posix":
logging.warning(
"Session file is locked. Trying to kill blocking process..."
)
subprocess.run(["fuser", "-k", "my_account.session"])
restart()
raise
except (errors.NotAcceptable, errors.Unauthorized) as e:
logging.error(
f" {
e.__class__.__name__
}:  {
e
}\n"
f"Moving session file to my_account.session-old..."
)
os.rename("./my_account.session", "./my_account.session-old")
restart()
try:
app.start()
except sqlite3.OperationalError as e:
if str(e) == "database is locked" and os.name == "posix":
logging.warning(
"Session file is locked. Trying to kill blocking process..."
)
subprocess.run(["fuser", "-k", "my_account.session"])
restart()
raise
except (errors.NotAcceptable, errors.Unauthorized) as e:
logging.error(
f"{e.__class__.__name__}: {e}\n"
f"Moving session file to my_account.session-old..."
)
os.rename("./my_account.session", "./my_account.session-old")
restart()
success_handlers = 0
failed_handlers = 0
success_modules = 0
failed_modules = 0
success_handlers = 0
failed_handlers = 0
success_modules = 0
failed_modules = 0
for path in sorted((Path("modules")).rglob("*.py")):
module_path = ".".join(path.parent.parts + (path.stem,))
try:
module = import_module(module_path)
for name, obj in vars(module).items():
# defaulting to [] if obj isn't a function-handler
for handler, group in getattr(obj, "handlers", []):
try:
app.add_handler(handler, group)
success_handlers += 1
except Exception as e:
failed_handlers += 1
logging.warning(
f"Can't add  {
module_path
}. {
name
}. {
handler.__name__
}:  {
e.__class__.__name__
}:  {
e
}"
)
except Exception as e:
logging.warning(
f"Can't import module  {
module_path
}:  {
e.__class__.__name__
}:  {
e
}"
)
failed_modules += 1
else :
success_modules += 1
for path in sorted((Path("modules")).rglob("*.py")):
module_path = ".".join(path.parent.parts + (path.stem,))
try:
module = import_module(module_path)
for name, obj in vars(module).items():
# defaulting to [] if obj isn't a function-handler
for handler, group in getattr(obj, "handlers", []):
try:
app.add_handler(handler, group)
success_handlers += 1
except Exception as e:
failed_handlers += 1
logging.warning(
f"Can't add {module_path}.{name}.{handler.__name__}: {e.__class__.__name__}: {e}"
)
except Exception as e:
logging.warning(
f"Can't import module {module_path}: {e.__class__.__name__}: {e}"
)
failed_modules += 1
else:
success_modules += 1
logging.info(
f"Imported  {
success_handlers
} handlers from  {
success_modules
} modules."
)
if failed_modules:
logging.warning(f"Failed to import  {
failed_modules
} modules")
if failed_handlers:
logging.warning(f"Failed to add  {
failed_handlers
} to handlers")
logging.info(
f"Imported {success_handlers} handlers from {success_modules} modules."
)
if failed_modules:
logging.warning(f"Failed to import {failed_modules} modules")
if failed_handlers:
logging.warning(f"Failed to add {failed_handlers} to handlers")
if len(sys.argv) == 4:
restart_type = sys.argv[3]
if restart_type == "1":
text = "<b>Update process completed!</b>"
else :
text = "<b>Restart completed!</b>"
try:
app.send_message(
chat_id = sys.argv[1], text = text, reply_to_message_id = int(sys.argv[2])
)
except errors.RPCError:
app.send_message(chat_id = sys.argv[1], text = text)
if len(sys.argv) == 4:
restart_type = sys.argv[3]
if restart_type == "1":
text = "<b>Update process completed!</b>"
else:
text = "<b>Restart completed!</b>"
try:
app.send_message(
chat_id=sys.argv[1], text=text, reply_to_message_id=int(
sys.argv[2])
)
except errors.RPCError:
app.send_message(chat_id=sys.argv[1], text=text)
# required for sessionkiller module
if db.get("core.sessionkiller", "enabled", False):
db.set(
"core.sessionkiller",
"auths_hashes",
[auth.hash for auth in app.send(GetAuthorizations()).authorizations],
)
# required for sessionkiller module
if db.get("core.sessionkiller", "enabled", False):
db.set(
"core.sessionkiller",
"auths_hashes",
[auth.hash for auth in app.send(
GetAuthorizations()).authorizations],
)
logging.info("Moon-Userbot started!")
logging.info("Moon-Userbot started!")
idle()
idle()

File diff suppressed because it is too large Load Diff

View File

@@ -1,129 +1,129 @@
#  Moon-Userbot - telegram userbot
#  Copyright (C) 2020-present Moon Userbot Organization
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
import json
from html import escape as t
from time import perf_counter
from pyrogram import Client, filters
from pyrogram.errors.exceptions.flood_420 import FloodWait
from pyrogram.raw.functions.messages.get_all_chats import GetAllChats
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import format_exc
@Client.on_message(filters.command("admcount", prefix) & filters.me)
async def admcount(client: Client, message: Message):
    await message.edit("<b>Retrieving information... (it'll take some time)</b>")
    start = perf_counter()
    try:
        response = await client.send(GetAllChats(except_ids=[]))
        chats = response["chats"]
        adminned_chats = 0
        owned_chats = 0
        owned_usernamed_chats = 0
        for chat in chats:
            if getattr(chat, "migrated_to", None):
                continue
            if chat.creator and getattr(chat, "username", None):
                owned_usernamed_chats += 1
            elif chat.creator:
                owned_chats += 1
            elif getattr(chat, "admin_rights", None):
                adminned_chats += 1
    except Exception as e:
        await message.edit(format_exc(e))
        return
    stop = perf_counter()
    await message.edit(
        f"<b><u>Total:</u></b> {adminned_chats + owned_chats + owned_usernamed_chats}"
        f"\n<b><u>Adminned chats:</u></b> {adminned_chats}\n"
        f"<b><u>Owned chats:</u></b> {owned_chats}\n"
        f"<b><u>Owned chats with username:</u></b> {owned_usernamed_chats}\n\n"
        f"Done at {round(stop - start, 3)} seconds.\n\n"
        f"<b>Get full list: </b><code>{prefix}admlist</code>"
    )
@Client.on_message(filters.command("admlist", prefix) & filters.me)
async def admlist(client: Client, message: Message):
    await message.edit("<b>Retrieving information... (it'll take some time)</b>")
    start = perf_counter()
    try:
        response = await client.send(GetAllChats(except_ids=[]))
        chats = response["chats"]
        adminned_chats = []
        owned_chats = []
        owned_usernamed_chats = []
        for chat in chats:
            if getattr(chat, "migrated_to", None) is not None:
                continue
            if chat.creator and getattr(chat, "username", None):
                owned_usernamed_chats.append(chat)
            elif chat.creator:
                owned_chats.append(chat)
            elif getattr(chat, "admin_rights", None):
                adminned_chats.append(chat)
        text = "<b>Adminned chats:</b>\n"
        for index, chat in enumerate(adminned_chats):
            text += (
                f"{index + 1}. <a href=https://t.me/c/{chat.id}/1>{chat.title}</a>\n"
            )
        text += "\n<b>Owned chats:</b>\n"
        for index, chat in enumerate(owned_chats):
            text += (
                f"{index + 1}. <a href=https://t.me/c/{chat.id}/1>{chat.title}</a>\n"
            )
        text += "\n<b>Owned chats with username:</b>\n"
        for index, chat in enumerate(owned_usernamed_chats):
            text += (
                f"{index + 1}. <a href=https://t.me/{chat.username}>{chat.title}</a>\n"
            )
        stop = perf_counter()
        total_count = (
            len(adminned_chats) + len(owned_chats) + len(owned_usernamed_chats)
        )
        await message.edit(
            text + "\n"
            f"<b><u>Total:</u></b> {total_count}"
            f"\n<b><u>Adminned chats:</u></b> {len(adminned_chats)}\n"
            f"<b><u>Owned chats:</u></b> {len(owned_chats)}\n"
            f"<b><u>Owned chats with username:</u></b> {len(owned_usernamed_chats)}\n\n"
            f"Done at {round(stop - start, 3)} seconds."
        )
    except Exception as e:
        await message.edit(format_exc(e))
        return
modules_help["admlist"] = {
    "admcount": "Get count of adminned and owned chats",
    "admlist": "Get list of adminned and owned chats",
}
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import json
from html import escape as t
from time import perf_counter
from pyrogram import Client, filters
from pyrogram.errors.exceptions.flood_420 import FloodWait
from pyrogram.raw.functions.messages.get_all_chats import GetAllChats
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import format_exc
@Client.on_message(filters.command("admcount", prefix) & filters.me)
async def admcount(client: Client, message: Message):
await message.edit("<b>Retrieving information... (it'll take some time)</b>")
start = perf_counter()
try:
response = await client.send(GetAllChats(except_ids=[]))
chats = response["chats"]
adminned_chats = 0
owned_chats = 0
owned_usernamed_chats = 0
for chat in chats:
if getattr(chat, "migrated_to", None):
continue
if chat.creator and getattr(chat, "username", None):
owned_usernamed_chats += 1
elif chat.creator:
owned_chats += 1
elif getattr(chat, "admin_rights", None):
adminned_chats += 1
except Exception as e:
await message.edit(format_exc(e))
return
stop = perf_counter()
await message.edit(
f"<b><u>Total:</u></b> {adminned_chats + owned_chats + owned_usernamed_chats}"
f"\n<b><u>Adminned chats:</u></b> {adminned_chats}\n"
f"<b><u>Owned chats:</u></b> {owned_chats}\n"
f"<b><u>Owned chats with username:</u></b> {owned_usernamed_chats}\n\n"
f"Done at {round(stop - start, 3)} seconds.\n\n"
f"<b>Get full list: </b><code>{prefix}admlist</code>"
)
@Client.on_message(filters.command("admlist", prefix) & filters.me)
async def admlist(client: Client, message: Message):
await message.edit("<b>Retrieving information... (it'll take some time)</b>")
start = perf_counter()
try:
response = await client.send(GetAllChats(except_ids=[]))
chats = response["chats"]
adminned_chats = []
owned_chats = []
owned_usernamed_chats = []
for chat in chats:
if getattr(chat, "migrated_to", None) is not None:
continue
if chat.creator and getattr(chat, "username", None):
owned_usernamed_chats.append(chat)
elif chat.creator:
owned_chats.append(chat)
elif getattr(chat, "admin_rights", None):
adminned_chats.append(chat)
text = "<b>Adminned chats:</b>\n"
for index, chat in enumerate(adminned_chats):
text += (
f"{index + 1}. <a href=https://t.me/c/{chat.id}/1>{chat.title}</a>\n"
)
text += "\n<b>Owned chats:</b>\n"
for index, chat in enumerate(owned_chats):
text += (
f"{index + 1}. <a href=https://t.me/c/{chat.id}/1>{chat.title}</a>\n"
)
text += "\n<b>Owned chats with username:</b>\n"
for index, chat in enumerate(owned_usernamed_chats):
text += (
f"{index + 1}. <a href=https://t.me/{chat.username}>{chat.title}</a>\n"
)
stop = perf_counter()
total_count = (
len(adminned_chats) + len(owned_chats) + len(owned_usernamed_chats)
)
await message.edit(
text + "\n"
f"<b><u>Total:</u></b> {total_count}"
f"\n<b><u>Adminned chats:</u></b> {len(adminned_chats)}\n"
f"<b><u>Owned chats:</u></b> {len(owned_chats)}\n"
f"<b><u>Owned chats with username:</u></b> {len(owned_usernamed_chats)}\n\n"
f"Done at {round(stop - start, 3)} seconds."
)
except Exception as e:
await message.edit(format_exc(e))
return
modules_help["admlist"] = {
"admcount": "Get count of adminned and owned chats",
"admlist": "Get list of adminned and owned chats",
}

View File

@@ -1,85 +1,86 @@
#  Moon-Userbot - telegram userbot
#  Copyright (C) 2020-present Moon Userbot Organization
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
import datetime
from pyrogram import Client, filters, types
from utils.misc import modules_help, prefix
from utils.db import db
# avoid using global variables
afk_info = db.get(
    "core.afk",
    "afk_info",
    {
        "start": 0,
        "is_afk": False,
        "reason": "",
    },
)
is_afk = filters.create(lambda _, __, ___: afk_info["is_afk"])
@Client.on_message(
    is_afk
    & (filters.private | filters.mentioned)
    & ~filters.channel
    & ~filters.me
    & ~filters.bot
)
async def afk_handler(_, message: types.Message):
    start = datetime.datetime.fromtimestamp(afk_info["start"])
    end = datetime.datetime.now().replace(microsecond=0)
    afk_time = end - start
    await message.reply(
        f"<b>I'm AFK {afk_time}\n" f"Reason:</b> <i>{afk_info['reason']}</i>"
    )
@Client.on_message(filters.command("afk", prefix) & filters.me)
async def afk(_, message):
    if len(message.text.split()) >= 2:
        reason = message.text.split(" ", maxsplit=1)[1]
    else:
        reason = "None"
    afk_info["start"] = int(datetime.datetime.now().timestamp())
    afk_info["is_afk"] = True
    afk_info["reason"] = reason
    await message.edit(f"<b>I'm going AFK.\n" f"Reason:</b> <i>{reason}</i>")
    db.set("core.afk", "afk_info", afk_info)
@Client.on_message(filters.command("unafk", prefix) & filters.me)
async def unafk(_, message):
    if afk_info["is_afk"]:
        start = datetime.datetime.fromtimestamp(afk_info["start"])
        end = datetime.datetime.now().replace(microsecond=0)
        afk_time = end - start
        await message.edit(f"<b>I'm not AFK anymore.\n" f"I was afk {afk_time}</b>")
        afk_info["is_afk"] = False
    else:
        await message.edit("<b>You weren't afk</b>")
    db.set("core.afk", "afk_info", afk_info)
modules_help["afk"] = {"afk [reason]": "Go to afk", "unafk": "Get out of AFK"}
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import datetime
from pyrogram import Client, filters, types
from utils.misc import modules_help, prefix
from utils.db import db
# avoid using global variables
afk_info = db.get(
"core.afk",
"afk_info",
{
"start": 0,
"is_afk": False,
"reason": "",
},
)
is_afk = filters.create(lambda _, __, ___: afk_info["is_afk"])
@Client.on_message(
is_afk
& (filters.private | filters.mentioned)
& ~filters.channel
& ~filters.me
& ~filters.bot
)
async def afk_handler(_, message: types.Message):
start = datetime.datetime.fromtimestamp(afk_info["start"])
end = datetime.datetime.now().replace(microsecond=0)
afk_time = end - start
await message.reply(
f"<b>I'm AFK {afk_time}\n" f"Reason:</b> <i>{afk_info['reason']}</i>"
)
@Client.on_message(filters.command("afk", prefix) & filters.me)
async def afk(_, message):
if len(message.text.split()) >= 2:
reason = message.text.split(" ", maxsplit=1)[1]
else:
reason = "None"
afk_info["start"] = int(datetime.datetime.now().timestamp())
afk_info["is_afk"] = True
afk_info["reason"] = reason
await message.edit(f"<b>I'm going AFK.\n" f"Reason:</b> <i>{reason}</i>")
db.set("core.afk", "afk_info", afk_info)
@Client.on_message(filters.command("unafk", prefix) & filters.me)
async def unafk(_, message):
if afk_info["is_afk"]:
start = datetime.datetime.fromtimestamp(afk_info["start"])
end = datetime.datetime.now().replace(microsecond=0)
afk_time = end - start
await message.edit(f"<b>I'm not AFK anymore.\n" f"I was afk {afk_time}</b>")
afk_info["is_afk"] = False
else:
await message.edit("<b>You weren't afk</b>")
db.set("core.afk", "afk_info", afk_info)
modules_help["afk"] = {
"afk [reason]": "Go to afk(note that afk module is not fully completed yet so to unafk it's unable tp detect user messages and disable automatically so you'll have to manually use .unafk command for a while ASAP )", "unafk": "Get out of AFK"}

View File

@@ -1,125 +1,126 @@
#  Moon-Userbot - telegram userbot
#  Copyright (C) 2020-present Moon Userbot Organization
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, filters
from pyrogram.raw import functions
from pyrogram.types import Message
from utils.db import db
from utils.misc import modules_help, prefix
anti_pm_enabled = filters.create(
    lambda _, __, ___: db.get("core.antipm", "status", False)
)
in_contact_list = filters.create(lambda _, __, message: message.from_user.is_contact)
is_support = filters.create(lambda _, __, message: message.chat.is_support)
@Client.on_message(
    filters.private
    & ~filters.me
    & ~filters.bot
    & ~in_contact_list
    & ~is_support
    & anti_pm_enabled
)
async def anti_pm_handler(client: Client, message: Message):
    user_info = await client.resolve_peer(message.chat.id)
    if db.get("core.antipm", "spamrep", False):
        await client.send(functions.messages.ReportSpam(peer=user_info))
    if db.get("core.antipm", "block", False):
        await client.send(functions.contacts.Block(id=user_info))
    await client.send(
        functions.messages.DeleteHistory(peer=user_info, max_id=0, revoke=True)
    )
@Client.on_message(filters.command(["antipm", "anti_pm"], prefix) & filters.me)
async def anti_pm(_, message: Message):
    if len(message.command) == 1:
        if db.get("core.antipm", "status", False):
            await message.edit(
                "<b>Anti-PM status: enabled\n"
                f"Disable with: </b><code>{prefix}antipm disable</code>"
            )
        else:
            await message.edit(
                "<b>Anti-PM status: disabled\n"
                f"Enable with: </b><code>{prefix}antipm enable</code>"
            )
    elif message.command[1] in ["enable", "on", "1", "yes", "true"]:
        db.set("core.antipm", "status", True)
        await message.edit("<b>Anti-PM enabled!</b>")
    elif message.command[1] in ["disable", "off", "0", "no", "false"]:
        db.set("core.antipm", "status", False)
        await message.edit("<b>Anti-PM disabled!</b>")
    else:
        await message.edit(f"<b>Usage: {prefix}antipm [enable|disable]</b>")
@Client.on_message(filters.command(["antipm_report"], prefix) & filters.me)
async def antipm_report(_, message: Message):
    if len(message.command) == 1:
        if db.get("core.antipm", "spamrep", False):
            await message.edit(
                "<b>Spam-reporting enabled.\n"
                f"Disable with: </b><code>{prefix}antipm_report disable</code>"
            )
        else:
            await message.edit(
                "<b>Spam-reporting disabled.\n"
                f"Enable with: </b><code>{prefix}antipm_report enable</code>"
            )
    elif message.command[1] in ["enable", "on", "1", "yes", "true"]:
        db.set("core.antipm", "spamrep", True)
        await message.edit("<b>Spam-reporting enabled!</b>")
    elif message.command[1] in ["disable", "off", "0", "no", "false"]:
        db.set("core.antipm", "spamrep", False)
        await message.edit("<b>Spam-reporting disabled!</b>")
    else:
        await message.edit(f"<b>Usage: {prefix}antipm_report [enable|disable]</b>")
@Client.on_message(filters.command(["antipm_block"], prefix) & filters.me)
async def antipm_block(_, message: Message):
    if len(message.command) == 1:
        if db.get("core.antipm", "block", False):
            await message.edit(
                "<b>Blocking users enabled.\n"
                f"Disable with: </b><code>{prefix}antipm_block disable</code>"
            )
        else:
            await message.edit(
                "<b>Blocking users disabled.\n"
                f"Enable with: </b><code>{prefix}antipm_block enable</code>"
            )
    elif message.command[1] in ["enable", "on", "1", "yes", "true"]:
        db.set("core.antipm", "block", True)
        await message.edit("<b>Blocking users enabled!</b>")
    elif message.command[1] in ["disable", "off", "0", "no", "false"]:
        db.set("core.antipm", "block", False)
        await message.edit("<b>Blocking users disabled!</b>")
    else:
        await message.edit(f"<b>Usage: {prefix}antipm_block [enable|disable]</b>")
modules_help["antipm"] = {
    "antipm [enable|disable]*": "When enabled, deletes all messages from users who are not in the contact book",
    "antipm_report [enable|disable]*": "Enable spam reporting",
    "antipm_block [enable|disable]*": "Enable user blocking",
}
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, filters
from pyrogram.raw import functions
from pyrogram.types import Message
from utils.db import db
from utils.misc import modules_help, prefix
anti_pm_enabled = filters.create(
lambda _, __, ___: db.get("core.antipm", "status", False)
)
in_contact_list = filters.create(
lambda _, __, message: message.from_user.is_contact)
is_support = filters.create(lambda _, __, message: message.chat.is_support)
@Client.on_message(
filters.private
& ~filters.me
& ~filters.bot
& ~in_contact_list
& ~is_support
& anti_pm_enabled
)
async def anti_pm_handler(client: Client, message: Message):
user_info = await client.resolve_peer(message.chat.id)
if db.get("core.antipm", "spamrep", False):
await client.send(functions.messages.ReportSpam(peer=user_info))
if db.get("core.antipm", "block", False):
await client.send(functions.contacts.Block(id=user_info))
await client.send(
functions.messages.DeleteHistory(peer=user_info, max_id=0, revoke=True)
)
@Client.on_message(filters.command(["antipm", "anti_pm"], prefix) & filters.me)
async def anti_pm(_, message: Message):
if len(message.command) == 1:
if db.get("core.antipm", "status", False):
await message.edit(
"<b>Anti-PM status: enabled\n"
f"Disable with: </b><code>{prefix}antipm disable</code>"
)
else:
await message.edit(
"<b>Anti-PM status: disabled\n"
f"Enable with: </b><code>{prefix}antipm enable</code>"
)
elif message.command[1] in ["enable", "on", "1", "yes", "true"]:
db.set("core.antipm", "status", True)
await message.edit("<b>Anti-PM enabled!</b>")
elif message.command[1] in ["disable", "off", "0", "no", "false"]:
db.set("core.antipm", "status", False)
await message.edit("<b>Anti-PM disabled!</b>")
else:
await message.edit(f"<b>Usage: {prefix}antipm [enable|disable]</b>")
@Client.on_message(filters.command(["antipm_report"], prefix) & filters.me)
async def antipm_report(_, message: Message):
if len(message.command) == 1:
if db.get("core.antipm", "spamrep", False):
await message.edit(
"<b>Spam-reporting enabled.\n"
f"Disable with: </b><code>{prefix}antipm_report disable</code>"
)
else:
await message.edit(
"<b>Spam-reporting disabled.\n"
f"Enable with: </b><code>{prefix}antipm_report enable</code>"
)
elif message.command[1] in ["enable", "on", "1", "yes", "true"]:
db.set("core.antipm", "spamrep", True)
await message.edit("<b>Spam-reporting enabled!</b>")
elif message.command[1] in ["disable", "off", "0", "no", "false"]:
db.set("core.antipm", "spamrep", False)
await message.edit("<b>Spam-reporting disabled!</b>")
else:
await message.edit(f"<b>Usage: {prefix}antipm_report [enable|disable]</b>")
@Client.on_message(filters.command(["antipm_block"], prefix) & filters.me)
async def antipm_block(_, message: Message):
if len(message.command) == 1:
if db.get("core.antipm", "block", False):
await message.edit(
"<b>Blocking users enabled.\n"
f"Disable with: </b><code>{prefix}antipm_block disable</code>"
)
else:
await message.edit(
"<b>Blocking users disabled.\n"
f"Enable with: </b><code>{prefix}antipm_block enable</code>"
)
elif message.command[1] in ["enable", "on", "1", "yes", "true"]:
db.set("core.antipm", "block", True)
await message.edit("<b>Blocking users enabled!</b>")
elif message.command[1] in ["disable", "off", "0", "no", "false"]:
db.set("core.antipm", "block", False)
await message.edit("<b>Blocking users disabled!</b>")
else:
await message.edit(f"<b>Usage: {prefix}antipm_block [enable|disable]</b>")
modules_help["antipm"] = {
"antipm [enable|disable]*": "When enabled, deletes all messages from users who are not in the contact book",
"antipm_report [enable|disable]*": "Enable spam reporting",
"antipm_block [enable|disable]*": "Enable user blocking",
}

View File

@@ -1,72 +1,88 @@
from pyrogram import Client, filters
from pyrogram.errors import FloodWait
from pyrogram.raw import functions, types
from pyrogram.types import Message
from utils.misc import modules_help, prefix
@Client.on_message(filters.command(["clear_@"], prefix) & filters.me)
async def solo_mention_clear(client: Client, message: Message):
    await message.delete()
    peer = await client.resolve_peer(message.chat.id)
    request = functions.messages.ReadMentions(peer=peer)
    await client.send(request)
@Client.on_message(filters.command(["clear_all_@"], prefix) & filters.me)
async def global_mention_clear(client: Client, message: Message):
    request = functions.messages.GetAllChats(except_ids=[])
    try:
        result = await client.send(request)
    except FloodWait as e:
        await message.edit_text(
            f"<code>FloodWait received. Wait {e.x} seconds before trying again</code>"
        )
        return
    await message.delete()
    for chat in result.chats:
        if type(chat) is types.Chat:
            peer_id = -chat.id
        elif type(chat) is types.Channel:
            peer_id = int(f"-100{chat.id}")
        peer = await client.resolve_peer(peer_id)
        request = functions.messages.ReadMentions(peer=peer)
        await client.send(request)
@Client.on_message(filters.command(["clear_reacts"], prefix) & filters.me)
async def solo_reaction_clear(client: Client, message: Message):
    await message.delete()
    peer = await client.resolve_peer(message.chat.id)
    request = functions.messages.ReadReactions(peer=peer)
    await client.send(request)
@Client.on_message(filters.command(["clear_all_reacts"], prefix) & filters.me)
async def global_reaction_clear(client: Client, message: Message):
    request = functions.messages.GetAllChats(except_ids=[])
    try:
        result = await client.send(request)
    except FloodWait as e:
        await message.edit_text(
            f"<code>FloodWait received. Wait {e.x} seconds before trying again</code>"
        )
        return
    await message.delete()
    for chat in result.chats:
        if type(chat) is types.Chat:
            peer_id = -chat.id
        elif type(chat) is types.Channel:
            peer_id = int(f"-100{chat.id}")
        peer = await client.resolve_peer(peer_id)
        request = functions.messages.ReadReactions(peer=peer)
        await client.send(request)
modules_help["clear_notifs"] = {
    "clear_@": "clear all mentions in this chat",
    "clear_all_@": "clear all mentions in all chats",
    "clear_reacts": "clear all reactions in this chat",
    "clear_all_reacts": "clear all reactions in all chats (except private chats)",
}
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, filters
from pyrogram.errors import FloodWait
from pyrogram.raw import functions, types
from pyrogram.types import Message
from utils.misc import modules_help, prefix
@Client.on_message(filters.command(["clear_@"], prefix) & filters.me)
async def solo_mention_clear(client: Client, message: Message):
await message.delete()
peer = await client.resolve_peer(message.chat.id)
request = functions.messages.ReadMentions(peer=peer)
await client.send(request)
@Client.on_message(filters.command(["clear_all_@"], prefix) & filters.me)
async def global_mention_clear(client: Client, message: Message):
request = functions.messages.GetAllChats(except_ids=[])
try:
result = await client.send(request)
except FloodWait as e:
await message.edit_text(
f"<code>FloodWait received. Wait {e.x} seconds before trying again</code>"
)
return
await message.delete()
for chat in result.chats:
if type(chat) is types.Chat:
peer_id = -chat.id
elif type(chat) is types.Channel:
peer_id = int(f"-100{chat.id}")
peer = await client.resolve_peer(peer_id)
request = functions.messages.ReadMentions(peer=peer)
await client.send(request)
@Client.on_message(filters.command(["clear_reacts"], prefix) & filters.me)
async def solo_reaction_clear(client: Client, message: Message):
await message.delete()
peer = await client.resolve_peer(message.chat.id)
request = functions.messages.ReadReactions(peer=peer)
await client.send(request)
@Client.on_message(filters.command(["clear_all_reacts"], prefix) & filters.me)
async def global_reaction_clear(client: Client, message: Message):
request = functions.messages.GetAllChats(except_ids=[])
try:
result = await client.send(request)
except FloodWait as e:
await message.edit_text(
f"<code>FloodWait received. Wait {e.x} seconds before trying again</code>"
)
return
await message.delete()
for chat in result.chats:
if type(chat) is types.Chat:
peer_id = -chat.id
elif type(chat) is types.Channel:
peer_id = int(f"-100{chat.id}")
peer = await client.resolve_peer(peer_id)
request = functions.messages.ReadReactions(peer=peer)
await client.send(request)
modules_help["clear_notifs"] = {
"clear_@": "clear all mentions in this chat",
"clear_all_@": "clear all mentions in all chats",
"clear_reacts": "clear all reactions in this chat",
"clear_all_reacts": "clear all reactions in all chats (except private chats)",
}

View File

@@ -1,53 +1,53 @@
#  Moon-Userbot - telegram userbot
#  Copyright (C) 2020-present Moon Userbot Organization
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
# if your module has packages from PyPi
# from utils.scripts import import_library
# example_1 = import_library("example_1")
# example_2 = import_library("example_2")
# import_library() will automatically install required library
# if it isn't installed
@Client.on_message(filters.command("example_edit", prefix) & filters.me)
async def example_edit(client: Client, message: Message):
    await message.edit("<code>This is an example module</code>")
@Client.on_message(filters.command("example_send", prefix) & filters.me)
async def example_send(client: Client, message: Message):
    await client.send_message(message.chat.id, "<b>This is an example module</b>")
# This adds instructions for your module
modules_help["example"] = {
    "example_send": "example send",
    "example_edit": "example edit",
}
# modules_help["example"] = { "example_send [text]": "example send" }
#                  |            |              |        |
#                  |            |              |        └─ command description
#           module_name         command_name   └─ optional command arguments
#        (only snake_case)   (only snake_case too)
#  Moon-Userbot - telegram userbot
#  Copyright (C) 2020-present Moon Userbot Organization
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
# if your module has packages from PyPi
# from utils.scripts import import_library
# example_1 = import_library("example_1")
# example_2 = import_library("example_2")
# import_library() will automatically install required library
# if it isn't installed
@Client.on_message(filters.command("example_edit", prefix) & filters.me)
async def example_edit(client: Client, message: Message):
await message.edit("<code>This is an example module</code>")
@Client.on_message(filters.command("example_send", prefix) & filters.me)
async def example_send(client: Client, message: Message):
await client.send_message(message.chat.id, "<b>This is an example module</b>")
# This adds instructions for your module
modules_help["example"] = {
"example_send": "example send",
"example_edit": "example edit",
}
# modules_help["example"] = { "example_send [text]": "example send" }
# | | | |
# | | | └─ command description
# module_name command_name └─ optional command arguments
# (only snake_case) (only snake_case too)

View File

@@ -1,3 +1,19 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, filters, ContinuePropagation, errors
from pyrogram.types import (
Message,
@@ -7,282 +23,256 @@ from pyrogram.types import (
InputMediaAudio,
)
# noinspection PyUnresolvedReferences
# noinspection PyUnresolvedReferences
from utils.misc import modules_help, prefix
from utils.scripts import format_exc
# noinspection PyUnresolvedReferences
# noinspection PyUnresolvedReferences
from utils.db import db
def get_filters_chat(chat_id):
return db.get("core.filters", f" {
chat_id
}", {})
return db.get("core.filters", f"{chat_id}", {})
def set_filters_chat(chat_id, filters_):
return db.set("core.filters", f" {
chat_id
}", filters_)
return db.set("core.filters", f"{chat_id}", filters_)
async def contains_filter(_, __, m):
return m.text and m.text.lower() in get_filters_chat(m.chat.id).keys()
return m.text and m.text.lower() in get_filters_chat(m.chat.id).keys()
contains = filters.create(contains_filter)
# noinspection PyTypeChecker
# noinspection PyTypeChecker
@Client.on_message(contains)
async def filters_main_handler(client: Client, message: Message):
value = get_filters_chat(message.chat.id)[message.text.lower()]
try:
await client.get_messages(int(value["CHAT_ID"]), int(value["MESSAGE_ID"]))
except errors.RPCError:
raise ContinuePropagation
value = get_filters_chat(message.chat.id)[message.text.lower()]
try:
await client.get_messages(int(value["CHAT_ID"]), int(value["MESSAGE_ID"]))
except errors.RPCError:
raise ContinuePropagation
if value.get("MEDIA_GROUP"):
messages_grouped = await client.get_media_group(
int(value["CHAT_ID"]), int(value["MESSAGE_ID"])
)
media_grouped_list = []
for _ in messages_grouped:
if _.photo:
if _.caption:
media_grouped_list.append(
InputMediaPhoto(_.photo.file_id, _.caption.markdown)
)
else :
media_grouped_list.append(InputMediaPhoto(_.photo.file_id))
elif _.video:
if _.caption:
if _.video.thumbs:
media_grouped_list.append(
InputMediaVideo(
_.video.file_id,
_.video.thumbs[0].file_id,
_.caption.markdown,
)
)
else :
media_grouped_list.append(
InputMediaVideo(_.video.file_id, _.caption.markdown)
)
elif _.video.thumbs:
media_grouped_list.append(
InputMediaVideo(_.video.file_id, _.video.thumbs[0].file_id)
)
else :
media_grouped_list.append(InputMediaVideo(_.video.file_id))
elif _.audio:
if _.caption:
media_grouped_list.append(
InputMediaAudio(_.audio.file_id, _.caption.markdown)
)
else :
media_grouped_list.append(InputMediaAudio(_.audio.file_id))
elif _.document:
if _.caption:
if _.document.thumbs:
media_grouped_list.append(
InputMediaDocument(
_.document.file_id,
_.document.thumbs[0].file_id,
_.caption.markdown,
)
)
else :
media_grouped_list.append(
InputMediaDocument(_.document.file_id, _.caption.markdown)
)
elif _.document.thumbs:
media_grouped_list.append(
InputMediaDocument(
_.document.file_id, _.document.thumbs[0].file_id
)
)
else :
media_grouped_list.append(InputMediaDocument(_.document.file_id))
await client.send_media_group(
message.chat.id,
media_grouped_list,
reply_to_message_id = message.message_id,
)
else :
await client.copy_message(
message.chat.id,
int(value["CHAT_ID"]),
int(value["MESSAGE_ID"]),
reply_to_message_id = message.message_id,
)
raise ContinuePropagation
if value.get("MEDIA_GROUP"):
messages_grouped = await client.get_media_group(
int(value["CHAT_ID"]), int(value["MESSAGE_ID"])
)
media_grouped_list = []
for _ in messages_grouped:
if _.photo:
if _.caption:
media_grouped_list.append(
InputMediaPhoto(_.photo.file_id, _.caption.markdown)
)
else:
media_grouped_list.append(InputMediaPhoto(_.photo.file_id))
elif _.video:
if _.caption:
if _.video.thumbs:
media_grouped_list.append(
InputMediaVideo(
_.video.file_id,
_.video.thumbs[0].file_id,
_.caption.markdown,
)
)
else:
media_grouped_list.append(
InputMediaVideo(_.video.file_id,
_.caption.markdown)
)
elif _.video.thumbs:
media_grouped_list.append(
InputMediaVideo(_.video.file_id,
_.video.thumbs[0].file_id)
)
else:
media_grouped_list.append(InputMediaVideo(_.video.file_id))
elif _.audio:
if _.caption:
media_grouped_list.append(
InputMediaAudio(_.audio.file_id, _.caption.markdown)
)
else:
media_grouped_list.append(InputMediaAudio(_.audio.file_id))
elif _.document:
if _.caption:
if _.document.thumbs:
media_grouped_list.append(
InputMediaDocument(
_.document.file_id,
_.document.thumbs[0].file_id,
_.caption.markdown,
)
)
else:
media_grouped_list.append(
InputMediaDocument(
_.document.file_id, _.caption.markdown)
)
elif _.document.thumbs:
media_grouped_list.append(
InputMediaDocument(
_.document.file_id, _.document.thumbs[0].file_id
)
)
else:
media_grouped_list.append(
InputMediaDocument(_.document.file_id))
await client.send_media_group(
message.chat.id,
media_grouped_list,
reply_to_message_id=message.message_id,
)
else:
await client.copy_message(
message.chat.id,
int(value["CHAT_ID"]),
int(value["MESSAGE_ID"]),
reply_to_message_id=message.message_id,
)
raise ContinuePropagation
@Client.on_message(filters.command(["filter"], prefix) & filters.me)
async def filter_handler(client: Client, message: Message):
try:
if len(message.text.split()) < 2:
return await message.edit(
f"<b>Usage</b>: <code> {
prefix
}filter [name] (Reply required)</code>"
)
name = message.text.split(maxsplit = 1)[1].lower()
chat_filters = get_filters_chat(message.chat.id)
if name in chat_filters.keys():
return await message.edit(
f"<b>Filter</b> <code> {
name
}</code> already exists."
)
if not message.reply_to_message:
return await message.edit("<b>Reply to message</b> please.")
try:
if len(message.text.split()) < 2:
return await message.edit(
f"<b>Usage</b>: <code>{prefix}filter [name] (Reply required)</code>"
)
name = message.text.split(maxsplit=1)[1].lower()
chat_filters = get_filters_chat(message.chat.id)
if name in chat_filters.keys():
return await message.edit(
f"<b>Filter</b> <code>{name}</code> already exists."
)
if not message.reply_to_message:
return await message.edit("<b>Reply to message</b> please.")
try:
chat = await client.get_chat(db.get("core.notes", "chat_id", 0))
except (errors.RPCError, ValueError, KeyError):
# group is not accessible or isn't created
chat = await client.create_supergroup(
"Moon_Userbot_Notes_Filters", "Don't touch this group, please"
)
db.set("core.notes", "chat_id", chat.id)
try:
chat = await client.get_chat(db.get("core.notes", "chat_id", 0))
except (errors.RPCError, ValueError, KeyError):
# group is not accessible or isn't created
chat = await client.create_supergroup(
"Moon_Userbot_Notes_Filters", "Don't touch this group, please"
)
db.set("core.notes", "chat_id", chat.id)
chat_id = chat.id
chat_id = chat.id
if message.reply_to_message.media_group_id:
get_media_group = [
_.message_id
for _ in await client.get_media_group(
message.chat.id, message.reply_to_message.message_id
)
]
try:
message_id = await client.forward_messages(
chat_id, message.chat.id, get_media_group
)
except errors.ChatForwardsRestricted:
await message.edit(
"<b>Forwarding messages is restricted by chat admins</b>"
)
return
filter_ = {
"MESSAGE_ID": str(message_id[1].message_id),
"MEDIA_GROUP": True,
"CHAT_ID": str(chat_id),
} else :
try:
message_id = await message.reply_to_message.forward(chat_id)
except errors.ChatForwardsRestricted:
if message.reply_to_message.text:
# manual copy
message_id = await client.send_message(
chat_id, message.reply_to_message.text
)
else :
await message.edit(
"<b>Forwarding messages is restricted by chat admins</b>"
)
return
filter_ = {
"MEDIA_GROUP": False,
"MESSAGE_ID": str(message_id.message_id),
"CHAT_ID": str(chat_id),
}
if message.reply_to_message.media_group_id:
get_media_group = [
_.message_id
for _ in await client.get_media_group(
message.chat.id, message.reply_to_message.message_id
)
]
try:
message_id = await client.forward_messages(
chat_id, message.chat.id, get_media_group
)
except errors.ChatForwardsRestricted:
await message.edit(
"<b>Forwarding messages is restricted by chat admins</b>"
)
return
filter_ = {
"MESSAGE_ID": str(message_id[1].message_id),
"MEDIA_GROUP": True,
"CHAT_ID": str(chat_id),
}
else:
try:
message_id = await message.reply_to_message.forward(chat_id)
except errors.ChatForwardsRestricted:
if message.reply_to_message.text:
# manual copy
message_id = await client.send_message(
chat_id, message.reply_to_message.text
)
else:
await message.edit(
"<b>Forwarding messages is restricted by chat admins</b>"
)
return
filter_ = {
"MEDIA_GROUP": False,
"MESSAGE_ID": str(message_id.message_id),
"CHAT_ID": str(chat_id),
}
chat_filters.update({
name: filter_
})
chat_filters.update({name: filter_})
set_filters_chat(message.chat.id, chat_filters)
return await message.edit(f"<b>Filter</b> <code> {
name
}</code> has been added.")
except Exception as e:
return await message.edit(format_exc(e))
set_filters_chat(message.chat.id, chat_filters)
return await message.edit(f"<b>Filter</b> <code>{name}</code> has been added.")
except Exception as e:
return await message.edit(format_exc(e))
@Client.on_message(filters.command(["filters"], prefix) & filters.me)
async def filters_handler(client: Client, message: Message):
try:
text = ""
for index, a in enumerate(get_filters_chat(message.chat.id).items(), start = 1):
key, item = a
key = key.replace("<", "").replace(">", "")
text += f" {
index
}. <code> {
key
}</code>\n"
text = f"<b>Your filters in current chat</b>:\n\n" f" {
text
}"
text = text[:4096]
return await message.edit(text)
except Exception as e:
return await message.edit(format_exc(e))
try:
text = ""
for index, a in enumerate(get_filters_chat(message.chat.id).items(), start=1):
key, item = a
key = key.replace("<", "").replace(">", "")
text += f"{index}. <code>{key}</code>\n"
text = f"<b>Your filters in current chat</b>:\n\n" f"{text}"
text = text[:4096]
return await message.edit(text)
except Exception as e:
return await message.edit(format_exc(e))
@Client.on_message(
filters.command(["delfilter", "filterdel", "fdel"], prefix) & filters.me
)
async def filter_del_handler(client: Client, message: Message):
try:
if len(message.text.split()) < 2:
return await message.edit(f"<b>Usage</b>: <code> {
prefix
}fdel [name]</code>")
name = message.text.split(maxsplit = 1)[1].lower()
chat_filters = get_filters_chat(message.chat.id)
if name not in chat_filters.keys():
return await message.edit(
f"<b>Filter</b> <code> {
name
}</code> doesn't exists."
)
del chat_filters[name]
set_filters_chat(message.chat.id, chat_filters)
return await message.edit(
f"<b>Filter</b> <code> {
name
}</code> has been deleted."
)
except Exception as e:
return await message.edit(format_exc(e))
try:
if len(message.text.split()) < 2:
return await message.edit(f"<b>Usage</b>: <code>{prefix}fdel [name]</code>")
name = message.text.split(maxsplit=1)[1].lower()
chat_filters = get_filters_chat(message.chat.id)
if name not in chat_filters.keys():
return await message.edit(
f"<b>Filter</b> <code>{name}</code> doesn't exists."
)
del chat_filters[name]
set_filters_chat(message.chat.id, chat_filters)
return await message.edit(
f"<b>Filter</b> <code>{name}</code> has been deleted."
)
except Exception as e:
return await message.edit(format_exc(e))
@Client.on_message(filters.command(["fsearch"], prefix) & filters.me)
async def filter_search_handler(client: Client, message: Message):
try:
if len(message.text.split()) < 2:
return await message.edit(
f"<b>Usage</b>: <code> {
prefix
}fsearch [name]</code>"
)
name = message.text.split(maxsplit = 1)[1].lower()
chat_filters = get_filters_chat(message.chat.id)
if name not in chat_filters.keys():
return await message.edit(
f"<b>Filter</b> <code> {
name
}</code> doesn't exists."
)
return await message.edit(
f"<b>Trigger</b>:\n<code> {
name
}</code"
f">\n<b>Answer</b>:\n {
chat_filters[name]}"
)
except Exception as e:
return await message.edit(format_exc(e))
try:
if len(message.text.split()) < 2:
return await message.edit(
f"<b>Usage</b>: <code>{prefix}fsearch [name]</code>"
)
name = message.text.split(maxsplit=1)[1].lower()
chat_filters = get_filters_chat(message.chat.id)
if name not in chat_filters.keys():
return await message.edit(
f"<b>Filter</b> <code>{name}</code> doesn't exists."
)
return await message.edit(
f"<b>Trigger</b>:\n<code>{name}</code"
f">\n<b>Answer</b>:\n{chat_filters[name]}"
)
except Exception as e:
return await message.edit(format_exc(e))
modules_help["filters"] = {
"filter [name]": "Create filter (Reply required)",
"filters": "List of all triggers",
"fdel [name]": "Delete filter by name",
"fsearch [name]": "Info filter by name",
}
"filter [name]": "Create filter (Reply required)",
"filters": "List of all triggers",
"fdel [name]": "Delete filter by name",
"fsearch [name]": "Info filter by name",
}

View File

@@ -1,18 +1,18 @@
#  Moon-Userbot - telegram userbot
#  Copyright (C) 2020-present Moon Userbot Organization
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, filters
from pyrogram.types import Message
@@ -23,83 +23,58 @@ from utils.scripts import format_module_help
@Client.on_message(filters.command(["help", "h"], prefix) & filters.me)
async def help_cmd(_, message: Message):
if len(message.command) == 1:
msg_edited = False
text = (
"<b>Help for <a href=https://t.me/Moonub_chat>Moon-Userbot</a>\n"
f"For more help on how to use a command, type <code> {
prefix
}help [module]</code>\n\n"
"Available Modules:\n"
)
if len(message.command) == 1:
msg_edited = False
text = (
"<b>Help for <a href=https://t.me/Moonub_chat>Moon-Userbot</a>\n"
f"For more help on how to use a command, type <code>{prefix}help [module]</code>\n\n"
"Available Modules:\n"
)
for module_name, module_commands in modules_help.items():
text += " {}: {}\n".format(
module_name.title(),
" ".join(
[
f"<code> {
prefix + cmd_name.split()[0]}</code>"
for cmd_name in module_commands.keys()
]
),
)
if len(text) >= 2048:
text += "</b>"
if msg_edited:
await message.reply(text, disable_web_page_preview = True)
else :
await message.edit(text, disable_web_page_preview = True)
msg_edited = True
text = "<b>"
for module_name, module_commands in modules_help.items():
text += " {}: {}\n".format(
module_name.title(),
" ".join(
[
f"<code>{prefix + cmd_name.split()[0]}</code>"
for cmd_name in module_commands.keys()
]
),
)
if len(text) >= 2048:
text += "</b>"
if msg_edited:
await message.reply(text, disable_web_page_preview=True)
else:
await message.edit(text, disable_web_page_preview=True)
msg_edited = True
text = "<b>"
text += f"\nThe number of modules in the userbot:  {
len(modules_help) / 1
}</b>"
text += f"\nThe number of modules in the userbot: {len(modules_help) / 1}</b>"
if msg_edited:
await message.reply(text, disable_web_page_preview = True)
else :
await message.edit(text, disable_web_page_preview = True)
elif message.command[1].lower() in modules_help:
await message.edit(format_module_help(message.command[1].lower()))
else :
# TODO: refactor this cringe
command_name = message.command[1].lower()
for name, commands in modules_help.items():
for command in commands.keys():
if command.split()[0] == command_name:
cmd = command.split(maxsplit = 1)
cmd_desc = commands[command]
return await message.edit(
f"<b>Help for command <code> {
prefix
} {
command_name
}</code>\n"
f"Module:  {
name
} (<code> {
prefix
}help  {
name
}</code>)</b>\n\n"
f"<code> {
prefix
} {
cmd[0]}</code>"
f" {
' <code>' + cmd[1] + '</code>' if len(cmd) > 1 else ''
}"
f" — <i> {
cmd_desc
}</i>"
)
await message.edit(f"<b>Module  {
command_name
} not found</b>")
if msg_edited:
await message.reply(text, disable_web_page_preview=True)
else:
await message.edit(text, disable_web_page_preview=True)
elif message.command[1].lower() in modules_help:
await message.edit(format_module_help(message.command[1].lower()))
else:
# TODO: refactor this cringe
command_name = message.command[1].lower()
for name, commands in modules_help.items():
for command in commands.keys():
if command.split()[0] == command_name:
cmd = command.split(maxsplit=1)
cmd_desc = commands[command]
return await message.edit(
f"<b>Help for command <code>{prefix}{command_name}</code>\n"
f"Module: {name} (<code>{prefix}help {name}</code>)</b>\n\n"
f"<code>{prefix}{cmd[0]}</code>"
f"{' <code>' + cmd[1] + '</code>' if len(cmd) > 1 else ''}"
f" — <i>{cmd_desc}</i>"
)
await message.edit(f"<b>Module {command_name} not found</b>")
modules_help["help"] = {
"help [module/command name]": "Get common/module/command help"
}
"help [module/command name]": "Get common/module/command help"}

View File

@@ -1,225 +1,225 @@
#  Moon-Userbot - telegram userbot
#  Copyright (C) 2020-present Moon Userbot Organization
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
import hashlib
import os
import requests
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.scripts import restart
from utils.misc import modules_help, prefix
BASE_PATH = os.path.abspath(os.getcwd())
@Client.on_message(filters.command(["modhash", "mh"], prefix) & filters.me)
async def get_mod_hash(_, message: Message):
    if len(message.command) == 1:
        return
    url = message.command[1].lower()
    resp = requests.get(url)
    if not resp.ok:
        await message.edit(
            f"<b>Troubleshooting with downloading module <code>{url}</code></b>"
        )
        return
    await message.edit(
        f"<b>Module hash: <code>{hashlib.sha256(resp.content).hexdigest()}</code>\n"
        f"Link: <code>{url}</code>\nFile: <code>{url.split('/')[-1]}</code></b>"
    )
@Client.on_message(filters.command(["loadmod", "lm"], prefix) & filters.me)
async def loadmod(_, message: Message):
    if (
        not (
            message.reply_to_message
            and message.reply_to_message.document
            and message.reply_to_message.document.file_name.endswith(".py")
        )
        and len(message.command) == 1
    ):
        await message.edit("<b>Specify module to download</b>")
        return
    if len(message.command) > 1:
        url = message.command[1].lower()
        if url.startswith(
            "https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/"
        ):
            module_name = url.split("/")[-1].split(".")[0]
        elif "/" not in url and "." not in url:
            module_name = url.lower()
            url = f"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/{module_name}.py"
        else:
            modules_hashes = requests.get(
                "https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/modules_hashes.txt"
            ).text
            resp = requests.get(url)
            if not resp.ok:
                await message.edit(
                    f"<b>Troubleshooting with downloading module <code>{url}</code></b>"
                )
                return
            if hashlib.sha256(resp.content).hexdigest() not in modules_hashes:
                return await message.edit(
                    "<b>Only <a href=https://github.com/The-MoonTg-project/custom_modules/tree/main/modules_hashes.txt>"
                    "verified</a> modules or from the official "
                    "<a href=https://github.com/The-MoonTg-project/custom_modules>"
                    "custom_modules</a> repository are supported!</b>",
                    disable_web_page_preview=True,
                )
            module_name = url.split("/")[-1].split(".")[0]
        resp = requests.get(url)
        if not resp.ok:
            await message.edit(f"<b>Module <code>{module_name}</code> is not found</b>")
            return
        if not os.path.exists(f"{BASE_PATH}/modules/custom_modules"):
            os.mkdir(f"{BASE_PATH}/modules/custom_modules")
        with open(f"./modules/custom_modules/{module_name}.py", "wb") as f:
            f.write(resp.content)
    else:
        file_name = await message.reply_to_message.download()
        module_name = message.reply_to_message.document.file_name[:-3]
        with open(file_name, "rb") as f:
            content = f.read()
        modules_hashes = requests.get(
            "https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/modules_hashes.txt"
        ).text
        if hashlib.sha256(content).hexdigest() not in modules_hashes:
            os.remove(file_name)
            return await message.edit(
                "<b>Only <a href=https://github.com/The-MoonTg-project/custom_modules/tree/main/modules_hashes.txt>"
                "verified</a> modules or from the official "
                "<a href=https://github.com/The-MoonTg-project/custom_modules>"
                "custom_modules</a> repository are supported!</b>",
                disable_web_page_preview=True,
            )
        else:
            os.rename(file_name, f"./modules/custom_modules/{module_name}.py")
    await message.edit(f"<b>The module <code>{module_name}</code> is loaded!</b>")
    restart()
@Client.on_message(filters.command(["unloadmod", "ulm"], prefix) & filters.me)
async def unload_mods(_, message: Message):
    if len(message.command) <= 1:
        return
    module_name = message.command[1].lower()
    if module_name.startswith(
        "https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/"
    ):
        module_name = module_name.split("/")[-1].split(".")[0]
    if os.path.exists(f"{BASE_PATH}/modules/custom_modules/{module_name}.py"):
        os.remove(f"{BASE_PATH}/modules/custom_modules/{module_name}.py")
        await message.edit(f"<b>The module <code>{module_name}</code> removed!</b>")
        restart()
    elif os.path.exists(f"{BASE_PATH}/modules/{module_name}.py"):
        await message.edit(
            "<b>It is forbidden to remove built-in modules, it will disrupt the updater</b>"
        )
    else:
        await message.edit(f"<b>Module <code>{module_name}</code> is not found</b>")
@Client.on_message(filters.command(["loadallmods"], prefix) & filters.me)
async def load_all_mods(_, message: Message):
    await message.edit("<b>Fetching info...</b>")
    if not os.path.exists(f"{BASE_PATH}/modules/custom_modules"):
        os.mkdir(f"{BASE_PATH}/modules/custom_modules")
    modules_list = requests.get(
        "https://api.github.com/repos/The-MoonTg-project/custom_modules/contents/"
    ).json()
    new_modules = {}
    for module_info in modules_list:
        if not module_info["name"].endswith(".py"):
            continue
        if os.path.exists(f'{BASE_PATH}/modules/custom_modules/{module_info["name"]}'):
            continue
        new_modules[module_info["name"][:-3]] = module_info["download_url"]
    if not new_modules:
        return await message.edit("<b>All modules already loaded</b>")
    await message.edit(f'<b>Loading new modules: {" ".join(new_modules.keys())}</b>')
    for name, url in new_modules.items():
        with open(f"./modules/custom_modules/{name}.py", "wb") as f:
            f.write(requests.get(url).content)
    await message.edit(
        f'<b>Successfully loaded new modules: {" ".join(new_modules.keys())}</b>'
    )
    restart()
@Client.on_message(filters.command(["updateallmods"], prefix) & filters.me)
async def updateallmods(_, message: Message):
    await message.edit("<b>Updating modules...</b>")
    if not os.path.exists(f"{BASE_PATH}/modules/custom_modules"):
        os.mkdir(f"{BASE_PATH}/modules/custom_modules")
    modules_installed = list(os.walk("modules/custom_modules"))[0][2]
    if not modules_installed:
        return await message.edit("<b>You don't have any modules installed</b>")
    for module_name in modules_installed:
        if not module_name.endswith(".py"):
            continue
        resp = requests.get(
            f"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/{module_name}"
        )
        if not resp.ok:
            modules_installed.remove(module_name)
            continue
        with open(f"./modules/custom_modules/{module_name}", "wb") as f:
            f.write(resp.content)
    await message.edit(f"<b>Successfully updated {len(modules_installed)} modules</b>")
modules_help["loader"] = {
    "loadmod [module_name]*": "Download module.\n"
    "Only modules from the official custom_modules repository and proven "
    "modules whose hashes are in modules_hashes.txt are supported",
    "unloadmod [module_name]*": "Delete module",
    "modhash [link]*": "Get module hash by link",
    "loadallmods": "Load all custom modules (use it at your own risk)",
    "updateallmods": "Update all custom modules",
}
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import hashlib
import os
import requests
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.scripts import restart
from utils.misc import modules_help, prefix
BASE_PATH = os.path.abspath(os.getcwd())
@Client.on_message(filters.command(["modhash", "mh"], prefix) & filters.me)
async def get_mod_hash(_, message: Message):
if len(message.command) == 1:
return
url = message.command[1].lower()
resp = requests.get(url)
if not resp.ok:
await message.edit(
f"<b>Troubleshooting with downloading module <code>{url}</code></b>"
)
return
await message.edit(
f"<b>Module hash: <code>{hashlib.sha256(resp.content).hexdigest()}</code>\n"
f"Link: <code>{url}</code>\nFile: <code>{url.split('/')[-1]}</code></b>"
)
@Client.on_message(filters.command(["loadmod", "lm"], prefix) & filters.me)
async def loadmod(_, message: Message):
if (
not (
message.reply_to_message
and message.reply_to_message.document
and message.reply_to_message.document.file_name.endswith(".py")
)
and len(message.command) == 1
):
await message.edit("<b>Specify module to download</b>")
return
if len(message.command) > 1:
url = message.command[1].lower()
if url.startswith(
"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/"
):
module_name = url.split("/")[-1].split(".")[0]
elif "/" not in url and "." not in url:
module_name = url.lower()
url = f"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/{module_name}.py"
else:
modules_hashes = requests.get(
"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/modules_hashes.txt"
).text
resp = requests.get(url)
if not resp.ok:
await message.edit(
f"<b>Troubleshooting with downloading module <code>{url}</code></b>"
)
return
if hashlib.sha256(resp.content).hexdigest() not in modules_hashes:
return await message.edit(
"<b>Only <a href=https://github.com/The-MoonTg-project/custom_modules/tree/main/modules_hashes.txt>"
"verified</a> modules or from the official "
"<a href=https://github.com/The-MoonTg-project/custom_modules>"
"custom_modules</a> repository are supported!</b>",
disable_web_page_preview=True,
)
module_name = url.split("/")[-1].split(".")[0]
resp = requests.get(url)
if not resp.ok:
await message.edit(f"<b>Module <code>{module_name}</code> is not found</b>")
return
if not os.path.exists(f"{BASE_PATH}/modules/custom_modules"):
os.mkdir(f"{BASE_PATH}/modules/custom_modules")
with open(f"./modules/custom_modules/{module_name}.py", "wb") as f:
f.write(resp.content)
else:
file_name = await message.reply_to_message.download()
module_name = message.reply_to_message.document.file_name[:-3]
with open(file_name, "rb") as f:
content = f.read()
modules_hashes = requests.get(
"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/modules_hashes.txt"
).text
if hashlib.sha256(content).hexdigest() not in modules_hashes:
os.remove(file_name)
return await message.edit(
"<b>Only <a href=https://github.com/The-MoonTg-project/custom_modules/tree/main/modules_hashes.txt>"
"verified</a> modules or from the official "
"<a href=https://github.com/The-MoonTg-project/custom_modules>"
"custom_modules</a> repository are supported!</b>",
disable_web_page_preview=True,
)
else:
os.rename(file_name, f"./modules/custom_modules/{module_name}.py")
await message.edit(f"<b>The module <code>{module_name}</code> is loaded!</b>")
restart()
@Client.on_message(filters.command(["unloadmod", "ulm"], prefix) & filters.me)
async def unload_mods(_, message: Message):
if len(message.command) <= 1:
return
module_name = message.command[1].lower()
if module_name.startswith(
"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/"
):
module_name = module_name.split("/")[-1].split(".")[0]
if os.path.exists(f"{BASE_PATH}/modules/custom_modules/{module_name}.py"):
os.remove(f"{BASE_PATH}/modules/custom_modules/{module_name}.py")
await message.edit(f"<b>The module <code>{module_name}</code> removed!</b>")
restart()
elif os.path.exists(f"{BASE_PATH}/modules/{module_name}.py"):
await message.edit(
"<b>It is forbidden to remove built-in modules, it will disrupt the updater</b>"
)
else:
await message.edit(f"<b>Module <code>{module_name}</code> is not found</b>")
@Client.on_message(filters.command(["loadallmods"], prefix) & filters.me)
async def load_all_mods(_, message: Message):
await message.edit("<b>Fetching info...</b>")
if not os.path.exists(f"{BASE_PATH}/modules/custom_modules"):
os.mkdir(f"{BASE_PATH}/modules/custom_modules")
modules_list = requests.get(
"https://api.github.com/repos/The-MoonTg-project/custom_modules/contents/"
).json()
new_modules = {}
for module_info in modules_list:
if not module_info["name"].endswith(".py"):
continue
if os.path.exists(f'{BASE_PATH}/modules/custom_modules/{module_info["name"]}'):
continue
new_modules[module_info["name"][:-3]] = module_info["download_url"]
if not new_modules:
return await message.edit("<b>All modules already loaded</b>")
await message.edit(f'<b>Loading new modules: {" ".join(new_modules.keys())}</b>')
for name, url in new_modules.items():
with open(f"./modules/custom_modules/{name}.py", "wb") as f:
f.write(requests.get(url).content)
await message.edit(
f'<b>Successfully loaded new modules: {" ".join(new_modules.keys())}</b>'
)
restart()
@Client.on_message(filters.command(["updateallmods"], prefix) & filters.me)
async def updateallmods(_, message: Message):
await message.edit("<b>Updating modules...</b>")
if not os.path.exists(f"{BASE_PATH}/modules/custom_modules"):
os.mkdir(f"{BASE_PATH}/modules/custom_modules")
modules_installed = list(os.walk("modules/custom_modules"))[0][2]
if not modules_installed:
return await message.edit("<b>You don't have any modules installed</b>")
for module_name in modules_installed:
if not module_name.endswith(".py"):
continue
resp = requests.get(
f"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/{module_name}"
)
if not resp.ok:
modules_installed.remove(module_name)
continue
with open(f"./modules/custom_modules/{module_name}", "wb") as f:
f.write(resp.content)
await message.edit(f"<b>Successfully updated {len(modules_installed)} modules</b>")
modules_help["loader"] = {
"loadmod [module_name]*": "Download module.\n"
"Only modules from the official custom_modules repository and proven "
"modules whose hashes are in modules_hashes.txt are supported",
"unloadmod [module_name]*": "Delete module",
"modhash [link]*": "Get module hash by link",
"loadallmods": "Load all custom modules (use it at your own risk)",
"updateallmods": "Update all custom modules",
}

View File

@@ -29,7 +29,7 @@ if ! command -v termux-setup-storage; then
echo
echo "Enter API_ID and API_HASH"
echo "You can get it here -> https://my.telegram.org/apps"
echo "You can get it here -> https://my.telegram.org/"
echo "Leave empty to use defaults  (please note that default keys significantly increases your ban chances)"
read -r -p "API_ID > " api_id

View File

@@ -1,170 +1,170 @@
#  Moon-Userbot - telegram userbot
#  Copyright (C) 2020-present Moon Userbot Organization
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
import json
import threading
import dns.resolver
import pymongo
import sqlite3
from utils import config
dns.resolver.default_resolver = dns.resolver.Resolver(configure=False)
dns.resolver.default_resolver.nameservers = ["8.8.8.8"]
class Database:
    def get(self, module: str, variable: str, default=None):
        """Get value from database"""
        raise NotImplementedError
    def set(self, module: str, variable: str, value):
        """Set key in database"""
        raise NotImplementedError
    def remove(self, module: str, variable: str):
        """Remove key from database"""
        raise NotImplementedError
    def get_collection(self, module: str) -> dict:
        """Get database for selected module"""
        raise NotImplementedError
    def close(self):
        """Close the database"""
        raise NotImplementedError
class MongoDatabase(Database):
    def __init__(self, url, name):
        self._client = pymongo.MongoClient(url)
        self._database = self._client[name]
    def set(self, module: str, variable: str, value):
        self._database[module].replace_one(
            {"var": variable}, {"var": variable, "val": value}, upsert=True
        )
    def get(self, module: str, variable: str, expected_value=None):
        doc = self._database[module].find_one({"var": variable})
        return expected_value if doc is None else doc["val"]
    def get_collection(self, module: str):
        return {item["var"]: item["val"] for item in self._database[module].find()}
    def remove(self, module: str, variable: str):
        self._database[module].delete_one({"var": variable})
    def close(self):
        self._client.close()
class SqliteDatabase(Database):
    def __init__(self, file):
        self._conn = sqlite3.connect(file, check_same_thread=False)
        self._conn.row_factory = sqlite3.Row
        self._cursor = self._conn.cursor()
        self._lock = threading.Lock()
    @staticmethod
    def _parse_row(row: sqlite3.Row):
        if row["type"] == "bool":
            return row["val"] == "1"
        elif row["type"] == "int":
            return int(row["val"])
        elif row["type"] == "str":
            return row["val"]
        else:
            return json.loads(row["val"])
    def _execute(self, module: str, *args, **kwargs) -> sqlite3.Cursor:
        self._lock.acquire()
        try:
            return self._cursor.execute(*args, **kwargs)
        except sqlite3.OperationalError as e:
            if str(e).startswith("no such table"):
                sql = f"""
                CREATE TABLE IF NOT EXISTS '{module}' (
                var TEXT UNIQUE NOT NULL,
                val TEXT NOT NULL,
                type TEXT NOT NULL
                )
                """
                self._cursor.execute(sql)
                self._conn.commit()
                return self._cursor.execute(*args, **kwargs)
            raise e from None
        finally:
            self._lock.release()
    def get(self, module: str, variable: str, default=None):
        sql = f"SELECT * FROM '{module}' WHERE var=:var"
        cur = self._execute(module, sql, {"tabl": module, "var": variable})
        row = cur.fetchone()
        if row is None:
            return default
        else:
            return self._parse_row(row)
    def set(self, module: str, variable: str, value) -> bool:
        sql = f"""
        INSERT INTO '{module}' VALUES ( :var, :val, :type )
        ON CONFLICT (var) DO
        UPDATE SET val=:val, type=:type WHERE var=:var
        """
        if isinstance(value, bool):
            val = "1" if value else "0"
            typ = "bool"
        elif isinstance(value, str):
            val = value
            typ = "str"
        elif isinstance(value, int):
            val = str(value)
            typ = "int"
        else:
            val = json.dumps(value)
            typ = "json"
        self._execute(module, sql, {"var": variable, "val": val, "type": typ})
        self._conn.commit()
        return True
    def remove(self, module: str, variable: str):
        sql = f"DELETE FROM '{module}' WHERE var=:var"
        self._execute(module, sql, {"var": variable})
        self._conn.commit()
    def get_collection(self, module: str) -> dict:
        sql = f"SELECT * FROM '{module}'"
        cur = self._execute(module, sql)
        collection = {}
        for row in cur:
            collection[row["var"]] = self._parse_row(row)
        return collection
    def close(self):
        self._conn.commit()
        self._conn.close()
if config.db_type in ["mongo", "mongodb"]:
    db = MongoDatabase(config.db_url, config.db_name)
else:
    db = SqliteDatabase(config.db_name)
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import json
import threading
import dns.resolver
import pymongo
import sqlite3
from utils import config
dns.resolver.default_resolver = dns.resolver.Resolver(configure=False)
dns.resolver.default_resolver.nameservers = ["8.8.8.8"]
class Database:
def get(self, module: str, variable: str, default=None):
"""Get value from database"""
raise NotImplementedError
def set(self, module: str, variable: str, value):
"""Set key in database"""
raise NotImplementedError
def remove(self, module: str, variable: str):
"""Remove key from database"""
raise NotImplementedError
def get_collection(self, module: str) -> dict:
"""Get database for selected module"""
raise NotImplementedError
def close(self):
"""Close the database"""
raise NotImplementedError
class MongoDatabase(Database):
def __init__(self, url, name):
self._client = pymongo.MongoClient(url)
self._database = self._client[name]
def set(self, module: str, variable: str, value):
self._database[module].replace_one(
{"var": variable}, {"var": variable, "val": value}, upsert=True
)
def get(self, module: str, variable: str, expected_value=None):
doc = self._database[module].find_one({"var": variable})
return expected_value if doc is None else doc["val"]
def get_collection(self, module: str):
return {item["var"]: item["val"] for item in self._database[module].find()}
def remove(self, module: str, variable: str):
self._database[module].delete_one({"var": variable})
def close(self):
self._client.close()
class SqliteDatabase(Database):
def __init__(self, file):
self._conn = sqlite3.connect(file, check_same_thread=False)
self._conn.row_factory = sqlite3.Row
self._cursor = self._conn.cursor()
self._lock = threading.Lock()
@staticmethod
def _parse_row(row: sqlite3.Row):
if row["type"] == "bool":
return row["val"] == "1"
elif row["type"] == "int":
return int(row["val"])
elif row["type"] == "str":
return row["val"]
else:
return json.loads(row["val"])
def _execute(self, module: str, *args, **kwargs) -> sqlite3.Cursor:
self._lock.acquire()
try:
return self._cursor.execute(*args, **kwargs)
except sqlite3.OperationalError as e:
if str(e).startswith("no such table"):
sql = f"""
CREATE TABLE IF NOT EXISTS '{module}' (
var TEXT UNIQUE NOT NULL,
val TEXT NOT NULL,
type TEXT NOT NULL
)
"""
self._cursor.execute(sql)
self._conn.commit()
return self._cursor.execute(*args, **kwargs)
raise e from None
finally:
self._lock.release()
def get(self, module: str, variable: str, default=None):
sql = f"SELECT * FROM '{module}' WHERE var=:var"
cur = self._execute(module, sql, {"tabl": module, "var": variable})
row = cur.fetchone()
if row is None:
return default
else:
return self._parse_row(row)
def set(self, module: str, variable: str, value) -> bool:
sql = f"""
INSERT INTO '{module}' VALUES ( :var, :val, :type )
ON CONFLICT (var) DO
UPDATE SET val=:val, type=:type WHERE var=:var
"""
if isinstance(value, bool):
val = "1" if value else "0"
typ = "bool"
elif isinstance(value, str):
val = value
typ = "str"
elif isinstance(value, int):
val = str(value)
typ = "int"
else:
val = json.dumps(value)
typ = "json"
self._execute(module, sql, {"var": variable, "val": val, "type": typ})
self._conn.commit()
return True
def remove(self, module: str, variable: str):
sql = f"DELETE FROM '{module}' WHERE var=:var"
self._execute(module, sql, {"var": variable})
self._conn.commit()
def get_collection(self, module: str) -> dict:
sql = f"SELECT * FROM '{module}'"
cur = self._execute(module, sql)
collection = {}
for row in cur:
collection[row["var"]] = self._parse_row(row)
return collection
def close(self):
self._conn.commit()
self._conn.close()
if config.db_type in ["mongo", "mongodb"]:
db = MongoDatabase(config.db_url, config.db_name)
else:
db = SqliteDatabase(config.db_name)

View File

@@ -1,44 +1,45 @@
#  Moon-Userbot - telegram userbot
#  Copyright (C) 2020-present Moon Userbot Organization
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
from sys import version_info
from .db import db
from git import Repo
class ModulesHelpDict(dict):
    def append(self, obj: dict):
        # convert help from old to new type
        module_name = list(obj.keys())[0]
        cmds = obj[module_name]
        commands = {}
        for cmd in cmds:
            cmd_name = list(cmd.keys())[0]
            cmd_desc = cmd[cmd_name]
            commands[cmd_name] = cmd_desc
        self[module_name] = commands
modules_help = ModulesHelpDict()
requirements_list = []
python_version = f"{version_info[0]}.{version_info[1]}.{version_info[2]}"
prefix = db.get("core.main", "prefix", ".")
gitrepo = Repo(".")
commits_since_tag = list(gitrepo.iter_commits(f"{gitrepo.tags[-1].name}..HEAD"))
userbot_version = f"3.1.{len(commits_since_tag)}"
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from sys import version_info
from .db import db
from git import Repo
class ModulesHelpDict(dict):
def append(self, obj: dict):
# convert help from old to new type
module_name = list(obj.keys())[0]
cmds = obj[module_name]
commands = {}
for cmd in cmds:
cmd_name = list(cmd.keys())[0]
cmd_desc = cmd[cmd_name]
commands[cmd_name] = cmd_desc
self[module_name] = commands
modules_help = ModulesHelpDict()
requirements_list = []
python_version = f"{version_info[0]}.{version_info[1]}.{version_info[2]}"
prefix = db.get("core.main", "prefix", ".")
gitrepo = Repo(".")
commits_since_tag = list(gitrepo.iter_commits(
f"{gitrepo.tags[-1].name}..HEAD"))
userbot_version = f"3.1.{len(commits_since_tag)}"

View File

@@ -1,18 +1,18 @@
#  Moon-Userbot - telegram userbot
#  Copyright (C) 2020-present Moon Userbot Organization
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import asyncio
import os
import sys
@@ -28,173 +28,137 @@ from .misc import modules_help, prefix, requirements_list
def text(message: types.Message):
return message.text if message.text else message.caption
return message.text if message.text else message.caption
def restart():
os.execvp(sys.executable, [sys.executable, "main.py"])
os.execvp(sys.executable, [sys.executable, "main.py"])
def format_exc(e: Exception, hint: str = None):
traceback.print_exc()
if isinstance(e, errors.RPCError):
return (
f"<b>Telegram API error!</b>\n"
f"<code>[ {
e.CODE
}  {
e.ID or e.NAME
}] -  {
e.MESSAGE
}</code>"
)
else :
if hint:
hint_text = f"\n\n<b>Hint:  {
hint
}</b>"
else :
hint_text = ""
return (
f"<b>Error!</b>\n" f"<code> {
e.__class__.__name__
}:  {
e
}</code>" + hint_text
)
traceback.print_exc()
if isinstance(e, errors.RPCError):
return (
f"<b>Telegram API error!</b>\n"
f"<code>[{e.CODE} {e.ID or e.NAME}] - {e.MESSAGE}</code>"
)
else:
if hint:
hint_text = f"\n\n<b>Hint: {hint}</b>"
else:
hint_text = ""
return (
f"<b>Error!</b>\n" f"<code>{e.__class__.__name__}: {e}</code>" + hint_text
)
def with_reply(func):
async def wrapped(client: Client, message: types.Message):
if not message.reply_to_message:
await message.edit("<b>Reply to message is required</b>")
else :
return await func(client, message)
async def wrapped(client: Client, message: types.Message):
if not message.reply_to_message:
await message.edit("<b>Reply to message is required</b>")
else:
return await func(client, message)
return wrapped
return wrapped
async def interact_with(message: types.Message) -> types.Message:
"""
    Check history with bot and return bot's response
    Example:
    .. code-block:: python
        bot_msg = await interact_with(await bot.send_message("@BotFather", "/start"))
    :param message: already sent message to bot
    :return: bot's response
    """
"""
Check history with bot and return bot's response
Example:
.. code-block:: python
bot_msg = await interact_with(await bot.send_message("@BotFather", "/start"))
:param message: already sent message to bot
:return: bot's response
"""
await asyncio.sleep(1)
# noinspection PyProtectedMember
response = await message._client.get_history(message.chat.id, limit = 1)
seconds_waiting = 0
await asyncio.sleep(1)
# noinspection PyProtectedMember
response = await message._client.get_history(message.chat.id, limit=1)
seconds_waiting = 0
while response[0].from_user.is_self:
seconds_waiting += 1
if seconds_waiting >= 5:
raise RuntimeError("bot didn't answer in 5 seconds")
while response[0].from_user.is_self:
seconds_waiting += 1
if seconds_waiting >= 5:
raise RuntimeError("bot didn't answer in 5 seconds")
await asyncio.sleep(1)
# noinspection PyProtectedMember
response = await message._client.get_history(message.chat.id, limit = 1)
await asyncio.sleep(1)
# noinspection PyProtectedMember
response = await message._client.get_history(message.chat.id, limit=1)
interact_with_to_delete.append(message.message_id)
interact_with_to_delete.append(response[0].message_id)
interact_with_to_delete.append(message.message_id)
interact_with_to_delete.append(response[0].message_id)
return response[0]
return response[0]
interact_with_to_delete = []
def format_module_help(module_name: str):
commands = modules_help[module_name]
commands = modules_help[module_name]
help_text = f"<b>Help for | {
module_name
}|\n\nUsage:</b>\n"
help_text = f"<b>Help for |{module_name}|\n\nUsage:</b>\n"
for command, desc in commands.items():
cmd = command.split(maxsplit = 1)
args = " <code>" + cmd[1] + "</code>" if len(cmd) > 1 else ""
help_text += f"<code> {
prefix
} {
cmd[0]}</code> {
args
} — <i> {
desc
}</i>\n"
for command, desc in commands.items():
cmd = command.split(maxsplit=1)
args = " <code>" + cmd[1] + "</code>" if len(cmd) > 1 else ""
help_text += f"<code>{prefix}{cmd[0]}</code>{args} — <i>{desc}</i>\n"
return help_text
return help_text
def format_small_module_help(module_name: str):
commands = modules_help[module_name]
commands = modules_help[module_name]
help_text = f"<b>Help for | {
module_name
}|\n\nCommands list:\n"
for command, desc in commands.items():
cmd = command.split(maxsplit = 1)
args = " <code>" + cmd[1] + "</code>" if len(cmd) > 1 else ""
help_text += f"<code> {
prefix
} {
cmd[0]}</code> {
args
}\n"
help_text += f"\nGet full usage: <code> {
prefix
}help  {
module_name
}</code></b>"
help_text = f"<b>Help for |{module_name}|\n\nCommands list:\n"
for command, desc in commands.items():
cmd = command.split(maxsplit=1)
args = " <code>" + cmd[1] + "</code>" if len(cmd) > 1 else ""
help_text += f"<code>{prefix}{cmd[0]}</code>{args}\n"
help_text += f"\nGet full usage: <code>{prefix}help {module_name}</code></b>"
return help_text
return help_text
def import_library(library_name: str, package_name: str = None):
"""
    Loads a library, or installs it in ImportError case
    :param library_name: library name (import example...)
    :param package_name: package name in PyPi (pip install example)
    :return: loaded module
    """
if package_name is None:
package_name = library_name
requirements_list.append(package_name)
"""
Loads a library, or installs it in ImportError case
:param library_name: library name (import example...)
:param package_name: package name in PyPi (pip install example)
:return: loaded module
"""
if package_name is None:
package_name = library_name
requirements_list.append(package_name)
try:
return importlib.import_module(library_name)
except ImportError:
completed = subprocess.run(["python3", "-m", "pip", "install", package_name])
if completed.returncode != 0:
raise AssertionError(
f"Failed to install library  {
package_name
} (pip exited with code  {
completed.returncode
})"
)
return importlib.import_module(library_name)
try:
return importlib.import_module(library_name)
except ImportError:
completed = subprocess.run(
["python3", "-m", "pip", "install", package_name])
if completed.returncode != 0:
raise AssertionError(
f"Failed to install library {package_name} (pip exited with code {completed.returncode})"
)
return importlib.import_module(library_name)
def resize_image(input_img, output = None, img_type = "PNG"):
if output is None:
output = BytesIO()
output.name = f"sticker. {
img_type.lower()}"
def resize_image(input_img, output=None, img_type="PNG"):
if output is None:
output = BytesIO()
output.name = f"sticker.{img_type.lower()}"
with Image.open(input_img) as img:
# We used to use thumbnail(size) here, but it returns with a *max* dimension of 512,512
# rather than making one side exactly 512 so we have to calculate dimensions manually :(
if img.width == img.height:
size = (512, 512)
elif img.width < img.height:
size = (max(512 * img.width // img.height, 1), 512)
else :
size = (512, max(512 * img.height // img.width, 1))
with Image.open(input_img) as img:
# We used to use thumbnail(size) here, but it returns with a *max* dimension of 512,512
# rather than making one side exactly 512 so we have to calculate dimensions manually :(
if img.width == img.height:
size = (512, 512)
elif img.width < img.height:
size = (max(512 * img.width // img.height, 1), 512)
else:
size = (512, max(512 * img.height // img.width, 1))
img.resize(size).save(output, img_type)
img.resize(size).save(output, img_type)
return output
return output