From e2611b2c5a8d8daa08ffe9dcabfcb18464c9456d Mon Sep 17 00:00:00 2001 From: sTiKyt <35602029+sTiKyt@users.noreply.github.com> Date: Fri, 29 Nov 2024 02:57:08 +0200 Subject: [PATCH 01/13] Base of the cross-distro installer, some fixes (#102) * Ensure root execution Added a check to ensure the script runs with root privileges, and prompt for the root password if necessary. Package manager detection Automatic package manager detection and installation commands. This change simplifies the installation process by automating the detection of the package manager and installing necessary packages accordingly. Added support for multiple package managers such as apt, apk, yum, and pacman. Add repository cloning and environment setup in install.sh Refactored install.sh to improve virtual environment setup, forbid it from executing apt commands without verifying apt presence, added loops for database and installation options. Add repository cloning and environment setup in install.sh Refactored install.sh to improve virtual environment setup, forbid it from executing apt commands without verifying apt presence, added loops for database and installation options. * Update README format and streamline installation instructions Reformatted sections for better readability, removed unnecessary

, replaced weird symbols with spaces * spacing * enhnace PM_PERMIT comment * enhance git install instrunction * Enhance repo existence check in installation script Updated the condition to verify both the presence of the directory and essential files (.env.dist, main.py, modules) before proceeding in the existing repository path. This change ensures the script runs only if all required files are available, preventing errors during installation. * Add user prompt for virtual environment creation Introduce a prompt to let the user decide whether to create a virtual environment, providing guidance and the option to skip if needed. * Fixed a typo in options for db_type * Reorder script execution for better flow Moved the execution of `install.py` to ensure configuration prompts occur before running the script. * Update README.md --------- Co-authored-by: Abhi <85984486+AbhiTheModder@users.noreply.github.com> --- README.md | 50 ++++---- install.sh | 331 ++++++++++++++++++++++++++++++++++------------------- 2 files changed, 238 insertions(+), 143 deletions(-) mode change 100644 => 100755 install.sh diff --git a/README.md b/README.md index 2acd35a7..af84f038 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ [![License](https://img.shields.io/badge/License-GPL-pink)](https://github.com/The-MoonTg-project/Moon-Userbot/blob/main/LICENSE) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://makeapullrequest.com) -

+ ***A Simple, Fast, Customizable, Ai powered Userbot for Telegram made after Dragon-Userbot abandoned*** @@ -129,22 +129,10 @@ If you're using Docker Compose version 2.x, use the following commands to start > Make Sure you add appropriate env vars ## 🖥️ Local Host -## Linux, Windows [only wsl] - -### Update the packages - -```shell -sudo apt update && sudo apt upgrade -y -``` +## 🐧 Linux (WSL compatible) ### Install Git - -> [!TIP] -> Ignore if already installed - -```shell -sudo apt install git -``` +There are instructions for installing on several different Unix distributions on the Git website, at https://git-scm.com/download/linux ### Clone the repo @@ -152,15 +140,25 @@ sudo apt install git git clone https://github.com/The-MoonTg-project/Moon-Userbot.git ``` -### Setup +### Installation ```shell -cd Moon-Userbot/ && sudo bash install.sh +cd Moon-Userbot +chmod +x install.sh +./install.sh ``` +**Installer tested on:** +- Arch +- Debian +- Ubuntu +- WSL (APT based distros) + +Feel free to test on other distros and let us know! + #### 📱 Termux > [!TIP] -> use [GitHub](https://github.com/termux/termux-app/releases) version +> Use [GitHub](https://github.com/termux/termux-app/releases) version ------------------------------------------------------------------------------- > **Full Installation instruction [Given here](https://telegra.ph/Moon-Userbot-Installation---Termux-02-09)** @@ -198,15 +196,15 @@ Contributions of any type are welcome like `custom_modules` etc. Feel free to do ## Licence ```plaintext -                    GNU GENERAL PUBLIC LICENSE -                        Version 3, 29 June 2007 + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 -  Copyright (C) 2007 Free Software Foundation, Inc.  -  Everyone is permitted to copy and distribute verbatim copies -  of this license document, but changing it is not allowed. + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. -                             Preamble + Preamble -   The GNU General Public License is a free, copyleft license for - software and other kinds of works. + The GNU General Public License is a free, copyleft license for + software and other kinds of works. ``` diff --git a/install.sh b/install.sh old mode 100644 new mode 100755 index 31c2e58c..7bc0d783 --- a/install.sh +++ b/install.sh @@ -1,24 +1,58 @@ #!/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 -fi +PACKAGE_MANAGER="" +# Ensure the script is run with root privileges if [[ $UID != 0 ]]; then - echo Please run this script as root + echo "This script requires root privileges." + echo "Please enter the root password to continue." + exec sudo "$0" "$@" +else + echo "Running with root privileges" +fi + +# Detect available package manager +if command -v apt &>/dev/null; then + PACKAGE_MANAGER="apt" +elif command -v apk &>/dev/null; then + PACKAGE_MANAGER="apk" +elif command -v yum &>/dev/null; then + PACKAGE_MANAGER="yum" +elif command -v pacman &>/dev/null; then + PACKAGE_MANAGER="pacman" +else + echo "Unsupported package manager. Please use a compatible distribution or update the installer script." exit 1 fi -apt update -y -apt install python3 python3-pip git ffmpeg wget gnupg -y || exit 2 +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 +fi -su -c "python3 -m pip install -U pip" $SUDO_USER -su -c "python3 -m pip install -U wheel pillow" $SUDO_USER +# Install necessary packages based on detected package manager +case "$PACKAGE_MANAGER" in + apt) + apt update -y + apt install python3 python3-venv git wget -y || exit 2 + ;; + apk) + apk update + apk add python3 py3-virtualenv git wget || exit 2 # Packages here may be wrong, to verify + ;; + yum) + yum update -y + yum install python3 python3-venv git wget -y || exit 2 # Packages here may be wrong, to verify + ;; + pacman) + pacman -S --noconfirm python python-virtualenv git wget || exit 2 + ;; +esac -if [[ -d "Moon-Userbot" ]]; then - cd Moon-Userbot -elif [[ -f ".env.dist" ]] && [[ -f "main.py" ]] && [[ -d "modules" ]]; then - : +# Clone repository if not exists +if [[ -d "Moon-Userbot" && "$(basename "$PWD")" != "Moon-Userbot" ]]; then + cd Moon-Userbot || exit 2 +elif [[ "$(basename "$PWD")" == "Moon-Userbot" && -f ".env.dist" && -f "main.py" && -d "modules" ]]; then + echo "Already inside the Moon-Userbot repo, proceeding." else git clone https://github.com/The-MoonTg-project/Moon-Userbot || exit 2 cd Moon-Userbot || exit 2 @@ -29,32 +63,59 @@ if [[ -f ".env" ]] && [[ -f "my_account.session" ]]; then exit fi -su -c "python3 -m pip install -U -r requirements.txt" $SUDO_USER || exit 2 +# Prompt user if they want to proceed with creating a virtual environment +echo "It's recommended to use a virtual environment for Python projects." +echo "Note: If your drive resources are very limited, you might consider not creating a virtual environment, but it shouldn't be rejected otherwise unless you know what you're doing." +read -r -p "Would you like to create a virtual environment? (Y/n) > " create_venv + +if [[ "$create_venv" != "n" ]] && [[ "$create_venv" != "N" ]]; then + # Create a virtual environment inside the cloned repository and activate it + python3 -m venv venv + source venv/bin/activate + # Upgrade pip and install wheel and pillow + pip install -U pip wheel pillow +fi +# Install Python requirements +pip install -U -r requirements.txt || exit 2 +# Prompt for API_ID and API_HASH echo 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)" +echo "Leave empty to use defaults (please note that using default keys is a **very bad idea** and significantly increases your ban chances)" read -r -p "API_ID > " api_id +# Default API_ID and API_HASH if [[ $api_id = "" ]]; then - api_id="2040" - api_hash="b18441a1ff607e10a989891a5462e627" + echo "You have chosen to use the default API_ID and API_HASH, which is strongly discouraged." + echo "Please type 'I agree' to confirm that you understand the risks and still wish to proceed." + read -r -p "Confirmation > " confirmation + if [[ $confirmation = "I agree" ]]; then + api_id="2040" + api_hash="b18441a1ff607e10a989891a5462e627" + else + echo "Confirmation not provided. Exiting..." + exit 1 + fi else read -r -p "API_HASH > " api_hash fi - +# Prompt for PM PERMIT warn limit +# PM PERMIT warn limit is the number of messages a user can receive from others before giving them a warning, requires `antipm` plugin to be enabled echo echo "SET PM PERMIT warn limit" +# Now below is more clear version: +echo "Enter the number of messages others can send you before receiving a warning, and eventually a ban or leave empty for default (3)" read -r -p "PM_LIMIT warn limit > " pm_limit if [[ $pm_limit = "" ]]; then pm_limit="3" - echo "limit not provided by user set to default" + echo "Limit not provided by user; set to default" fi +# Prompt for musicbot usage echo -echo "Do you want to use musicbot? (y/n)" +echo "Do you want to use musicbot? (y/N)" read -r -p "MUSIC_BOT > " musicbot if [[ $musicbot = "y" ]]; then echo @@ -65,7 +126,7 @@ if [[ $musicbot = "y" ]]; then second_session="" else echo - echo "Please provide handler to be used by msuicbot" + echo "Please provide handler to be used by musicbot" read -r -p "MUSIC_HANDLER > " music_handler if [[ $music_handler = "" ]]; then echo "MUSIC_HANDLER not provided by user" @@ -74,13 +135,13 @@ if [[ $musicbot = "y" ]]; then fi fi -echo +# Prompt for various API keys echo "Enter APIFLASH_KEY for webshot plugin" echo "You can get it here -> https://apiflash.com/dashboard/access_keys" read -r -p "APIFLASH_KEY > " apiflash_key if [[ $apiflash_key = "" ]]; then - echo "NOTE: API Not set you'll get errors with webshot & ws module" + echo "NOTE: API Not set; you'll get errors with webshot & ws module" fi echo @@ -89,7 +150,7 @@ echo "You can get it here -> https://www.remove.bg/dashboard#api-key" read -r -p "RMBG_KEY > " rmbg_key if [[ $rmbg_key = "" ]]; then - echo "NOTE: API Not set you'll not be able to use remove background modules" + echo "NOTE: API Not set; you'll not be able to use remove background modules" fi echo @@ -98,7 +159,7 @@ echo "You can get it here -> https://www.virustotal.com/" read -r -p "VT_KEY > " vt_key if [[ $vt_key = "" ]]; then - echo "NOTE: API Not set you'll not be able to use VirusTotal module" + echo "NOTE: API Not set; you'll not be able to use VirusTotal module" fi echo @@ -107,7 +168,7 @@ echo "You can get it here -> https://makersuite.google.com/app/apikey" read -r -p "GEMINI_KEY > " gemini_key if [[ $gemini_key = "" ]]; then - echo "NOTE: API Not set you'll not be able to use Gemini AI modules" + echo "NOTE: API Not set; you'll not be able to use Gemini AI modules" fi echo @@ -116,7 +177,7 @@ echo "You can get it here -> https://dashboard.cohere.com/api-keys" read -r -p "COHERE_KEY > " cohere_key if [[ $cohere_key = "" ]]; then - echo "NOTE: API Not set you'll not be able to use Coral AI modules" + echo "NOTE: API Not set; you'll not be able to use Coral AI modules" fi echo @@ -125,47 +186,64 @@ echo "Learn How to Get One --> https://github.com/VisionCraft-org/VisionCraft?ta read -r -p "VCA_API_KEY > " vca_api_key if [[ $vca_api_key = "" ]]; then - echo "NOTE: API Not set you'll not be able to use aiutils module/pligins" + echo "NOTE: API Not set; you'll not be able to use aiutils module/plugins" 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 -case $db_type in - 1) - echo "Please enter db_url" - echo "You can get it here -> https://mongodb.com/atlas" - read -r -p "> " db_url - db_name=Moon_Userbot - db_type=mongodb - ;; - 2) - if systemctl status mongodb; then - wget -qO - https://www.mongodb.org/static/pgp/server-5.0.asc | apt-key add - - source /etc/os-release - echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu ${UBUNTU_CODENAME}/mongodb-org/5.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-5.0.list - apt update - apt install mongodb -y - systemctl daemon-reload - systemctl enable mongodb - fi - systemctl start mongodb - - db_url=mongodb://localhost:27017 - db_name=Moon_Userbot - db_type=mongodb - ;; - *) - db_name=db.sqlite3 - db_type=sqlite3 - ;; -esac - +while true; do + # Prompt for database type and database URL if MongoDB is selected + echo + echo "Choose database type:" + echo "[1] MongoDB db_url" + echo "[2] MongoDB localhost" + echo "[3] Sqlite (default)" + read -r -p "> " db_type + + case $db_type in + 1) + echo "Please enter db_url" + echo "You can get it here -> https://mongodb.com/atlas" + read -r -p "> " db_url + db_name=Moon_Userbot + db_type=mongodb + break + ;; + 2) + if ! command -v apt &>/dev/null; then + echo "This option requires apt package manager, which is not available on your system." + echo "Please choose a different database type." + continue + fi + + 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 + break + ;; + 3) + db_name=db.sqlite3 + db_type=sqlite3 + break + ;; + *) + echo "Invalid choice!" + ;; + esac +done + +# Generate .env file with collected variables cat > .env << EOL API_ID=${api_id} API_HASH=${api_hash} @@ -187,40 +265,50 @@ SECOND_SESSION=${second_session} MUSIC_HANDLER=${music_handler} EOL +# Adjust the ownership of the Moon-Userbot directory chown -R $SUDO_USER:$SUDO_USER . -echo -echo "Choose installation type:" -echo "[1] PM2" -echo "[2] Systemd service" -echo "[3] Custom (default)" -read -r -p "> " install_type - -su -c "python3 install.py ${install_type}" $SUDO_USER || exit 3 - -case $install_type in - 1) - if ! command -v pm2; then - curl -fsSL https://deb.nodesource.com/setup_17.x | bash - apt install nodejs -y - npm install pm2 -g - su -c "pm2 startup" $SUDO_USER - env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u $SUDO_USER --hp /home/$SUDO_USER - fi - su -c "pm2 start main.py --name Moon --interpreter python3" $SUDO_USER - su -c "pm2 save" $SUDO_USER - echo - echo "============================" - echo "Great! Moon-Userbot installed successfully and running now!" - echo "Installation type: PM2" - echo "Start with: \"pm2 start Moon\"" - echo "Stop with: \"pm2 stop Moon\"" - echo "Process name: Moon" - echo "============================" - ;; - 2) - cat > /etc/systemd/system/Moon.service << EOL +# Configure the bot based on selected installation type +while true; do + # Prompt for installation type and execute accordingly + echo + echo "Choose installation type:" + echo "[1] PM2" + echo "[2] Systemd service" + echo "[3] Custom (default)" + read -r -p "> " install_type + + case $install_type in + 1) + if ! command -v apt &>/dev/null; then + echo "This option requires apt package manager, which is not available on your system." + echo "Please choose a different installation type." + continue + fi + + if ! command -v pm2 &>/dev/null; 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 "============================" + break + ;; + 2) + cat > /etc/systemd/system/Moon.service << EOL [Unit] Description=Service for Moon Userbot [Service] @@ -233,26 +321,35 @@ 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 - + 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 "============================" + break + ;; + 3) + echo + echo "============================" + echo "Great! Moon-Userbot installed successfully!" + echo "Installation type: Custom" + echo "Start with: \"python3 main.py\"" + echo "============================" + break + ;; + *) + echo "Invalid choice! Please enter 1, 2, or 3." + ;; + esac +done + + su -c "python3 install.py ${install_type}" $SUDO_USER || exit 3 + +# Adjust the ownership of the Moon-Userbot directory again as a final step chown -R $SUDO_USER:$SUDO_USER . \ No newline at end of file From 5bac8a6b7c3a6dae6d10981e6cd1223d41d383cd Mon Sep 17 00:00:00 2001 From: Abhi <85984486+AbhiTheModder@users.noreply.github.com> Date: Fri, 29 Nov 2024 18:30:56 +0530 Subject: [PATCH 02/13] use printf --- install.sh | 366 ++++++++++++++++++++++++++--------------------------- start | 9 ++ 2 files changed, 192 insertions(+), 183 deletions(-) create mode 100755 start diff --git a/install.sh b/install.sh index 7bc0d783..5eaffd8e 100755 --- a/install.sh +++ b/install.sh @@ -1,13 +1,22 @@ -#!/bin/bash +#!/usr/bin/env bash + +# Define color codes +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +BLUE='\033[0;34m' +INPUT='\033[1;30m' +NC='\033[0m' # No Color + PACKAGE_MANAGER="" # Ensure the script is run with root privileges if [[ $UID != 0 ]]; then - echo "This script requires root privileges." - echo "Please enter the root password to continue." + printf "${YELLOW}This script requires root privileges.${NC}\n" + printf "Please enter the root password to continue.\n" exec sudo "$0" "$@" else - echo "Running with root privileges" + printf "${YELLOW}Running with root privileges${NC}\n" fi # Detect available package manager @@ -20,81 +29,89 @@ elif command -v yum &>/dev/null; then elif command -v pacman &>/dev/null; then PACKAGE_MANAGER="pacman" else - echo "Unsupported package manager. Please use a compatible distribution or update the installer script." + printf "${RED}Unsupported package manager. Please use a compatible distribution or update the installer script.${NC}\n" exit 1 fi 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" + printf "${RED}For termux, please use https://raw.githubusercontent.com/The-MoonTg-project/Moon-Userbot/main/termux-install.sh${NC}\n" exit 1 fi # Install necessary packages based on detected package manager case "$PACKAGE_MANAGER" in - apt) - apt update -y - apt install python3 python3-venv git wget -y || exit 2 - ;; - apk) - apk update - apk add python3 py3-virtualenv git wget || exit 2 # Packages here may be wrong, to verify - ;; - yum) - yum update -y - yum install python3 python3-venv git wget -y || exit 2 # Packages here may be wrong, to verify - ;; - pacman) - pacman -S --noconfirm python python-virtualenv git wget || exit 2 - ;; +apt) + apt update -y + apt install python3 python3-venv git wget -y || exit 2 + ;; +apk) + apk update + apk add python3 py3-virtualenv git wget || exit 2 # Packages here may be wrong, to verify + ;; +yum) + yum update -y + yum install python3 python3-venv git wget -y || exit 2 # Packages here may be wrong, to verify + ;; +pacman) + pacman -S --noconfirm python python-virtualenv git wget || exit 2 + ;; esac # Clone repository if not exists if [[ -d "Moon-Userbot" && "$(basename "$PWD")" != "Moon-Userbot" ]]; then cd Moon-Userbot || exit 2 elif [[ "$(basename "$PWD")" == "Moon-Userbot" && -f ".env.dist" && -f "main.py" && -d "modules" ]]; then - echo "Already inside the Moon-Userbot repo, proceeding." + printf "${BLUE}Already inside the Moon-Userbot repo, proceeding...${NC}\n" else git clone https://github.com/The-MoonTg-project/Moon-Userbot || exit 2 cd Moon-Userbot || exit 2 fi if [[ -f ".env" ]] && [[ -f "my_account.session" ]]; then - echo "It seems that Moon-Userbot is already installed. Exiting..." + printf "${GREEN}It seems that Moon-Userbot is already installed. Exiting...${NC}\n" exit fi # Prompt user if they want to proceed with creating a virtual environment -echo "It's recommended to use a virtual environment for Python projects." -echo "Note: If your drive resources are very limited, you might consider not creating a virtual environment, but it shouldn't be rejected otherwise unless you know what you're doing." -read -r -p "Would you like to create a virtual environment? (Y/n) > " create_venv +printf "${YELLOW}It's recommended to use a virtual environment for Python projects.${NC}\n" +printf "Note: If your drive resources are very limited, you might consider not creating a virtual environment, but it shouldn't be rejected otherwise unless you know what you're doing.\n" +printf "If you're unsure, it's better to create a virtual environment.\n" +printf "${INPUT}Would you like to create a virtual environment? (Y/n)${NC} > " +read -r create_venv if [[ "$create_venv" != "n" ]] && [[ "$create_venv" != "N" ]]; then - # Create a virtual environment inside the cloned repository and activate it - python3 -m venv venv - source venv/bin/activate + # Create a virtual environment inside the cloned repository and activate it + python3 -m venv venv + . venv/bin/activate + + # Upgrade pip and install wheel and pillow + pip install -U pip wheel pillow +fi - # Upgrade pip and install wheel and pillow - pip install -U pip wheel pillow +if [ -d ".venv" ]; then + . .venv/bin/activate +elif [ -d "venv" ]; then + . venv/bin/activate fi + # Install Python requirements pip install -U -r requirements.txt || exit 2 # Prompt for API_ID and API_HASH -echo -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 using default keys is a **very bad idea** and significantly increases your ban chances)" +printf "Enter API_ID and API_HASH\n" +printf "You can get it here -> https://my.telegram.org/\n" +printf "Leave empty to use defaults (please note that using default keys is a ${RED}very bad idea${NC} and significantly increases your ban chances)\n" read -r -p "API_ID > " api_id # Default API_ID and API_HASH if [[ $api_id = "" ]]; then - echo "You have chosen to use the default API_ID and API_HASH, which is strongly discouraged." - echo "Please type 'I agree' to confirm that you understand the risks and still wish to proceed." + printf "${RED}You have chosen to use the default API_ID and API_HASH, which is strongly discouraged.${NC}\n" + printf "${YELLOW}Please type${NC} '${BLUE}I agree${NC}'${YELLOW} to confirm that you understand the risks and still wish to proceed.${NC}\n" read -r -p "Confirmation > " confirmation if [[ $confirmation = "I agree" ]]; then api_id="2040" api_hash="b18441a1ff607e10a989891a5462e627" else - echo "Confirmation not provided. Exiting..." + printf "${RED}Confirmation not provided. Exiting...${NC}\n" exit 1 fi else @@ -102,149 +119,137 @@ else fi # Prompt for PM PERMIT warn limit # PM PERMIT warn limit is the number of messages a user can receive from others before giving them a warning, requires `antipm` plugin to be enabled -echo -echo "SET PM PERMIT warn limit" +printf "SET PM PERMIT warn limit\n" # Now below is more clear version: -echo "Enter the number of messages others can send you before receiving a warning, and eventually a ban or leave empty for default (3)" +printf "The number of messages others can send you before receiving a warning, and eventually a ban or leave empty for default (3), requires $(antipm) plugin to be enabled\n" read -r -p "PM_LIMIT warn limit > " pm_limit if [[ $pm_limit = "" ]]; then pm_limit="3" - echo "Limit not provided by user; set to default" + printf "Limit not provided by user; set to default\n" fi # Prompt for musicbot usage -echo -echo "Do you want to use musicbot? (y/N)" -read -r -p "MUSIC_BOT > " musicbot +printf "Do you want to use musicbot? (y/N)" +read -r musicbot if [[ $musicbot = "y" ]]; then - echo - echo "Enter SECOND_SESSION_STRING to be used by musicbot" + printf "Enter SECOND_SESSION_STRING to be used by musicbot\n" read -r -p "SECOND_SESSION > " second_session if [[ $second_session = "" ]]; then - echo "SECOND_SESSION not provided by user" + printf "SECOND_SESSION not provided by user\n" second_session="" else - echo - echo "Please provide handler to be used by musicbot" + printf "Please provide handler to be used by musicbotn\n" read -r -p "MUSIC_HANDLER > " music_handler if [[ $music_handler = "" ]]; then - echo "MUSIC_HANDLER not provided by user" + printf "MUSIC_HANDLER not provided by user\n" music_handler="" fi fi fi # Prompt for various API keys -echo "Enter APIFLASH_KEY for webshot plugin" -echo "You can get it here -> https://apiflash.com/dashboard/access_keys" +printf "Enter APIFLASH_KEY for webshot plugin\n" +printf "You can get it here -> https://apiflash.com/dashboard/access_keys\n" read -r -p "APIFLASH_KEY > " apiflash_key if [[ $apiflash_key = "" ]]; then - echo "NOTE: API Not set; you'll get errors with webshot & ws module" + printf "NOTE: API Not set; you'll get errors with webshot & ws module\n" fi -echo -echo "Enter RMBG_KEY for remove background module" -echo "You can get it here -> https://www.remove.bg/dashboard#api-key" +printf "Enter RMBG_KEY for remove background module\n" +printf "You can get it here -> https://www.remove.bg/dashboard#api-key\n" read -r -p "RMBG_KEY > " rmbg_key if [[ $rmbg_key = "" ]]; then - echo "NOTE: API Not set; you'll not be able to use remove background modules" + printf "NOTE: API Not set; you'll not be able to use remove background modules\n" fi -echo -echo "Enter VT_KEY for VirusTotal" -echo "You can get it here -> https://www.virustotal.com/" +printf "Enter VT_KEY for VirusTotal\n" +printf "You can get it here -> https://www.virustotal.com/\n" read -r -p "VT_KEY > " vt_key if [[ $vt_key = "" ]]; then - echo "NOTE: API Not set; you'll not be able to use VirusTotal module" + printf "NOTE: API Not set; you'll not be able to use VirusTotal module\n" fi -echo -echo "Enter GEMINI_KEY if you want to use AI" -echo "You can get it here -> https://makersuite.google.com/app/apikey" +printf "Enter GEMINI_KEY if you want to use AI\n" +printf "You can get it here -> https://makersuite.google.com/app/apikey\n" read -r -p "GEMINI_KEY > " gemini_key if [[ $gemini_key = "" ]]; then - echo "NOTE: API Not set; you'll not be able to use Gemini AI modules" + printf "NOTE: API Not set; you'll not be able to use Gemini AI modules\n" fi -echo -echo "Enter COHERE_KEY if you want to use AI" -echo "You can get it here -> https://dashboard.cohere.com/api-keys" +printf "Enter COHERE_KEY if you want to use AI" +printf "You can get it here -> https://dashboard.cohere.com/api-keys\n" read -r -p "COHERE_KEY > " cohere_key if [[ $cohere_key = "" ]]; then - echo "NOTE: API Not set; you'll not be able to use Coral AI modules" + printf "NOTE: API Not set; you'll not be able to use Coral AI modules\n" fi -echo -echo "Enter VCA_API_KEY for aiutils" -echo "Learn How to Get One --> https://github.com/VisionCraft-org/VisionCraft?tab=readme-ov-file#obtaining-an-api-key" +printf "Enter VCA_API_KEY for aiutils\n" +printf "Learn How to Get One --> https://github.com/VisionCraft-org/VisionCraft?tab=readme-ov-file#obtaining-an-api-key\n" read -r -p "VCA_API_KEY > " vca_api_key if [[ $vca_api_key = "" ]]; then - echo "NOTE: API Not set; you'll not be able to use aiutils module/plugins" + printf "NOTE: API Not set; you'll not be able to use aiutils module/plugins\n" fi - -echo while true; do # Prompt for database type and database URL if MongoDB is selected - echo - echo "Choose database type:" - echo "[1] MongoDB db_url" - echo "[2] MongoDB localhost" - echo "[3] Sqlite (default)" + printf "${YELLOW}Choose database type:${NC}\n" + printf "[1] MongoDB db_url\n" + printf "[2] MongoDB localhost\n" + printf "[3] Sqlite (default)\n" read -r -p "> " db_type case $db_type in - 1) - echo "Please enter db_url" - echo "You can get it here -> https://mongodb.com/atlas" - read -r -p "> " db_url - db_name=Moon_Userbot - db_type=mongodb - break - ;; - 2) - if ! command -v apt &>/dev/null; then - echo "This option requires apt package manager, which is not available on your system." - echo "Please choose a different database type." - continue - fi - - 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 - break - ;; - 3) - db_name=db.sqlite3 - db_type=sqlite3 - break - ;; - *) - echo "Invalid choice!" - ;; + 1) + printf "Please enter db_url\n" + printf "You can get it here -> https://mongodb.com/atlas\n" + read -r -p "> " db_url + db_name=Moon_Userbot + db_type=mongodb + break + ;; + 2) + if ! command -v apt &>/dev/null; then + printf "This option requires apt package manager, which is not available on your system.\n" + printf "Please choose a different database type.\n" + continue + fi + + if systemctl status mongodb; then + wget -qO - https://www.mongodb.org/static/pgp/server-5.0.asc | apt-key add - + source /etc/os-release + printf "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu ${UBUNTU_CODENAME}/mongodb-org/5.0 multiverse\n" | 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 + break + ;; + 3) + db_name=db.sqlite3 + db_type=sqlite3 + break + ;; + *) + printf "${RED}Invalid choice!${NC}\n" + ;; esac done # Generate .env file with collected variables -cat > .env << EOL +cat >.env < " install_type case $install_type in - 1) - if ! command -v apt &>/dev/null; then - echo "This option requires apt package manager, which is not available on your system." - echo "Please choose a different installation type." - continue - fi - - if ! command -v pm2 &>/dev/null; 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 "============================" - break - ;; - 2) - cat > /etc/systemd/system/Moon.service << EOL + 1) + if ! command -v apt &>/dev/null; then + printf "This option requires apt package manager, which is not available on your system.\n" + printf "Please choose a different installation type.\n" + continue + fi + + if ! command -v pm2 &>/dev/null; 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 + + printf "${GREEN}============================\\n" + printf "Great! Moon-Userbot installed successfully and running now!\n" + printf "Installation type: PM2\n" + printf "Start with: \"pm2 start Moon\"\n" + printf "Stop with: \"pm2 stop Moon\"\n" + printf "Process name: Moon\n" + printf "============================${NC}\n" + break + ;; + 2) + cat >/etc/systemd/system/Moon.service < Date: Fri, 29 Nov 2024 19:03:15 +0530 Subject: [PATCH 03/13] move safone out of core --- modules/safone.py | 517 ---------------------------------------------- utils/scripts.py | 19 -- 2 files changed, 536 deletions(-) delete mode 100644 modules/safone.py diff --git a/modules/safone.py b/modules/safone.py deleted file mode 100644 index fe9c188e..00000000 --- a/modules/safone.py +++ /dev/null @@ -1,517 +0,0 @@ -# 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 . - -import os -import requests -import aiofiles -import base64 - -from pyrogram import Client, enums, filters -from pyrogram.types import Message, InputMediaPhoto -from pyrogram.errors import MediaCaptionTooLong, MessageTooLong - -from utils.misc import prefix, modules_help -from utils.scripts import format_exc, make_carbon - -url = "https://api.safone.co" - -headers = { - "Accept-Language": "en-US,en;q=0.9", - "Connection": "keep-alive", - "DNT": "1", - "Referer": "https://api.safone.dev/docs", - "Sec-Fetch-Dest": "empty", - "Sec-Fetch-Mode": "cors", - "Sec-Fetch-Site": "same-origin", - "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36", - "accept": "application/json", - "sec-ch-ua": '"Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"', - "sec-ch-ua-mobile": "?0", - "sec-ch-ua-platform": '"Linux"', -} - - -async def telegraph(title, user_name, content): - formatted_content = "
".join(content.split("\n")) - formatted_content = "

" + formatted_content + "

" - - data = {"title": title, "content": formatted_content, "author_name": user_name} - - response = requests.post( - url=f"{url}/telegraph/text", headers=headers, json=data, timeout=5 - ) - - result = response.json() - - return result["url"] - - -async def voice_characters(): - response = requests.get(url=f"{url}/speech/characters", headers=headers, timeout=5) - - result = response.json() - - return ", ".join(result["characters"]) - - -async def make_rayso(code: str, title: str, theme: str): - data = { - "code": code, - "title": title, - "theme": theme, - "padding": 64, - "language": "auto", - "darkMode": False, - } - response = requests.post(f"{url}/rayso", data=data, headers=headers) - if response.status_code != 200: - return None - result = response.json() - try: - if result["error"] is not None: - return None - except KeyError: - pass - image_data = result["image"] - file_name = "rayso.png" - with open(file_name, "wb") as f: - f.write(base64.b64decode(image_data)) - return file_name - - -@Client.on_message(filters.command("asq", prefix) & filters.me) -async def asq(_, message: Message): - if len(message.command) > 1: - query = message.text.split(maxsplit=1)[1] - else: - await message.edit_text("Query not provided!") - return - await message.edit_text("Processing...") - response = requests.get(url=f"{url}/asq?query={query}", headers=headers, timeout=5) - if response.status_code != 200: - await message.edit_text("Something went wrong!") - return - - result = response.json() - - ans = result["answer"] - await message.edit_text( - f"Q. {query}\n A. {ans}", parse_mode=enums.ParseMode.MARKDOWN - ) - - -@Client.on_message(filters.command("sgemini", prefix) & filters.me) -async def sgemini(_, message: Message): - if len(message.command) > 1: - prompt = message.text.split(maxsplit=1)[1] - else: - await message.edit_text("prompt not provided!") - return - await message.edit_text("Processing...") - response = requests.get(url=f"{url}/bard?query={prompt}", headers=headers) - if response.status_code != 200: - await message.edit_text("Something went wrong!") - return - - result = response.json() - - ans = result["message"] - await message.edit_text( - f"Prompt: {prompt}\n Ans: {ans}", parse_mode=enums.ParseMode.MARKDOWN - ) - - -@Client.on_message(filters.command("app", prefix) & filters.me) -async def app(client: Client, message: Message): - try: - chat_id = message.chat.id - await message.edit_text("Processing...") - if len(message.command) > 1: - query = message.text.split(maxsplit=1)[1] - else: - message.edit_text( - "What should i search? You didn't provided me with any value to search" - ) - - response = requests.get( - url=f"{url}/apps?query={query}&limit=1", headers=headers, timeout=5 - ) - if response.status_code != 200: - await message.edit_text("Something went wrong") - return - - result = response.json() - - try: - coverImage_url = result["results"][0]["icon"] - coverImage = requests.get(url=coverImage_url).content - async with aiofiles.open("coverImage.jpg", mode="wb") as f: - await f.write(coverImage) - - except Exception: - coverImage = None - - description = result["results"][0]["description"] - developer = result["results"][0]["developer"] - IsFree = result["results"][0]["free"] - genre = result["results"][0]["genre"] - package_name = result["results"][0]["id"] - title = result["results"][0]["title"] - price = result["results"][0]["price"] - link = result["results"][0]["link"] - rating = result["results"][0]["rating"] - - await message.delete() - await client.send_media_group( - chat_id, - [ - InputMediaPhoto( - "coverImage.jpg", - caption=f"Title: {title}\nRating: {rating}\nIsFree: {IsFree}\nPrice: {price}\nPackage Name: {package_name}\nGenres: {genre}\nDeveloper: {developer}\nDescription: {description}\nLink: {link}", - ) - ], - ) - - except MediaCaptionTooLong: - description = description[:850] - await message.delete() - await client.send_media_group( - chat_id, - [ - InputMediaPhoto( - "coverImage.jpg", - caption=f"Title: {title}\nRating: {rating}\nIsFree: {IsFree}\nPrice: {price}\nPackage Name: {package_name}\nGenres: {genre}\nDeveloper: {developer}\nDescription: {description}\nLink: {link}", - ) - ], - ) - except Exception as e: - await message.edit_text(format_exc(e)) - finally: - if os.path.exists("coverImage.jpg"): - os.remove("coverImage.jpg") - - -@Client.on_message(filters.command("tsearch", prefix) & filters.me) -async def tsearch(client: Client, message: Message): - try: - chat_id = message.chat.id - limit = 10 - await message.edit_text("Processing...") - if len(message.command) > 1: - query = message.text.split(maxsplit=1)[1] - else: - message.edit_text( - "What should i search? You didn't provided me with any value to search" - ) - - response = requests.get( - url=f"{url}/torrent?query={query}&limit={limit}", headers=headers - ) - if response.status_code != 200: - await message.edit_text("Something went wrong") - return - - result = response.json() - - coverImage_url = result["results"][0]["thumbnail"] - description = result["results"][0]["description"] - genre = result["results"][0]["genre"] - category = result["results"][0]["category"] - title = result["results"][0]["name"] - link = result["results"][0]["magnetLink"] - link_result = await telegraph( - title=title, user_name=message.from_user.first_name, content=link - ) - language = result["results"][0]["language"] - size = result["results"][0]["size"] - - results = [] - - for i in range(min(limit, len(result["results"]))): - descriptions = result["results"][i]["description"] - genres = result["results"][i]["genre"] - categorys = result["results"][i]["category"] - titles = result["results"][i]["name"] - links = result["results"][i]["magnetLink"] - languages = result["results"][i]["language"] - sizes = result["results"][i]["size"] - - r = f"Title: {titles}\nCategory: {categorys}\nLanguage: {languages}\nSize: {sizes}\nGenres: {genres}\nDescription: {descriptions}\nMagnet Link: {links}
" - results.append(r) - - all_results_content = "
".join(results) - - link_results = await telegraph( - title="Search Results", - user_name=message.from_user.first_name, - content=all_results_content, - ) - - if coverImage_url is not None: - coverImage = requests.get(url=coverImage_url).content - async with aiofiles.open("coverImage.jpg", mode="wb") as f: - await f.write(coverImage) - - await message.delete() - await client.send_media_group( - chat_id, - [ - InputMediaPhoto( - "coverImage.jpg", - caption=f"Title: {title}\nCategory: {category}\nLanguage: {language}\nSize: {size}\nGenres: {genre}\nDescription: {description}\nMagnet Link: Click Here\nMore Results: Click Here", - ) - ], - ) - else: - await message.edit_text( - f"Title: {title}\nCategory: {category}\nLanguage: {language}\nSize: {size}\nGenres: {genre}\nDescription: {description}\nMagnet Link: Click Here\nMore Results: Click Here", - disable_web_page_preview=True, - ) - - except MediaCaptionTooLong: - description = description[:850] - await message.delete() - await client.send_media_group( - chat_id, - [ - InputMediaPhoto( - "coverImage.jpg", - caption=f"Title: {title}\nCategory: {category}\nLanguage: {language}\nSize: {size}\nGenres: {genre}\nDescription: {description}\nMagnet Link: Click Here", - ) - ], - ) - - except MessageTooLong: - description = description[:150] - await message.edit_text( - f"Title: {title}\nCategory: {category}\nLanguage: {language}\nSize: {size}\nGenres: {genre}\nDescription: {description}\nMagnet Link: Click Here", - disable_web_page_preview=True, - ) - - except Exception as e: - await message.edit_text(format_exc(e)) - finally: - if os.path.exists("coverImage.jpg"): - os.remove("coverImage.jpg") - - -@Client.on_message(filters.command("tts", prefix) & filters.me) -async def tts(client: Client, message: Message): - characters = await voice_characters() - await message.edit_text("Please Wait...") - try: - if len(message.command) > 2: - character, prompt = message.text.split(maxsplit=2)[1:] - if character not in characters: - await message.edit_text( - f"Usage: {prefix}tts [character]* [text/reply to text]*\n Available Characters:
{characters}
" - ) - return - - elif message.reply_to_message and len(message.command) > 1: - character = message.text.split(maxsplit=1)[1] - if character in characters: - prompt = message.reply_to_message.text - else: - await message.edit_text( - f"Usage: {prefix}tts [character]* [text/reply to text]*\n Available Characters:
{characters}
" - ) - return - - else: - await message.edit_text( - f"Usage: {prefix}tts [character]* [text/reply to text]*\n Available Characters:
{characters}
" - ) - return - - data = {"text": prompt, "character": character} - response = requests.post(url=f"{url}/speech", headers=headers, json=data) - if response.status_code != 200: - await message.edit_text("Something went wrong") - return - - result = response.json() - audio_data = result["audio"] - audio_data = base64.b64decode(audio_data) - async with aiofiles.open(f"{prompt}.mp3", mode="wb") as f: - await f.write(audio_data) - - await message.delete() - await client.send_audio( - chat_id=message.chat.id, - audio=f"{prompt}.mp3", - caption=f"Characters: {character}\nPrompt: {prompt}", - ) - if os.path.exists(f"{prompt}.mp3"): - os.remove(f"{prompt}.mp3") - - except KeyError: - try: - error = result["error"] - await message.edit_text(error) - except KeyError: - await message.edit_text( - f"Usage: {prefix}tts [character]* [text/reply to text]*\n Available Characters:
{characters}
" - ) - except Exception as e: - await message.edit_text(format_exc(e)) - - -@Client.on_message( - filters.command(["carbonnowsh", "carboon", "carbon", "cboon"], prefix) & filters.me -) -async def carbon(client: Client, message: Message): - if message.reply_to_message: - text = message.reply_to_message.text - message_id = message.reply_to_message.id - elif len(message.command) > 1: - message_id = None - text = message.text.split(maxsplit=1)[1] - else: - await message.edit_text("Query not provided!") - return - await message.edit_text("Processing...") - - image_file = await make_carbon(text) - - await message.delete() - try: - await client.send_photo( - chat_id=message.chat.id, - photo=image_file, - caption=f"Text: {text}", - reply_to_message_id=message_id, - ) - except MediaCaptionTooLong: - cap = text[:850] - await client.send_photo( - chat_id=message.chat.id, - photo=image_file, - caption=f"Text: {cap}", - reply_to_message_id=message_id, - ) - except Exception as e: - await message.edit_text(format_exc(e)) - if os.path.exists("carbon.png"): - os.remove("carbon.png") - - -@Client.on_message(filters.command("ccgen", prefix) & filters.me) -async def ccgen(_, message: Message): - if len(message.command) > 1: - bins = message.text.split(maxsplit=1)[1] - else: - await message.edit_text("Code not provided!") - return - await message.edit_text("Processing...") - response = requests.get(url=f"{url}/ccgen?bins={bins}", headers=headers) - if response.status_code != 200: - await message.edit_text("Something went wrong") - return - - result = response.json() - - cards = result["results"][0]["cards"] - cards_str = "\n".join([f'"{card}"' for card in cards]) - bins = result["results"][0]["bin"] - await message.edit_text( - f"Bins: {bins}\nTotal: {len(cards)}\nCards: \n{cards_str}" - ) - - -@Client.on_message(filters.command("rayso", prefix) & filters.me) -async def rayso(client: Client, message: Message): - title = "Untitled" - themes = [ - "vercel", - "supabase", - "tailwind", - "clerk", - "mintlify", - "prisma", - "bitmap", - "noir", - "ice", - "sand", - "forest", - "mono", - "breeze", - "candy", - "crimson", - "falcon", - "meadow", - "midnight", - "raindrop", - "sunset", - ] - if message.reply_to_message: - text = message.reply_to_message.text - message_id = message.reply_to_message.id - if 2 <= len(message.command) <= 3: - title = message.text.split(maxsplit=2)[1] - theme = message.text.split(maxsplit=2)[2].lower() - if theme not in themes: - theme = "breeze" - elif len(message.command) > 1: - message_id = message.id - title = message.text.split(maxsplit=3)[1] - theme = message.text.split(maxsplit=3)[2] - if theme not in themes: - theme = "breeze" - text = message.text.split(maxsplit=3)[3] - else: - await message.edit_text("Query not provided!") - return - await message.edit_text("Processing...") - - image_file = await make_rayso(text, title, theme) - - if image_file is None: - await message.edit_text("Something went wrong") - return - try: - await client.send_photo( - chat_id=message.chat.id, - photo=image_file, - caption=f"Text: {text}", - reply_to_message_id=message_id, - ) - await message.delete() - except MediaCaptionTooLong: - cap = text[:850] - await client.send_photo( - chat_id=message.chat.id, - photo=image_file, - caption=f"Text: {cap}", - reply_to_message_id=message_id, - ) - await message.delete() - except Exception as e: - await message.edit_text(format_exc(e)) - if os.path.exists(image_file): - os.remove(image_file) - - -modules_help["safone"] = { - "asq [query]*": "Asq", - "app [query]*": "Search for an app on Play Store", - "tsearch [query]*": "Search Torrent", - "tts [character]* [text/reply to text]*": "Convert Text to Speech", - "sgemini [prompt]*": "Gemini Model through safone api", - "carbon [code/file/reply]": "Create beautiful image with your code", - "ccgen [bins]*": "Generate credit cards", - "rayso [title]* [theme]* [text/reply to text]*": "Create beautiful image with your text", -} diff --git a/utils/scripts.py b/utils/scripts.py index ac45ed88..21f3a0c4 100644 --- a/utils/scripts.py +++ b/utils/scripts.py @@ -216,25 +216,6 @@ def text(message: Message) -> str: return message.text if message.text else message.caption -async def make_carbon(code): - url = "https://carbonara.solopov.dev/api/cook" - - async with aiohttp.ClientSession() as session: - async with session.post(url, json={"code": code}) as resp: - image_data = await resp.read() - - carbon_image = Image.open(BytesIO(image_data)) - - enhancer = ImageEnhance.Brightness(carbon_image) - bright_image = enhancer.enhance(1.0) - - output_image = BytesIO() - bright_image.save(output_image, format="PNG", quality=95) - output_image.name = "carbon.png" - - return output_image - - def restart() -> None: music_bot_pid = db.get("custom.musicbot", "music_bot_pid", None) if music_bot_pid is not None: From 6289d3aad83c4b5145dc5a3bbde851f56f9cda5e Mon Sep 17 00:00:00 2001 From: Abhi <85984486+AbhiTheModder@users.noreply.github.com> Date: Fri, 29 Nov 2024 19:19:11 +0530 Subject: [PATCH 04/13] format --- install.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/install.sh b/install.sh index 5eaffd8e..867f2196 100755 --- a/install.sh +++ b/install.sh @@ -328,18 +328,18 @@ EOL systemctl enable Moon printf "${GREEN}============================\\n" - printf "Great! Moon-Userbot installed successfully and running now!" - printf "Installation type: Systemd service" - printf "Start with: \"sudo systemctl start Moon\"" - printf "Stop with: \"sudo systemctl stop Moon\"" + printf "Great! Moon-Userbot installed successfully and running now!\n" + printf "Installation type: Systemd service\n" + printf "Start with: \"sudo systemctl start Moon\"\n" + printf "Stop with: \"sudo systemctl stop Moon\"\n" printf "============================${NC}\n" break ;; 3) printf "${GREEN}============================\\n" - printf "Great! Moon-Userbot installed successfully!" - printf "Installation type: Custom" - printf "Start with: \"python3 main.py\"" + printf "Great! Moon-Userbot installed successfully!\n" + printf "Installation type: Custom\n" + printf "Start with: \"python3 main.py\"\n" printf "============================${NC}\n" break ;; From 6a228170b9d5f55b79790c0e54118ea5f2438022 Mon Sep 17 00:00:00 2001 From: Abhi <85984486+AbhiTheModder@users.noreply.github.com> Date: Fri, 29 Nov 2024 21:37:26 +0530 Subject: [PATCH 05/13] fix --- start | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/start b/start index 6701a2c8..cb333fff 100755 --- a/start +++ b/start @@ -1,8 +1,8 @@ #!/usr/bin/env bash -if [ -d ".venv"]; then +if [ -d ".venv" ]; then . .venv/bin/activate -elif [ -d "venv"]; then +elif [ -d "venv" ]; then . venv/bin/activate fi From add54827a19f3f10c7018123bd404d494278427a Mon Sep 17 00:00:00 2001 From: Abhi <85984486+AbhiTheModder@users.noreply.github.com> Date: Fri, 29 Nov 2024 22:25:37 +0530 Subject: [PATCH 06/13] refactor docker --- .github/workflows/cloud-image.yml | 27 +++++++++++++++++++++++++++ .github/workflows/docker-image.yml | 1 + Cloudfile | 8 ++++++++ README.md | 8 +++++++- compose.yml | 4 +++- docker-compose.yml | 4 +++- 6 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/cloud-image.yml create mode 100644 Cloudfile diff --git a/.github/workflows/cloud-image.yml b/.github/workflows/cloud-image.yml new file mode 100644 index 00000000..7b1299ec --- /dev/null +++ b/.github/workflows/cloud-image.yml @@ -0,0 +1,27 @@ +name: Cloud Docker Image CI + +on: + push: + branches: + - main +jobs: + push_to_registry: + name: Cloud Docker Image CI + runs-on: ubuntu-latest + steps: + - name: Check out the repo + uses: actions/checkout@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push Docker image + uses: docker/build-push-action@v4 + with: + context: ./ + file: ./Cloudfile + push: true + tags: qbtaumai/moonubcloud:latest-cloud diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 7d3c5431..18e096f7 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -22,5 +22,6 @@ jobs: uses: docker/build-push-action@v4 with: context: ./ + file: ./Dockerfile push: true tags: qbtaumai/moonuserbot:latest diff --git a/Cloudfile b/Cloudfile new file mode 100644 index 00000000..f5d8283f --- /dev/null +++ b/Cloudfile @@ -0,0 +1,8 @@ +FROM python:3.11 +WORKDIR /app +COPY . /app +RUN apt-get -qq update && apt-get -qq install -y git wget ffmpeg mediainfo \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* +RUN pip install --no-cache-dir -r requirements.txt +CMD ["bash", "cloud.sh"] \ No newline at end of file diff --git a/README.md b/README.md index af84f038..c4ae8563 100644 --- a/README.md +++ b/README.md @@ -90,14 +90,20 @@ You can either use `docker run` or `docker compose`. - Put your environment vars in `.env` file check [.env.dist](/.env.dist) for example format ### 👷‍♂️`docker run`: +We also push images to [Docker Hub](https://hub.docker.com/), so you can use the following commands to start and update the service: - Start: + 1. If you want to use normal image: ```shell docker run --env-file ./.env -d qbtaumai/moonuserbot:latest ``` + 2. If you want to use image with flask web (only recommended for heroku/koyeb/render etc.): + ```shell + docker run --env-file ./.env -d qbtaumai/moonubcloud:latest-cloud + ``` - Updating: ```shell - docker stop $(docker ps -q) && docker rm $(docker ps -a -q) + docker stop $(docker ps -q) ``` then re-run the start command diff --git a/compose.yml b/compose.yml index 86b92cbc..5c01f341 100644 --- a/compose.yml +++ b/compose.yml @@ -1,6 +1,8 @@ services: moonuserbot: - image: qbtaumai/moonuserbot:latest + build: + context: . + dockerfile: Dockerfile container_name: moonuserbot restart: unless-stopped env_file: diff --git a/docker-compose.yml b/docker-compose.yml index cf04c726..604020bc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,9 @@ version: "3" services: moonuserbot: - image: qbtaumai/moonuserbot:latest + build: + context: . + dockerfile: Dockerfile container_name: moonuserbot restart: unless-stopped env_file: From d54d78e677bf67983f46a7ca6f9689f0bea3b5e9 Mon Sep 17 00:00:00 2001 From: Abhi <85984486+AbhiTheModder@users.noreply.github.com> Date: Sat, 30 Nov 2024 01:21:42 +0530 Subject: [PATCH 07/13] Create DISCLAIMER.md --- DISCLAIMER.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 DISCLAIMER.md diff --git a/DISCLAIMER.md b/DISCLAIMER.md new file mode 100644 index 00000000..c5bf3976 --- /dev/null +++ b/DISCLAIMER.md @@ -0,0 +1,6 @@ +## Disclaimer +> [!WARNING] +> The use of this Telegram Userbot is entirely at your own risk. The developer of this Userbot is not responsible for any misuse, damage, or legal consequences that may arise from your use of this software. +>> It is your responsibility to ensure that you use this Userbot in accordance with all applicable laws and regulations, and that you do not engage in any activities that may cause harm to others or violate their privacy. This includes, but is not limited to, the use of this Userbot to send spam, harass others, or engage in any other form of unlawful or malicious activity. +>> The developer of this Userbot does not endorse or condone any such activities, and any such use of this software is strictly prohibited. By using this Userbot, you acknowledge that you are solely responsible for your own actions and that the developer of this Userbot shall not be held liable for any damages or consequences that may arise from your use of this software. +>> It is your responsibility to ensure that you have obtained all necessary permissions and consents before using this Userbot to interact with others, and that you respect their privacy and rights. The developer of this Userbot shall not be held liable for any breach of privacy or rights that may occur as a result of your use of this software. From 4b4e33686ae9a1e00e23ace8f8f2216561b34fd5 Mon Sep 17 00:00:00 2001 From: Abhi <85984486+AbhiTheModder@users.noreply.github.com> Date: Sat, 30 Nov 2024 02:03:03 +0530 Subject: [PATCH 08/13] remove unused music handler from install (#104) * remove unused music handler from install --- .env.dist | 3 --- install.sh | 54 +++++++++++++++++++++++------------------------------- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/.env.dist b/.env.dist index 7722fb75..c8e60b89 100644 --- a/.env.dist +++ b/.env.dist @@ -16,9 +16,6 @@ STRINGSESSION={@string_session} # Set if you want to use music bot SECOND_SESSION={@second_session} -# Music handler for music bot -MUSIC_HANDLER={@music_handler} - # PM LIMIT for AntiPM plugin PM_LIMIT={@pm_limit} diff --git a/install.sh b/install.sh index 867f2196..fcc74427 100755 --- a/install.sh +++ b/install.sh @@ -12,11 +12,11 @@ PACKAGE_MANAGER="" # Ensure the script is run with root privileges if [[ $UID != 0 ]]; then - printf "${YELLOW}This script requires root privileges.${NC}\n" + printf "${YELLOW}This script requires root privileges.${NC}\n" # skipcq printf "Please enter the root password to continue.\n" exec sudo "$0" "$@" else - printf "${YELLOW}Running with root privileges${NC}\n" + printf "${YELLOW}Running with root privileges${NC}\n" # skipcq fi # Detect available package manager @@ -29,12 +29,12 @@ elif command -v yum &>/dev/null; then elif command -v pacman &>/dev/null; then PACKAGE_MANAGER="pacman" else - printf "${RED}Unsupported package manager. Please use a compatible distribution or update the installer script.${NC}\n" + printf "${RED}Unsupported package manager. Please use a compatible distribution or update the installer script.${NC}\n" # skipcq exit 1 fi if command -v termux-setup-storage; then - printf "${RED}For termux, please use https://raw.githubusercontent.com/The-MoonTg-project/Moon-Userbot/main/termux-install.sh${NC}\n" + printf "${RED}For termux, please use https://raw.githubusercontent.com/The-MoonTg-project/Moon-Userbot/main/termux-install.sh${NC}\n" # skipcq exit 1 fi @@ -61,22 +61,22 @@ esac if [[ -d "Moon-Userbot" && "$(basename "$PWD")" != "Moon-Userbot" ]]; then cd Moon-Userbot || exit 2 elif [[ "$(basename "$PWD")" == "Moon-Userbot" && -f ".env.dist" && -f "main.py" && -d "modules" ]]; then - printf "${BLUE}Already inside the Moon-Userbot repo, proceeding...${NC}\n" + printf "${BLUE}Already inside the Moon-Userbot repo, proceeding...${NC}\n" # skipcq else git clone https://github.com/The-MoonTg-project/Moon-Userbot || exit 2 cd Moon-Userbot || exit 2 fi if [[ -f ".env" ]] && [[ -f "my_account.session" ]]; then - printf "${GREEN}It seems that Moon-Userbot is already installed. Exiting...${NC}\n" + printf "${GREEN}It seems that Moon-Userbot is already installed. Exiting...${NC}\n" # skipcq exit fi # Prompt user if they want to proceed with creating a virtual environment -printf "${YELLOW}It's recommended to use a virtual environment for Python projects.${NC}\n" +printf "${YELLOW}It's recommended to use a virtual environment for Python projects.${NC}\n" # skipcq printf "Note: If your drive resources are very limited, you might consider not creating a virtual environment, but it shouldn't be rejected otherwise unless you know what you're doing.\n" printf "If you're unsure, it's better to create a virtual environment.\n" -printf "${INPUT}Would you like to create a virtual environment? (Y/n)${NC} > " +printf "${INPUT}Would you like to create a virtual environment? (Y/n)${NC} > " # skipcq read -r create_venv if [[ "$create_venv" != "n" ]] && [[ "$create_venv" != "N" ]]; then @@ -99,19 +99,19 @@ pip install -U -r requirements.txt || exit 2 # Prompt for API_ID and API_HASH printf "Enter API_ID and API_HASH\n" printf "You can get it here -> https://my.telegram.org/\n" -printf "Leave empty to use defaults (please note that using default keys is a ${RED}very bad idea${NC} and significantly increases your ban chances)\n" +printf "Leave empty to use defaults (please note that using default keys is a ${RED}very bad idea${NC} and significantly increases your ban chances)\n" # skipcq read -r -p "API_ID > " api_id # Default API_ID and API_HASH if [[ $api_id = "" ]]; then - printf "${RED}You have chosen to use the default API_ID and API_HASH, which is strongly discouraged.${NC}\n" - printf "${YELLOW}Please type${NC} '${BLUE}I agree${NC}'${YELLOW} to confirm that you understand the risks and still wish to proceed.${NC}\n" + printf "${RED}You have chosen to use the default API_ID and API_HASH, which is strongly discouraged.${NC}\n" # skipcq + printf "${YELLOW}Please type${NC} '${BLUE}I agree${NC}'${YELLOW} to confirm that you understand the risks and still wish to proceed.${NC}\n" # skipcq read -r -p "Confirmation > " confirmation if [[ $confirmation = "I agree" ]]; then api_id="2040" api_hash="b18441a1ff607e10a989891a5462e627" else - printf "${RED}Confirmation not provided. Exiting...${NC}\n" + printf "${RED}Confirmation not provided. Exiting...${NC}\n" # skipcq exit 1 fi else @@ -121,7 +121,7 @@ fi # PM PERMIT warn limit is the number of messages a user can receive from others before giving them a warning, requires `antipm` plugin to be enabled printf "SET PM PERMIT warn limit\n" # Now below is more clear version: -printf "The number of messages others can send you before receiving a warning, and eventually a ban or leave empty for default (3), requires $(antipm) plugin to be enabled\n" +printf "The number of messages others can send you before receiving a warning, and eventually a ban or leave empty for default (3), requires antipm plugin to be enabled\n" read -r -p "PM_LIMIT warn limit > " pm_limit if [[ $pm_limit = "" ]]; then @@ -138,13 +138,6 @@ if [[ $musicbot = "y" ]]; then if [[ $second_session = "" ]]; then printf "SECOND_SESSION not provided by user\n" second_session="" - else - printf "Please provide handler to be used by musicbotn\n" - read -r -p "MUSIC_HANDLER > " music_handler - if [[ $music_handler = "" ]]; then - printf "MUSIC_HANDLER not provided by user\n" - music_handler="" - fi fi fi @@ -199,7 +192,7 @@ fi while true; do # Prompt for database type and database URL if MongoDB is selected - printf "${YELLOW}Choose database type:${NC}\n" + printf "${YELLOW}Choose database type:${NC}\n" # skipcq printf "[1] MongoDB db_url\n" printf "[2] MongoDB localhost\n" printf "[3] Sqlite (default)\n" @@ -224,7 +217,7 @@ while true; do if systemctl status mongodb; then wget -qO - https://www.mongodb.org/static/pgp/server-5.0.asc | apt-key add - source /etc/os-release - printf "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu ${UBUNTU_CODENAME}/mongodb-org/5.0 multiverse\n" | tee /etc/apt/sources.list.d/mongodb-org-5.0.list + printf "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu %s/mongodb-org/5.0 multiverse\n" "${UBUNTU_CODENAME}" | tee /etc/apt/sources.list.d/mongodb-org-5.0.list apt update apt install mongodb -y systemctl daemon-reload @@ -243,7 +236,7 @@ while true; do break ;; *) - printf "${RED}Invalid choice!${NC}\n" + printf "${RED}Invalid choice!${NC}\n" # skipcq ;; esac done @@ -267,7 +260,6 @@ VCA_API_KEY=${vca_api_key} COHERE_KEY=${cohere_key} PM_LIMIT=${pm_limit} SECOND_SESSION=${second_session} -MUSIC_HANDLER=${music_handler} EOL # Adjust the ownership of the Moon-Userbot directory @@ -276,7 +268,7 @@ chown -R $SUDO_USER:$SUDO_USER . # Configure the bot based on selected installation type while true; do # Prompt for installation type and execute accordingly - printf "${YELLOW}Choose installation type:${NC}\n" + printf "${YELLOW}Choose installation type:${NC}\n" # skipcq printf "[1] PM2\n" printf "[2] Systemd service\n" printf "[3] Custom (default)\n" @@ -300,13 +292,13 @@ while true; do su -c "pm2 start main.py --name Moon --interpreter python3" $SUDO_USER su -c "pm2 save" $SUDO_USER - printf "${GREEN}============================\\n" + printf "${GREEN}============================\\n" # skipcq printf "Great! Moon-Userbot installed successfully and running now!\n" printf "Installation type: PM2\n" printf "Start with: \"pm2 start Moon\"\n" printf "Stop with: \"pm2 stop Moon\"\n" printf "Process name: Moon\n" - printf "============================${NC}\n" + printf "============================${NC}\n" # skipcq break ;; 2) @@ -327,20 +319,20 @@ EOL systemctl start Moon systemctl enable Moon - printf "${GREEN}============================\\n" + printf "${GREEN}============================\\n" # skipcq printf "Great! Moon-Userbot installed successfully and running now!\n" printf "Installation type: Systemd service\n" printf "Start with: \"sudo systemctl start Moon\"\n" printf "Stop with: \"sudo systemctl stop Moon\"\n" - printf "============================${NC}\n" + printf "============================${NC}\n" # skipcq break ;; 3) - printf "${GREEN}============================\\n" + printf "${GREEN}============================\\n" # skipcq printf "Great! Moon-Userbot installed successfully!\n" printf "Installation type: Custom\n" printf "Start with: \"python3 main.py\"\n" - printf "============================${NC}\n" + printf "============================${NC}\n" # skipcq break ;; *) From 36fd906bb2090c6466dd9be05fc5e650d4d53427 Mon Sep 17 00:00:00 2001 From: Abhi <85984486+AbhiTheModder@users.noreply.github.com> Date: Sat, 30 Nov 2024 03:30:01 +0530 Subject: [PATCH 09/13] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index c4ae8563..b9a68b6e 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,8 @@ - **YT Video [How to deploy on Koyeb]**: +**For Detailed Guide refer to [wiki](https://github.com/The-MoonTg-project/Moon-Userbot/wiki/Installation#koyeb-free)** + ## 🐳 Docker You can either use `docker run` or `docker compose`. From 5fdbe84aed06ccced60bf6bbb8dda6939cb83b49 Mon Sep 17 00:00:00 2001 From: Abhi <85984486+AbhiTheModder@users.noreply.github.com> Date: Sat, 30 Nov 2024 05:50:16 +0530 Subject: [PATCH 10/13] set custom afk & pm permit (#105) * set custom afk message * set custom antipm message --- modules/afk.py | 54 +++++++++++++++++++++++++++++++++++++++++------ modules/antipm.py | 50 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 95 insertions(+), 9 deletions(-) diff --git a/modules/afk.py b/modules/afk.py index effaf717..ab171199 100644 --- a/modules/afk.py +++ b/modules/afk.py @@ -23,6 +23,7 @@ from utils.misc import modules_help, prefix from utils.scripts import ReplyCheck +from utils.db import db # Variables AFK = False @@ -59,13 +60,18 @@ async def collect_afk_messages(bot: Client, message: Message): CHAT_TYPE = GROUPS if is_group else USERS if GetChatID(message) not in CHAT_TYPE: - text = ( - f"Beep boop. This is an automated message.\n" - f"I am not available right now.\n" - f"Last seen: {last_seen}\n" - f"Reason: {AFK_REASON.upper()}\n" - f"See you after I'm done doing whatever I'm doing." - ) + text = db.get("core.afk", "afk_msg", None) + if text is None: + text = ( + f"Beep boop. This is an automated message.\n" + f"I am not available right now.\n" + f"Last seen: {last_seen}\n" + f"Reason: {AFK_REASON.upper()}\n" + f"See you after I'm done doing whatever I'm doing." + ) + else: + last_seen = last_seen.replace("ago", "").strip() + text = text.format(last_seen=last_seen, reason=AFK_REASON) await bot.send_message( chat_id=GetChatID(message), text=text, @@ -144,6 +150,39 @@ async def afk_unset(_, message: Message): await message.delete() +@Client.on_message(filters.command("setafkmsg", prefix) & filters.me, group=3) +async def set_afk_msg(_, message: Message): + if not message.reply_to_message: + return await message.edit("Reply to a message to set it as your AFK message.") + + msg = message.reply_to_message + afk_msg = msg.text or msg.caption + + if not afk_msg: + return await message.edit( + "Reply to a text or caption message to set it as your AFK message." + ) + + if len(afk_msg) > 200: + return await message.edit( + "AFK message is too long. It should be less than 200 characters." + ) + if "{reason}" not in afk_msg: + return await message.edit( + "AFK message should contain {reason} to indicate where the reason will be placed." + ) + if "{last_seen}" not in afk_msg: + return await message.edit( + "AFK message should contain {last_seen} to indicate where the last seen time will be placed." + ) + + old_afk_msg = db.get("core.afk", "afk_msg", None) + if old_afk_msg: + db.remove("core.afk", "afk_msg") + db.set("core.afk", "afk_msg", afk_msg) + await message.edit(f"AFK message set to:\n\n{afk_msg}") + + @Client.on_message(filters.me, group=3) async def auto_afk_unset(_, message: Message): global AFK, AFK_TIME, AFK_REASON, USERS, GROUPS @@ -166,4 +205,5 @@ async def auto_afk_unset(_, message: Message): modules_help["afk"] = { "afk [reason]": "Go to AFK mode with reason as anything after .afk\nUsage: .afk ", "unafk": "Get out of AFK", + "setafkmsg [reply to message]*": "Set your AFK message. Use {reason} and {last_seen} to indicate where the reason and last seen time will be placed.", } diff --git a/modules/antipm.py b/modules/antipm.py index be51996c..6823d869 100644 --- a/modules/antipm.py +++ b/modules/antipm.py @@ -52,14 +52,18 @@ async def anti_pm_handler(client: Client, message: Message): user = await client.get_users(ids) u_f = user.first_name user_info = await client.resolve_peer(ids) - default_text = f"""Hello, {u_f}! + default_text = db.get("core.antipm", "antipm_msg", None) + if default_text is None: + default_text = f"""Hello, {u_f}! This is the Assistant Of {u_n}. My Boss is away or busy as of now, You can wait for him to respond. Do not spam further messages else I may have to block you! This is an automated message by the assistant. Currently You Have {warns} Warnings. -""" + """ + else: + default_text = default_text.format(user=u_f, my_name=u_n, warns=warns) if db.get("core.antipm", "spamrep", False): await client.invoke(functions.messages.ReportSpam(peer=user_info)) if db.get("core.antipm", "block", False): @@ -179,10 +183,52 @@ async def del_contact(_, message: Message): await message.edit("User DisApproved!") +@Client.on_message(filters.command(["setantipmmsg", "sam"], prefix) & filters.me) +async def set_antipm_msg(_, message: Message): + if not message.reply_to_message: + return await message.edit( + "Reply to a message to set it as your antipm message." + ) + + msg = message.reply_to_message + afk_msg = msg.text or msg.caption + + if not afk_msg: + return await message.edit( + "Reply to a text or caption message to set it as your antipm message." + ) + + if len(afk_msg) > 200: + return await message.edit( + "antipm message is too long. It should be less than 200 characters." + ) + + if "{user}" not in afk_msg: + return await message.edit( + "antipm message must contain {user} to mention the user." + ) + if "{my_name}" not in afk_msg: + return await message.edit( + "antipm message must contain {my_name} to mention your name." + ) + if "{warns}" not in afk_msg: + return await message.edit( + "antipm message must contain {warns} to mention the warns count." + ) + + old_afk_msg = db.get("core.antipm", "antipm_msg", None) + if old_afk_msg: + db.remove("core.antipm", "antipm_msg") + db.set("core.antipm", "antipm_msg", afk_msg) + await message.edit(f"antipm message set to:\n\n{afk_msg}") + + modules_help["antipm"] = { "antipm [enable|disable]*": "Enable Pm permit", "antipm_report [enable|disable]*": "Enable spam reporting", "antipm_block [enable|disable]*": "Enable user blocking", + "setantipmmsg [reply to message]*": "Set antipm message. Use {user} to mention the user and {my_name} to mention your name and {warns} to mention the warns count.", + "sam [reply to message]*": "Set antipm message. Use {user} to mention the user and {my_name} to mention your name and {warns} to mention the warns count.", "a": "Approve User", "d": "DisApprove User", } From fdd3546e9f534dad136e251f852b8be31b0e1a90 Mon Sep 17 00:00:00 2001 From: Abhi <85984486+AbhiTheModder@users.noreply.github.com> Date: Wed, 4 Dec 2024 22:04:29 +0530 Subject: [PATCH 11/13] implement plugins load with category --- modules/loader.py | 60 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/modules/loader.py b/modules/loader.py index 7c5ad3b6..56ba1e0d 100644 --- a/modules/loader.py +++ b/modules/loader.py @@ -29,6 +29,22 @@ BASE_PATH = os.path.abspath(os.getcwd()) +CATEGORIES = [ + "ai", + "dl", + "admin", + "anime", + "fun", + "images", + "info", + "misc", + "music", + "news", + "paste", + "rev", + "tts", + "utils", +] @Client.on_message(filters.command(["modhash", "mh"], prefix) & filters.me) @@ -73,25 +89,31 @@ async def loadmod(_, message: Message): 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"Troubleshooting with downloading module {url}", - ) - return - - if hashlib.sha256(resp.content).hexdigest() not in modules_hashes: - return await message.edit( - "Only " - "verified modules or from the official " - "" - "custom_modules repository are supported!", - disable_web_page_preview=True, - ) + if "/" in url: + for category in CATEGORIES: + if url.startswith(f"{category}/"): + url = f"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/{url}.py" + break + 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"Troubleshooting with downloading module {url}", + ) + return + + if hashlib.sha256(resp.content).hexdigest() not in modules_hashes: + return await message.edit( + "Only " + "verified modules or from the official " + "" + "custom_modules repository are supported!", + disable_web_page_preview=True, + ) module_name = url.split("/")[-1].split(".")[0] From 1394aec513ecf6c2481ac6b7b2e746b0d2bad187 Mon Sep 17 00:00:00 2001 From: Abhi <85984486+AbhiTheModder@users.noreply.github.com> Date: Wed, 4 Dec 2024 22:46:57 +0530 Subject: [PATCH 12/13] resolve dependabot issues (#106) --- modules/help.py | 12 +++++------- utils/scripts.py | 4 +--- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/modules/help.py b/modules/help.py index a0edcbb9..d76894e5 100644 --- a/modules/help.py +++ b/modules/help.py @@ -21,13 +21,13 @@ total_pages = 0 -async def send_page(message, module_list, page, total_pages): +async def send_page(message, module_list, page, total_page): start_index = (page - 1) * 10 end_index = start_index + 10 page_modules = module_list[start_index:end_index] - text = f"Help for Moon-Userbot\n" + text = "Help for Moon-Userbot\n" text += f"For more help on how to use a command, type {prefix}help [module]\n\n" - text += f"Page {page}/{total_pages}\n\n" + text += f"Page {page}/{total_page}\n\n" for module_name in page_modules: commands = modules_help[module_name] text += f"• {module_name.title()}: {', '.join([f'{prefix + cmd_name.split()[0]}' for cmd_name in commands.keys()])}\n" @@ -77,8 +77,7 @@ async def handle_navigation(_, message: Message): message, list(modules_help.keys()), current_page, total_pages ) return await message.reply_to_message.delete() - else: - await message.edit("No more pages available.") + await message.edit("No more pages available.") elif message.command[0].lower() == "pp": if current_page > 1: current_page -= 1 @@ -86,8 +85,7 @@ async def handle_navigation(_, message: Message): message, list(modules_help.keys()), current_page, total_pages ) return await message.reply_to_message.delete() - else: - return await message.edit("This is the first page.") + return await message.edit("This is the first page.") elif message.command[0].lower() == "pq": await message.reply_to_message.delete() return await message.edit("Help closed.") diff --git a/utils/scripts.py b/utils/scripts.py index 21f3a0c4..89813ba3 100644 --- a/utils/scripts.py +++ b/utils/scripts.py @@ -24,13 +24,11 @@ import sys import time import traceback -from PIL import Image, ImageEnhance +from PIL import Image from io import BytesIO -import aiohttp from types import ModuleType from typing import Dict, Tuple -from PIL import Image import psutil from pyrogram import Client, errors, enums from pyrogram.errors import FloodWait, MessageNotModified, UserNotParticipant From 728d97250dad050ea50c70d135fdb154a269a883 Mon Sep 17 00:00:00 2001 From: Abhi <85984486+AbhiTheModder@users.noreply.github.com> Date: Wed, 4 Dec 2024 22:54:49 +0530 Subject: [PATCH 13/13] ensure help page change when it's actually help message --- modules/help.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/help.py b/modules/help.py index d76894e5..7c0ff3de 100644 --- a/modules/help.py +++ b/modules/help.py @@ -27,7 +27,7 @@ async def send_page(message, module_list, page, total_page): page_modules = module_list[start_index:end_index] text = "Help for Moon-Userbot\n" text += f"For more help on how to use a command, type {prefix}help [module]\n\n" - text += f"Page {page}/{total_page}\n\n" + text += f"Help Page No: {page}/{total_page}\n\n" for module_name in page_modules: commands = modules_help[module_name] text += f"• {module_name.title()}: {', '.join([f'{prefix + cmd_name.split()[0]}' for cmd_name in commands.keys()])}\n" @@ -68,7 +68,7 @@ async def help_cmd(_, message: Message): @Client.on_message(filters.command(["pn", "pp", "pq"], prefix) & filters.me) @with_reply async def handle_navigation(_, message: Message): - if message.reply_to_message: + if message.reply_to_message and "Help Page No:" in message.reply_to_message.text: global current_page if message.command[0].lower() == "pn": if current_page < total_pages: