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(
app = Client(
"my_account",
api_id = config.api_id,
api_hash = config.api_hash,
hide_password = True,
test_mode = config.test_server,
)
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(
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()
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
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
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 .
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 "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 .
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 .

267
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(
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",
)
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(
# 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],
)
[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.
# 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.
# 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 json
from html import escape as t
from time import perf_counter
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 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
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>")
@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"]
start = perf_counter()
try:
response = await client.send(GetAllChats(except_ids=[]))
chats = response["chats"]
        adminned_chats = 0
        owned_chats = 0
        owned_usernamed_chats = 0
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
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()
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>"
    )
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>")
@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"]
start = perf_counter()
try:
response = await client.send(GetAllChats(except_ids=[]))
chats = response["chats"]
        adminned_chats = []
        owned_chats = []
        owned_usernamed_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)
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 = "<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:</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"
            )
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
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",
}
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.
# 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.
# 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 datetime
from pyrogram import Client, filters, types
from pyrogram import Client, filters, types
from utils.misc import modules_help, prefix
from utils.db import db
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": "",
    },
# 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>"
)
is_afk = filters.create(lambda _, __, ___: afk_info["is_afk"])
@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(
    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("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)
@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"}
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.
# 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.
# 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.raw import functions
from pyrogram.types import Message
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
from utils.db import db
from utils.misc import modules_help, prefix
anti_pm_enabled = filters.create(
    lambda _, __, ___: db.get("core.antipm", "status", False)
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)
)
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
@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>"
)
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)
    )
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", "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_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>")
@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",
}
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
# 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.
from utils.misc import modules_help, prefix
# 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_@"], 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_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_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)
@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)",
}
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.
#  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.
#  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
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.misc import modules_help, prefix
# if your module has packages from PyPi
# 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")
# 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
# 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_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>")
@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",
}
# 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)
# 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(
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(
)
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(
)
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(
)
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(
)
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(
)
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(
)
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(
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
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 = [
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(
]
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_ = {
)
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(
}
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_ = {
)
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(
for module_name, module_commands in modules_help.items():
text += " {}: {}\n".format(
module_name.title(),
" ".join(
" ".join(
[
f"<code> {
prefix + cmd_name.split()[0]}</code>"
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>"
)
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.
# 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.
# 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 hashlib
import os
import hashlib
import os
import requests
from pyrogram import Client, filters
from pyrogram.types import Message
import requests
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.scripts import restart
from utils.misc import modules_help, prefix
from utils.scripts import restart
from utils.misc import modules_help, prefix
BASE_PATH = os.path.abspath(os.getcwd())
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
@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>"
    )
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
@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 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 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 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,
                )
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]
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
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")
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(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()
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
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")
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()
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
@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()
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 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>")
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>")
@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")
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()
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>")
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>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()
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>")
@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")
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]
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>")
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
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
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)
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>")
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",
}
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.
# 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.
# 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 json
import threading
import dns.resolver
import pymongo
import sqlite3
from utils import config
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"]
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
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 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 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 get_collection(self, module: str) -> dict:
"""Get database for selected module"""
raise NotImplementedError
    def close(self):
        """Close the database"""
        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]
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 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(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 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 remove(self, module: str, variable: str):
self._database[module].delete_one({"var": variable})
    def close(self):
        self._client.close()
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()
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)
@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:
    db = SqliteDatabase(config.db_name)
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.
# 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.
# 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 sys import version_info
from .db import db
from git import Repo
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
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 = []
modules_help = ModulesHelpDict()
requirements_list = []
python_version = f"{version_info[0]}.{version_info[1]}.{version_info[2]}"
python_version = f"{version_info[0]}.{version_info[1]}.{version_info[2]}"
prefix = db.get("core.main", "prefix", ".")
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)}"
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