├── .deepsource.toml ├── .github └── workflows │ └── pythonapp.yml ├── .gitignore ├── CODE_OF_CONDUCT ├── Dockerfile ├── LICENSE ├── Procfile.txt ├── README.md ├── app.json ├── bin ├── cmrudl.py ├── impact.ttf ├── megadirect └── megadown ├── config.yml ├── emptydir ├── gd.png ├── generate_session_file.py ├── heroku.yml ├── requirements.txt ├── sample_config.env ├── string_session.py ├── termux_install.sh ├── userbot ├── __init__.py ├── __main__.py ├── events.py ├── modules │ ├── __init__.py │ ├── admin.py │ ├── adzan.py │ ├── afk.py │ ├── android.py │ ├── anime.py │ ├── anti_spambot.py │ ├── aria.py │ ├── ariav2.py │ ├── ascii.py │ ├── blacklist.py │ ├── chat.py │ ├── chatinfo.py │ ├── covid.py │ ├── crbn.py │ ├── create.py │ ├── deepfryer.py │ ├── deezload.py │ ├── direct_links.py │ ├── dogbin.py │ ├── evaluators.py │ ├── fakeload.py │ ├── fban.py │ ├── figlet.py │ ├── filemanager.py │ ├── filter.py │ ├── gban.py │ ├── getmusic.py │ ├── github.py │ ├── google_drive.py │ ├── hash.py │ ├── hazmat.py │ ├── help.py │ ├── heroku.py │ ├── invite.py │ ├── justwatch.py │ ├── lastfm.py │ ├── locks.py │ ├── lydia.py │ ├── lyrics.py │ ├── mega_downloader.py │ ├── memes.py │ ├── memify.py │ ├── misc.py │ ├── nhentai.py │ ├── notes.py │ ├── ocr.py │ ├── openuserbot.py │ ├── oprek.py │ ├── pics.py │ ├── pmpermit.py │ ├── profile.py │ ├── purge.py │ ├── qrcode.py │ ├── quote.py │ ├── rastick.py │ ├── remove_bg.py │ ├── reverse.py │ ├── sangmata.py │ ├── scrapers.py │ ├── screencap.py │ ├── screencapture.py │ ├── sed.py │ ├── shalom.py │ ├── shortener.py │ ├── snips.py │ ├── spam.py │ ├── sql_helper │ │ ├── .DS_Store │ │ ├── __init__.py │ │ ├── blacklist_sql.py │ │ ├── fban_sql.py │ │ ├── filter_sql.py │ │ ├── globals.py │ │ ├── gmute_sql.py │ │ ├── google_drive_sql.py │ │ ├── keep_read_sql.py │ │ ├── lydia_sql.py │ │ ├── notes_sql.py │ │ ├── pm_permit_sql.py │ │ ├── snips_sql.py │ │ ├── spam_mute_sql.py │ │ └── welcome_sql.py │ ├── ssvideo.py │ ├── stickers.py │ ├── sticklet.py │ ├── system_stats.py │ ├── telegraph.py │ ├── time.py │ ├── torrent.py │ ├── updater.py │ ├── upload_download.py │ ├── waifu.py │ ├── weather.py │ ├── webupload.py │ ├── weebify.py │ ├── welcomes.py │ ├── whois.py │ ├── www.py │ └── zipfile.py ├── util.py └── utils │ ├── FastTelethon.py │ ├── __init__.py │ ├── chrome.py │ ├── exceptions.py │ ├── google_images_download.py │ ├── progress.py │ └── tools.py └── windows_startup_script.py /.deepsource.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | test_patterns = ["*/ds/integrated/test.py"] 4 | 5 | [[analyzers]] 6 | name = "python" 7 | enabled = true 8 | 9 | [analyzers.meta] 10 | runtime_version = "3.x.x" 11 | -------------------------------------------------------------------------------- /.github/workflows/pythonapp.yml: -------------------------------------------------------------------------------- 1 | name: Checker 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | strategy: 10 | max-parallel: 5 11 | matrix: 12 | python-version: [3.8] 13 | 14 | steps: 15 | - uses: actions/checkout@v1 16 | - name: Set up Python ${{ matrix.python-version }} 17 | uses: actions/setup-python@v1 18 | with: 19 | python-version: ${{ matrix.python-version }} 20 | - name: Install dependencies 21 | run: | 22 | sudo apt-get install libpq-dev 23 | python -m pip install --upgrade pip 24 | pip install -r requirements.txt 25 | pip install flake8 flake8-print flake8-quotes 26 | - name: Check for showstoppers 27 | run: | 28 | # stop the build if there are Python syntax errors 29 | flake8 . --count --select=E999 --show-source --statistics 30 | 31 | shellcheck: 32 | 33 | runs-on: ubuntu-latest 34 | 35 | steps: 36 | - uses: actions/checkout@v1 37 | - name: Check for install script errors 38 | uses: ludeeus/action-shellcheck@0.1.0 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | config.env 2 | __pycache__/* 3 | userbot.db 4 | userbot.session 5 | userbot.session-journal 6 | userbot/__pycache__/* 7 | userbot/modules/__pycache__/* 8 | userbot/modules/sql_helper/__pycache__/* 9 | .progress 10 | .vscode/* 11 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | All participants of RaphielGang are expected to abide by our Code of Conduct, 4 | both online and during in-person events that are hosted and/or associated with RaphielGang. 5 | 6 | 7 | ### The Pledge 8 | 9 | In the interest of fostering an open and welcoming environment, we pledge to make participation 10 | in our project and our community a harassment-free experience for everyone, regardless of age, 11 | body size, disability, ethnicity, gender identity and expression, level of experience, 12 | nationality, personal appearance, race, religion, or sexual identity and orientation. 13 | 14 | 15 | ### The Standards 16 | 17 | Examples of behaviour that contributes to creating a positive environment include: 18 | 19 | * **Be welcoming**: We strive to be a community that welcomes and supports people of all backgrounds and identities. This includes, but is not limited to members of any race, ethnicity, culture, national origin, colour, immigration status, social and economic class, educational level, sex, sexual orientation, gender identity and expression, age, size, family status, political belief, religion, and mental and physical ability. 20 | * **Be considerate**: Your work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we're a world-wide community, so you might not be communicating in someone else's primary language. 21 | * **Be respectful**: Not all of us will agree all the time, but disagreement is no excuse for poor behavior and poor manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It’s important to remember that a community where people feel uncomfortable or threatened is not a productive one. 22 | * **Gracefully accepting constructive criticism**: Not everyone are perfect, you can get some critism of your works from us, but it's not means that we don't accepting your contribution, we just want you to fixing it and making it better. 23 | * **Referring to people by their preferred pronouns/words**, but we do not have standardized gender-neutral pronouns/words, so your milleage may vary. 24 | * **Do not attack somebody because you have a different opinion** All opinions are accepted as long as they are reasonable, and everyone have right to shouting their opinion. 25 | * **Just chill :D** 26 | * **Don't forget, nobody is perfect, mistakes can be made** 27 | * **Equality is not a privilege, it's a rule!** 28 | 29 | ### Examples of unacceptable behaviour by participants include: 30 | 31 | * **Trolling, insulting/derogatory comments, public or private harassment** 32 | * **Publishing others' private information (Doxing)** such as a physical or electronic address, without explicit permission 33 | * **Not being respectful to reasonable communication boundaries** such as 'leave me alone,' 'go away,' or 'Fuck off.' 34 | * **The usage of sexualised language or imagery and unwelcome sexual attention or advances** 35 | * **Demonstrating the graphics or any other content you know may be considered disturbing** 36 | * **Assuming or promoting any kind of inequality** including but not limited to: age, body size, disability, ethnicity, gender identity and expression, nationality and race, personal appearance, religion, or sexual identity and orientation 37 | * **Drug promotion of any kind** 38 | * **Attacking personal tastes** 39 | * **Other conduct which you know could reasonably be considered inappropriate in a professional setting** 40 | 41 | 42 | ### Enforcement 43 | 44 | Violations of the Code of Conduct may be reported by sending an email to [raphielscape@outlook.com](mailto:raphielscape@outlook.com). 45 | All reports will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. 46 | Further details of specific enforcement policies may be posted separately. 47 | 48 | We hold the right and responsibility to remove comments or other contributions that 49 | are not aligned to this Code of Conduct, or to ban temporarily or permanently any members 50 | for other behaviours that they deem inappropriate, threatening, offensive, or harmful. -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM heinzdf/oubnew:buster 2 | 3 | # Clone repo and prepare working directory 4 | RUN git clone -b sql-extended https://github.com/fortifying/OUBnew /OUBnew 5 | RUN chmod 777 /OUBnew 6 | WORKDIR /OUBnew 7 | 8 | # Copies session and config (if it exists) 9 | COPY ./sample_config.env ./userbot.session* ./config.env* /root/userbot/ 10 | 11 | # Install requirements 12 | CMD ["python3","-m","userbot"] 13 | -------------------------------------------------------------------------------- /Procfile.txt: -------------------------------------------------------------------------------- 1 | build: 2 | docker: 3 | worker: Dockerfile 4 | run: 5 | worker: python3 -m userbot 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Last Commit](https://img.shields.io/github/last-commit/fortifying/OUBnew/sql-extended) ![Contributors](https://img.shields.io/github/contributors/fortifying/OUBnew?color=LightSlateGrey) 2 | 3 | ``` 4 | Project is no longer maintained! Use other userbot if you want to deploy 5 | as this Project is outdated. 6 | ``` 7 | 8 | # Project OUBnew-Fortizer 9 | 10 | ![our](https://telegra.ph/file/02abf5720f639072ce258.png) 11 | 12 | ` 13 | A modular Telegram userbot running on Python 3.8+ with an sqlalchemy database. 14 | ` 15 | 16 | ``` 17 | #include 18 | /** 19 | Your Telegram account may get banned. 20 | I am not responsible for any improper use of this bot 21 | This bot is intended for the purpose of having fun with memes, 22 | as well as efficiently managing groups. 23 | You ended up spamming groups, getting reported left and right, 24 | and you ended up in a Finale Battle with Telegram and at the end 25 | Telegram Team deleted your account? 26 | And after that, then you pointed your fingers at us 27 | for getting your acoount deleted? 28 | I will be rolling on the floor laughing at you. 29 | /** 30 | ``` 31 | 32 |

 

33 | 34 | # Easy way to deploy 35 |

Deploy to Heroku

36 | 37 | 38 |

 

39 | 40 | # Google Drive Tutorial 41 | [![SetGD](https://raw.githubusercontent.com/fortifying/OUBnew/sql-extended/gd.png)](https://telegra.ph/How-To-Setup-Google-Drive-04-03) 42 | 43 | 44 | # Updates and Support 45 | 46 | Join Userbot Indo Cloud Channel for update notifications! 47 | 48 | Also join Userbot INDO🇮🇩 Telegram Group for help and support! 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | ## Credits 57 | * [lonami](https://lonami.dev) - For creating [Telethon](https://github.com/LonamiWebs/Telethon) 58 | * [RaphielGang](https://github.com/RaphielGang) - Telegram-Paperplane 59 | * [AvinashReddy3108](https://github.com/AvinashReddy3108) - PaperplaneExtended 60 | * [kandnub](https://github.com/kandnub) - TG-UserBot 61 | * [AdekMaulana](https://github.com/adekmaulana) - ProjectBish 62 | * [Mkaraniya](https://github.com/mkaraniya) - OpenUserBot 63 | 64 |

 

65 |

License

66 |

Raphielscape Public License - Version 1.d, July 2020

67 | -------------------------------------------------------------------------------- /bin/impact.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortifying/OUBnew/4bd421d606a22f99a5a0d599ba6327088cf1caa0/bin/impact.ttf -------------------------------------------------------------------------------- /bin/megadirect: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2018 Azure Zanculmarktum 4 | # Copyright 2019 Adek Maulana 5 | # All rights reserved. 6 | # 7 | # Redistribution and use of this script, with or without modification, is 8 | # permitted provided that the following conditions are met: 9 | # 10 | # 1. Redistributions of this script must retain the above copyright 11 | # notice, this list of conditions and the following disclaimer. 12 | # 13 | # THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED 14 | # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 15 | # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 16 | # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 17 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 18 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 19 | # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20 | # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 21 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 22 | # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | # Dependencies: 25 | # openssl 26 | 27 | # Usage: 28 | # $ ./megadirect https://mega.nz/#!abcdefgh!1234567890abcdefghijklmnopqrstuvwxyzABCDEFG 29 | # http://gfs208n103.userstorage.mega.co.nz/dl/-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890A 30 | # file.name 31 | # abcefghijklmnopqrstuvwxyz0123456 32 | # 1234567890abcdef0000000000000000 33 | # $ wget -O file.name http://gfs208n103.userstorage.mega.co.nz/dl/-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890A 34 | # $ cat file.name | openssl enc -d -aes-128-ctr -K abcefghijklmnopqrstuvwxyz0123456 -iv 1234567890abcdef0000000000000000 > file.name.new 35 | # $ mv -f file.name.new file.name 36 | 37 | URL="" 38 | 39 | if [[ $1 =~ ^https?:\/\/mega(\.co)?\.nz ]]; then 40 | URL="$1" 41 | fi 42 | 43 | if [[ ! $URL ]]; then 44 | echo "Usage: ${0##*/} url" >&2 45 | exit 1 46 | fi 47 | 48 | CURL="curl -Y 1 -y 9 -s" 49 | 50 | missing=false 51 | for cmd in openssl; do 52 | if [[ ! $(command -v "$cmd" 2>&1) ]]; then 53 | missing=true 54 | echo "${0##*/}: $cmd: command not found" >&2 55 | fi 56 | done 57 | if $missing; then 58 | exit 1 59 | fi 60 | 61 | id="${URL#*!}"; id="${id%%!*}" 62 | key="${URL##*!}" 63 | raw_hex=$(echo "${key}=" | tr '\-_' '+/' | tr -d ',' | base64 -d -i 2>/dev/null | od -v -An -t x1 | tr -d '\n ') 64 | hex=$(printf "%016x" \ 65 | $(( 0x${raw_hex:0:16} ^ 0x${raw_hex:32:16} )) \ 66 | $(( 0x${raw_hex:16:16} ^ 0x${raw_hex:48:16} )) 67 | ) 68 | 69 | json=$($CURL --header 'Content-Type: application/json' --data '[{"a":"g", "g":"1", "p":"'"$id"'"}]' 'https://g.api.mega.co.nz/cs?id=&ak=') || exit 1; json="${json#"[{"}"; json="${json%"}]"}" 70 | file_url="${json##*'"g":'}"; file_url="${file_url%%,*}"; file_url="${file_url//'"'/}" 71 | 72 | json=$($CURL --header 'Content-Type: application/json' --data '[{"a":"g", "p":"'"$id"'"}]' 'https://g.api.mega.co.nz/cs?id=&ak=') || exit 1 73 | at="${json##*'"at":'}"; at="${at%%,*}"; at="${at//'"'/}" 74 | file_size="${json##*'"s":'}'"; file_size="${file_size%%,*}"; file_size="${file_size//'"'/}" 75 | 76 | json=$(echo "${at}==" | tr '\-_' '+/' | tr -d ',' | openssl enc -a -A -d -aes-128-cbc -K "$hex" -iv "00000000000000000000000000000000" -nopad | tr -d '\0'); json="${json#"MEGA{"}"; json="${json%"}"}" 77 | file_name="${json##*'"n":'}" 78 | if [[ $file_name == *,* ]]; then 79 | file_name="${file_name%%,*}" 80 | fi 81 | file_name="${file_name//'"'/}" 82 | 83 | # $CURL "$file_url" | openssl enc -d -aes-128-ctr -K "$hex" -iv "${raw_hex:32:16}0000000000000000" > "$file_name" 84 | 85 | echo "{\"file_name\" : \"${file_name}\", \"file_size\" : \"$file_size\", \"url\" : \"${file_url}\", \"raw_hex\" : \"${raw_hex:32:16}0000000000000000\", \"hex\" : \"${hex}\"}" 86 | -------------------------------------------------------------------------------- /config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | orbs: 4 | python: circleci/python@0.2.1 5 | 6 | jobs: 7 | build-and-test: 8 | executor: python/default 9 | steps: 10 | - checkout 11 | - python/load-cache 12 | - python/install-deps 13 | - python/save-cache 14 | - run: 15 | command: ./manage.py test 16 | name: Test 17 | 18 | workflows: 19 | main: 20 | jobs: 21 | - build-and-test 22 | -------------------------------------------------------------------------------- /emptydir: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /gd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortifying/OUBnew/4bd421d606a22f99a5a0d599ba6327088cf1caa0/gd.png -------------------------------------------------------------------------------- /generate_session_file.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.b (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | # This script wont run your bot, it just generates a session. 7 | 8 | from telethon import TelegramClient 9 | from dotenv import load_dotenv 10 | import os 11 | 12 | load_dotenv("config.env") 13 | 14 | API_KEY = os.environ.get("API_KEY", None) 15 | API_HASH = os.environ.get("API_HASH", None) 16 | 17 | bot = TelegramClient("userbot", API_KEY, API_HASH) 18 | bot.start() 19 | -------------------------------------------------------------------------------- /heroku.yml: -------------------------------------------------------------------------------- 1 | build: 2 | docker: 3 | worker: Dockerfile 4 | run: 5 | worker: python3 -m userbot 6 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiohttp 2 | aria2p 3 | async_generator 4 | bs4 5 | cowpy 6 | covid 7 | REPO_LINK 8 | cryptg 9 | cffi>=1.0.0 10 | dnspython 11 | deezloader 12 | emoji 13 | gitpython 14 | google-api-python-client 15 | google-auth-oauthlib 16 | google_images_download 17 | heroku3 18 | googletrans==3.1.0a0 19 | gTTS 20 | gTTS-token 21 | hachoir 22 | google-auth-httplib2 23 | instantmusic 24 | google_images_download 25 | hachoir 26 | heroku3 27 | html_telegraph_poster 28 | httplib2 29 | instalooter 30 | humanize 31 | jikanpy 32 | js2py 33 | lottie 34 | lxml 35 | natsort 36 | oauth2client 37 | pendulum==2.0.5 38 | Pillow>=6.0.0 39 | psutil 40 | psycopg2 41 | psycopg2-binary 42 | pybase64 43 | pylast 44 | pySmartDL 45 | python-barcode 46 | python-dotenv 47 | PyGithub 48 | youtube-dl 49 | regex 50 | pytz 51 | qrcode 52 | requests 53 | rarfile 54 | git+https://github.com/Ncode2014/search-engine-parser 55 | selenium 56 | speedtest-cli 57 | sqlalchemy==1.3.23 58 | telethon 59 | telethon-session-sqlalchemy 60 | urbandict 61 | telethon-tgcrypto 62 | wikipedia 63 | coffeehouse 64 | telegraph 65 | pyfiglet 66 | base 67 | git+https://github.com/johnwmillr/LyricsGenius.git 68 | lyricsgenius 69 | redis 70 | beautifulsoup4 71 | wget 72 | python-dateutil 73 | bitlyshortener 74 | justwatch 75 | vcsi 76 | youtube_search 77 | colour 78 | -------------------------------------------------------------------------------- /sample_config.env: -------------------------------------------------------------------------------- 1 | # Remove this line first before doing anything 2 | ___________PLOX_______REMOVE_____THIS_____LINE__________=True 3 | 4 | # Get these from https://my.telegram.org 5 | API_KEY = "" 6 | API_HASH = "" 7 | 8 | # Get this value by running python3 string_session.py locally 9 | # You can also get it from http://sessiongen.kenhv.repl.run 10 | STRING_SESSION = "" 11 | 12 | # ChatID for the Log group 13 | # Add a hyphen or a negative sign before ID 14 | BOTLOG_CHATID = 0 # this is an integer, don't use quotes 15 | 16 | # Custom name for .alive 17 | ALIVE_NAME = None 18 | 19 | # PM Auto-Ban Feature Switch 20 | # AKA PMPermit 21 | PM_AUTO_BAN = "False" 22 | 23 | # Report or kick some known spammer bots after they join 24 | ANTI_SPAMBOT = "False" 25 | ANTI_SPAMBOT_SHOUT = "False" 26 | 27 | # Country and Time Zone setup for 28 | # .time and .date modules 29 | COUNTRY = "" 30 | TZ_NUMBER = 1 # this is an integer, please don't use quotes. 31 | 32 | # Clean welcome messages automatically 33 | # Needed only if you use userbot's welcome module 34 | CLEAN_WELCOME = "False" 35 | 36 | # APIs 37 | 38 | # OpenWeather Map API Key for .weather command 39 | # Get from https://openweathermap.org/ 40 | OPEN_WEATHER_MAP_APPID = "" 41 | WEATHER_DEFCITY = "" 42 | 43 | # OCR Space API Key for .ocr command 44 | # Get from https://ocr.space/ocrapi 45 | OCR_SPACE_API_KEY = "" 46 | 47 | # remove.bg API Key for .rbg command 48 | # Get from https://www.remove.bg/api 49 | REM_BG_API_KEY = "" 50 | 51 | # Google Drive Credentials 52 | # for gdrive module. 53 | # Get from https://console.cloud.google.com 54 | G_DRIVE_DATA = "" 55 | G_DRIVE_FOLDER_ID = "" 56 | G_DRIVE_INDEX_URL = "" 57 | 58 | # Last.fm 59 | # You have to have your own unique two values for API_KEY and API_SECRET 60 | # Obtain yours from https://www.last.fm/api/account/create for Last.fm 61 | LASTFM_API = None 62 | LASTFM_SECRET = None 63 | LASTFM_USERNAME = None # Your last.fm username 64 | LASTFM_PASSWORD = None # Your last.fm password 65 | # Bot will add before song name. For last.fm module. 66 | # Example: 67 | # GitHub: ender1324 : Skillet - Feel Invincible 68 | BIO_PREFIX = "" 69 | # Default bio message 70 | DEFAULT_BIO = "" 71 | 72 | # Don't change these unless you know what you're doing 73 | BOTLOG = "True" 74 | CONSOLE_LOGGER_VERBOSE = "False" 75 | LOGSPAMMER = "True" 76 | TEMP_DOWNLOAD_DIRECTORY = "./downloads/" 77 | ZIP_DOWNLOAD_DIRECTORY = "./zips" 78 | -------------------------------------------------------------------------------- /string_session.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # (c) https://t.me/TelethonChat/37677 and SpEcHiDe 3 | # 4 | # Licensed under the Raphielscape Public License, Version 1.d (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # 7 | 8 | from telethon.sync import TelegramClient 9 | from telethon.sessions import StringSession 10 | 11 | print( 12 | """Please go-to my.telegram.org 13 | Login using your Telegram account 14 | Click on API Development Tools 15 | 16 | Create a new application, by entering the required details 17 | Check your Telegram saved messages section to copy the STRING_SESSION""") 18 | API_KEY = int(input("Enter API_KEY here: ")) 19 | API_HASH = input("Enter API_HASH here: ") 20 | 21 | with TelegramClient(StringSession(), API_KEY, API_HASH) as client: 22 | print("Check your Telegram Saved Messages to copy the STRING_SESSION value") 23 | session_string = client.session.save() 24 | saved_messages_template = """Support: @userbotindo 25 | 26 | STRING_SESSION: {} 27 | 28 | ⚠️ Please be carefull to pass this value to third parties""".format(session_string) 29 | client.send_message("me", saved_messages_template, parse_mode="html") 30 | -------------------------------------------------------------------------------- /termux_install.sh: -------------------------------------------------------------------------------- 1 | clear 2 | echo -E " ******,*,. ... " 3 | echo -E " /////*****,*... . . " 4 | echo -E " . . /((//*/*,*///*. . .. " 5 | echo -E ".. . . .((*,,. .*//*. . . . .. " 6 | echo -E ". . ../(((**((//,,/.......... .. .. .. " 7 | echo -E ". . . ./(/, ., , . . ...... " 8 | echo -E "..,,.... .. .. . **//*/*/*.... . . ...*,. " 9 | echo -E " .,,,..,,,.,...... //((/. /**,. ... .. .....,*,** " 10 | echo -E " /(/(*,/// ..,,,,,,,.,,,,,,,,*, " 11 | echo -E ". ((((((/ ., . ..**** " 12 | echo -E "....... */(##//((/ ,.*, ..... .,,,*** " 13 | echo -E "......................../((##(((###( .,.,. ,.... . ,.,*/ " 14 | echo -E " ...*, *,,...,//(((((((####(((*,.**.. **, ,*/***((# " 15 | echo -E " *((/,***(((((((((####((//*/*,,**(//(//(//((((( " 16 | echo -E " .(/ ,(#((((###((((((((#((/(#(*(#/(*((/((((.*,(//// " 17 | echo -E " (((//(( (###(((((/(##(*/((.(#/##((((((/**(/(#*( " 18 | echo -E "/////**/ /((//,*,,../(/,((((/((#(##/(*(/#%#(((/(((/. *****/ " 19 | echo -E " .*////(/((/(/*,**/((((##((//.,####/((#(#%#(((((((/ , .**** " 20 | echo -E ". /(//(#( (#(#(*,/#(#/#####%##(((((((/(////*, " 21 | echo -E "........ ((/((#( /((#(((/ /((#/###%%%#(((/(((//////(( " 22 | echo -E "........./((#(#*.... ((,(((((# /((#((#%%%/* **((. . .., " 23 | echo -E "........./((#(/(.......((((((///(/*((#((%%%%%##(((,*/. , . " 24 | echo -E "........./((((((......*###(((/(/*(# ####%%%%#(.*((..,. " 25 | echo -E ".........((####(......(#(##.(#(((,*((.#%%%%##(*((/..,,*. " 26 | echo -E "//(/***,*(###(//,,..,///#/(. /(((/((((*#%%##(/(,,,.. " 27 | echo -E "**/**,,,,####(/**//((////(##(.*..*((/*##%%%(((,/ .,/ . " 28 | echo -E ",,,,,,,,,#####%(,*///////(((((/(((((((###%##//*., ,/. " 29 | echo -E ",,,,,,,,,#####%(,,,,///((((((///*.,.. (##((((#/(*///*.. " 30 | echo -E " " 31 | sleep 5 32 | clear 33 | 34 | pkg update && pkg upgrade -y 35 | pkg install clang curl git libcrypt libffi libiconv libjpeg* libjpeg-turbo libwebp libxml2 libxslt make ndk-sysroot openssl postgresql python readline wget zlib -y 36 | 37 | git clone https://github.com/mkaraniya/OpenUserBot.git 38 | cd OpenUserBot 39 | 40 | pip install --upgrade pip setuptools 41 | pip install -r requirements.txt 42 | 43 | mv sample_config.env config.env 44 | 45 | mkdir -p $PREFIX/var/lib/postgresql 46 | initdb $PREFIX/var/lib/postgresql 47 | pg_ctl -D $PREFIX/var/lib/postgresql start 48 | createdb botdb 49 | createuser botuser 50 | 51 | cd .. 52 | echo "pg_ctl -D $PREFIX/var/lib/postgresql start" > startbot.sh 53 | echo "cd OpenUserBot" >> startbot.sh 54 | echo "python3 -m userbot" >> startbot.sh 55 | chmod 755 startbot.sh 56 | 57 | echo "Done." 58 | echo "Now edit config.env with nano or anything you want, then run the userbot with startbot.sh" 59 | echo "Please edit the db to postgresql://botuser:@localhost:5432/botdb" 60 | echo "Good luck!" 61 | -------------------------------------------------------------------------------- /userbot/__main__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | """ Userbot start point """ 7 | 8 | from importlib import import_module 9 | from sys import argv 10 | 11 | from telethon.errors.rpcerrorlist import PhoneNumberInvalidError 12 | from userbot import LOGS, bot, OUBnew_VER, CODENAME 13 | from userbot.modules import ALL_MODULES 14 | 15 | VER = str(OUBnew_VER) 16 | 17 | INVALID_PH = ( 18 | "\nERROR: The Phone No. entered is INVALID" 19 | "\n Tip: Use Country Code along with number." 20 | "\n or check your phone number and try again !" 21 | ) 22 | 23 | try: 24 | bot.start() 25 | except PhoneNumberInvalidError: 26 | print(INVALID_PH) 27 | exit(1) 28 | 29 | for module_name in ALL_MODULES: 30 | imported_module = import_module("userbot.modules." + module_name) 31 | 32 | LOGS.info(f"You are running OUBnew-ftzr {CODENAME} v{VER}.\n") 33 | 34 | LOGS.info( 35 | "Congrats, your bot have successfully running\n" 36 | "To test your bot type .on or .live\n" 37 | "Don't forget to check update by typing .update! Have fun!" 38 | ) 39 | 40 | if len(argv) not in (1, 3, 4): 41 | bot.disconnect() 42 | else: 43 | bot.run_until_disconnected() 44 | -------------------------------------------------------------------------------- /userbot/modules/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | """ Init file which loads all of the modules """ 7 | from userbot import LOGS 8 | 9 | 10 | def __list_all_modules(): 11 | from os.path import dirname, basename, isfile 12 | import glob 13 | 14 | mod_paths = glob.glob(dirname(__file__) + "/*.py") 15 | return [ 16 | basename(f)[:-3] 17 | for f in mod_paths 18 | if isfile(f) and f.endswith(".py") and not f.endswith("__init__.py") 19 | ] 20 | 21 | 22 | ALL_MODULES = sorted(__list_all_modules()) 23 | LOGS.info("Modules to load: %s", str(ALL_MODULES)) 24 | __all__ = ALL_MODULES + ["ALL_MODULES"] 25 | -------------------------------------------------------------------------------- /userbot/modules/adzan.py: -------------------------------------------------------------------------------- 1 | import json 2 | import requests 3 | 4 | from userbot import CMD_HELP 5 | from userbot.events import register 6 | 7 | PLACE = "" 8 | 9 | 10 | @register(outgoing=True, pattern=r"^.adzan (.*)") 11 | async def get_adzan(adzan): 12 | await adzan.edit("🚛Loading...") 13 | if not adzan.pattern_match.group(1): 14 | LOCATION = PLACE 15 | if not LOCATION: 16 | await adzan.edit("Please specify a city or a state.") 17 | return 18 | else: 19 | LOCATION = adzan.pattern_match.group(1) 20 | 21 | # url = f'http://muslimsalat.com/{LOKASI}.json?key=bd099c5825cbedb9aa934e255a81a5fc' 22 | url = f"https://api.pray.zone/v2/times/today.json?city={LOCATION}" 23 | request = requests.get(url) 24 | if request.status_code == 500: 25 | return await adzan.edit(f"Couldn't find city `{LOCATION}`") 26 | 27 | parsed = json.loads(request.text) 28 | 29 | city = parsed["results"]["location"]["city"] 30 | country = parsed["results"]["location"]["country"] 31 | date = parsed["results"]["datetime"][0]["date"]["gregorian"] 32 | 33 | imsak = parsed["results"]["datetime"][0]["times"]["Imsak"] 34 | subuh = parsed["results"]["datetime"][0]["times"]["Fajr"] 35 | zuhur = parsed["results"]["datetime"][0]["times"]["Dhuhr"] 36 | ashar = parsed["results"]["datetime"][0]["times"]["Asr"] 37 | maghrib = parsed["results"]["datetime"][0]["times"]["Maghrib"] 38 | isya = parsed["results"]["datetime"][0]["times"]["Isha"] 39 | 40 | result = ( 41 | f"**Jadwal Sholat**:\n" 42 | f"📅 `{date}`\n" 43 | f"🌏 `{city} | {country}`\n\n" 44 | f"**Imsak :** `{imsak}`\n" 45 | f"**Subuh :** `{subuh}`\n" 46 | f"**Zuhur :** `{zuhur}`\n" 47 | f"**Ashar :** `{ashar}`\n" 48 | f"**Maghrib :** `{maghrib}`\n" 49 | f"**Isya :** `{isya}`\n" 50 | ) 51 | 52 | await adzan.edit(result) 53 | 54 | 55 | CMD_HELP.update( 56 | { 57 | "adzan": ">`.adzan` **city**\ 58 | \nUsage: Gets the prayer time for moslem." 59 | } 60 | ) 61 | -------------------------------------------------------------------------------- /userbot/modules/ariav2.py: -------------------------------------------------------------------------------- 1 | # ported to OUB by fortifying 2 | """ 3 | #command: .url 4 | 5 | """ 6 | import aria2p 7 | from telethon import events 8 | from userbot import LOGS, CMD_HELP 9 | from userbot.events import register 10 | import asyncio 11 | import os 12 | 13 | cmd = "aria2c --enable-rpc --rpc-listen-all=false --rpc-listen-port 6800 --max-connection-per-server=10 --rpc-max-request-size=1024M --seed-time=0.01 --min-split-size=10M --follow-torrent=mem --split=10 --daemon=true" 14 | 15 | aria2_is_running = os.system(cmd) 16 | 17 | aria2 = aria2p.API(aria2p.Client(host="http://localhost", port=6800, secret="")) 18 | 19 | 20 | @register(outgoing=True, pattern="^.url(?: |$)(.*)") 21 | async def magnet_download(event): 22 | if event.fwd_from: 23 | return 24 | var = event.text[5:] 25 | print(var) 26 | uris = [var] 27 | 28 | # Add URL Into Queue 29 | try: 30 | download = aria2.add_uris(uris, options=None, position=None) 31 | except Exception as e: 32 | await event.edit("`Error:\n`" + str(e)) 33 | return 34 | 35 | gid = download.gid 36 | complete = None 37 | while complete != True: 38 | file = aria2.get_download(gid) 39 | complete = file.is_complete 40 | try: 41 | msg = ( 42 | "⬛⬛⬛⬛⬛⬛⬛⬛⬛\n**Downloading File:** " 43 | + str(file.name) 44 | + "\n**Speed:** " 45 | + str(file.download_speed_string()) 46 | + "\n**Progress:** " 47 | + str(file.progress_string()) 48 | + "\n**Total Size:** " 49 | + str(file.total_length_string()) 50 | + "\n**ETA:** " 51 | + str(file.eta_string()) 52 | + "\n⬛⬛⬛⬛⬛⬛⬛⬛⬛\n\n" 53 | ) 54 | await event.edit(msg) 55 | await asyncio.sleep(10) 56 | except Exception as e: 57 | print(str(e)) 58 | await event.edit("**File Downloaded Successfully:** `{}`".format(file.name)) 59 | 60 | 61 | CMD_HELP.update( 62 | { 63 | "aria2": ".url [URL]\ 64 | \nUsage: Downloads the file into your userbot server storage.\ 65 | \nUsing ariav2." 66 | } 67 | ) 68 | -------------------------------------------------------------------------------- /userbot/modules/ascii.py: -------------------------------------------------------------------------------- 1 | # based on https://gist.github.com/wshanshan/c825efca4501a491447056849dd207d6 2 | # Ported for ProjectAlf by Alfiananda P.A 3 | 4 | import os 5 | import random 6 | 7 | import numpy as np 8 | from colour import Color 9 | from hachoir.metadata import extractMetadata 10 | from hachoir.parser import createParser 11 | from PIL import Image, ImageDraw, ImageFont 12 | from telethon.tl.types import DocumentAttributeFilename 13 | 14 | from userbot import CMD_HELP, bot 15 | from userbot.events import register 16 | 17 | bground = "black" 18 | 19 | 20 | @register(outgoing=True, pattern=r"^\.(ascii|asciis)$") 21 | async def ascii(event): 22 | if not event.reply_to_msg_id: 23 | await event.edit("`Reply to Any media..`") 24 | return 25 | reply_message = await event.get_reply_message() 26 | if not reply_message.media: 27 | await event.edit("`reply to a image/sticker/video`") 28 | return 29 | await event.edit("`Downloading Media..`") 30 | if reply_message.photo: 31 | IMG = await bot.download_media( 32 | reply_message, 33 | "ascii.png", 34 | ) 35 | elif ( 36 | DocumentAttributeFilename(file_name="AnimatedSticker.tgs") 37 | in reply_message.media.document.attributes 38 | ): 39 | await bot.download_media( 40 | reply_message, 41 | "ASCII.tgs", 42 | ) 43 | os.system("lottie_convert.py ASCII.tgs ascii.png") 44 | IMG = "ascii.png" 45 | elif reply_message.video: 46 | video = await bot.download_media( 47 | reply_message, 48 | "ascii.mp4", 49 | ) 50 | extractMetadata(createParser(video)) 51 | os.system("ffmpeg -i ascii.mp4 -vframes 1 -an -s 480x360 -ss 1 ascii.png") 52 | IMG = "ascii.png" 53 | else: 54 | IMG = await bot.download_media( 55 | reply_message, 56 | "ascii.png", 57 | ) 58 | try: 59 | await event.edit("`Processing..`") 60 | list = await random_color() 61 | color1 = list[0] 62 | color2 = list[1] 63 | bgcolor = bground 64 | await asciiart(IMG, color1, color2, bgcolor) 65 | cmd = event.pattern_match.group(1) 66 | if cmd == "asciis": 67 | os.system("cp ascii.png ascii.webp") 68 | ascii_file = "ascii.webp" 69 | else: 70 | ascii_file = "ascii.png" 71 | await event.client.send_file( 72 | event.chat_id, 73 | ascii_file, 74 | force_document=False, 75 | reply_to=event.reply_to_msg_id, 76 | ) 77 | await event.delete() 78 | os.system("rm *.png") 79 | os.system("rm *.webp") 80 | os.system("rm *.mp4") 81 | os.system("rm *.tgs") 82 | except BaseException as e: 83 | os.system("rm *.png") 84 | os.system("rm *.webp") 85 | os.system("rm *.mp4") 86 | os.system("rm *.tgs") 87 | return await event.edit(str(e)) 88 | 89 | 90 | async def asciiart(IMG, color1, color2, bgcolor): 91 | chars = np.asarray(list(" .,:irs?@9B&#")) 92 | font = ImageFont.load_default() 93 | letter_width = font.getsize("x")[0] 94 | letter_height = font.getsize("x")[1] 95 | WCF = letter_height / letter_width 96 | img = Image.open(IMG) 97 | widthByLetter = round(img.size[0] * 0.15 * WCF) 98 | heightByLetter = round(img.size[1] * 0.15) 99 | S = (widthByLetter, heightByLetter) 100 | img = img.resize(S) 101 | img = np.sum(np.asarray(img), axis=2) 102 | img -= img.min() 103 | img = (1.0 - img / img.max()) ** 2.2 * (chars.size - 1) 104 | lines = ("\n".join(("".join(r) for r in chars[img.astype(int)]))).split("\n") 105 | nbins = len(lines) 106 | colorRange = list(Color(color1).range_to(Color(color2), nbins)) 107 | newImg_width = letter_width * widthByLetter 108 | newImg_height = letter_height * heightByLetter 109 | newImg = Image.new("RGBA", (newImg_width, newImg_height), bgcolor) 110 | draw = ImageDraw.Draw(newImg) 111 | leftpadding = 0 112 | y = 0 113 | lineIdx = 0 114 | for line in lines: 115 | color = colorRange[lineIdx] 116 | lineIdx += 1 117 | draw.text((leftpadding, y), line, color.hex, font=font) 118 | y += letter_height 119 | IMG = newImg.save("ascii.png") 120 | return IMG 121 | 122 | 123 | # this is from userge 124 | async def random_color(): 125 | color = [ 126 | "#" + "".join([random.choice("0123456789ABCDEF") for k in range(6)]) 127 | for i in range(2) 128 | ] 129 | return color 130 | 131 | 132 | @register(outgoing=True, pattern=r"^\.asciibg(?: |$)(.*)") 133 | async def _(event): 134 | BG = event.pattern_match.group(1) 135 | if BG.isnumeric(): 136 | return await event.edit("`Please input a color not a number!`") 137 | elif BG: 138 | global bground 139 | bground = BG 140 | else: 141 | return await event.edit("`please insert bg of ascii`") 142 | await event.edit(f"`Successfully set bg of ascii to` **{BG}**") 143 | 144 | 145 | CMD_HELP.update( 146 | { 147 | "ascii": ">`.ascii`\n" 148 | "Usage: create ascii art from media\n\n" 149 | ">`.asciis`\n" 150 | "Usage: same but upload the result as sticker\n\n" 151 | ">`.asciibg `\n" 152 | "Usage: to change background color of this ascii module" 153 | } 154 | ) 155 | -------------------------------------------------------------------------------- /userbot/modules/blacklist.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.d (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | 6 | # port to userbot from uniborg by @keselekpermen69 7 | 8 | 9 | import asyncio 10 | import io 11 | import re 12 | import userbot.modules.sql_helper.blacklist_sql as sql 13 | from telethon import events, utils 14 | from telethon.tl import types, functions 15 | from userbot import CMD_HELP, bot 16 | from userbot.events import register 17 | 18 | 19 | @register(incoming=True, disable_edited=True, disable_errors=True) 20 | async def on_new_message(event): 21 | # TODO: exempt admins from locks 22 | name = event.raw_text 23 | snips = sql.get_chat_blacklist(event.chat_id) 24 | for snip in snips: 25 | pattern = r"( |^|[^\w])" + re.escape(snip) + r"( |$|[^\w])" 26 | if re.search(pattern, name, flags=re.IGNORECASE): 27 | try: 28 | await event.delete() 29 | except Exception as e: 30 | await event.reply("I do not have DELETE permission in this chat") 31 | await sleep(1) 32 | await reply.delete() 33 | sql.rm_from_blacklist(event.chat_id, snip.lower()) 34 | break 35 | 36 | 37 | @register(outgoing=True, pattern="^.addbl(?: |$)(.*)") 38 | async def on_add_black_list(addbl): 39 | text = addbl.pattern_match.group(1) 40 | to_blacklist = list( 41 | {trigger.strip() for trigger in text.split("\n") if trigger.strip()} 42 | ) 43 | 44 | for trigger in to_blacklist: 45 | sql.add_to_blacklist(addbl.chat_id, trigger.lower()) 46 | await addbl.edit( 47 | "`Added` **{}** `to the blacklist in the current chat`".format(text) 48 | ) 49 | 50 | 51 | @register(outgoing=True, pattern="^.listbl(?: |$)(.*)") 52 | async def on_view_blacklist(listbl): 53 | all_blacklisted = sql.get_chat_blacklist(listbl.chat_id) 54 | OUT_STR = "Blacklists in the Current Chat:\n" 55 | if len(all_blacklisted) > 0: 56 | for trigger in all_blacklisted: 57 | OUT_STR += f"`{trigger}`\n" 58 | else: 59 | OUT_STR = "`There are no blacklist in current chat.`" 60 | if len(OUT_STR) > 4096: 61 | with io.BytesIO(str.encode(OUT_STR)) as out_file: 62 | out_file.name = "blacklist.text" 63 | await listbl.client.send_file( 64 | listbl.chat_id, 65 | out_file, 66 | force_document=True, 67 | allow_cache=False, 68 | caption="BlackLists in the Current Chat", 69 | reply_to=listbl, 70 | ) 71 | await listbl.delete() 72 | else: 73 | await listbl.edit(OUT_STR) 74 | 75 | 76 | @register(outgoing=True, pattern="^.rmbl(?: |$)(.*)") 77 | async def on_delete_blacklist(rmbl): 78 | text = rmbl.pattern_match.group(1) 79 | to_unblacklist = list( 80 | {trigger.strip() for trigger in text.split("\n") if trigger.strip()} 81 | ) 82 | 83 | successful = 0 84 | for trigger in to_unblacklist: 85 | if sql.rm_from_blacklist(rmbl.chat_id, trigger.lower()): 86 | successful += 1 87 | if not successful: 88 | await rmbl.edit("`Blacklist` **{}** `doesn't exist.`".format(text)) 89 | else: 90 | await rmbl.edit("`Blacklist` **{}** `was deleted successfully`".format(text)) 91 | 92 | 93 | CMD_HELP.update( 94 | { 95 | "blacklist": ".listbl\ 96 | \nUsage: Lists all active userbot blacklist in a chat.\ 97 | \n\n.addbl \ 98 | \nUsage: Saves the message to the 'blacklist keyword'.\ 99 | \nThe bot will delete to the message whenever 'blacklist keyword' is mentioned.\ 100 | \n\n.rmbl \ 101 | \nUsage: Stops the specified blacklist." 102 | } 103 | ) 104 | -------------------------------------------------------------------------------- /userbot/modules/covid.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.d (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | # Port to UserBot by @MoveAngel 7 | 8 | from covid import Covid 9 | from userbot import CMD_HELP 10 | from userbot.events import register 11 | 12 | 13 | @register(outgoing=True, pattern="^.covid (.*)") 14 | async def corona(event): 15 | await event.edit("`Processing...`") 16 | country = event.pattern_match.group(1) 17 | covid = Covid(source="worldometers") 18 | try: 19 | country_data = covid.get_status_by_country_name(country) 20 | output_text = ( 21 | f"`Confirmed : {country_data['confirmed']}`\n" 22 | + f"`Active : {country_data['active']}`\n" 23 | + f"`Deaths : {country_data['deaths']}`\n" 24 | + f"`Recovered : {country_data['recovered']}`\n\n" 25 | + f"`New Cases : {country_data['new_cases']}`\n" 26 | + f"`New Deaths : {country_data['new_deaths']}`\n" 27 | + f"`Critical : {country_data['critical']}`\n" 28 | + f"`Total Tests : {country_data['total_tests']}`\n\n" 29 | + f"Data provided by [Worldometer](https://www.worldometers.info/coronavirus/country/{country})" 30 | ) 31 | await event.edit(f"Corona Virus Info in {country}:\n\n{output_text}") 32 | except ValueError: 33 | await event.edit( 34 | f"No information found for: {country}!\nCheck your spelling and try again." 35 | ) 36 | 37 | 38 | CMD_HELP.update( 39 | { 40 | "covid": ".covid " 41 | "\nUsage: Get an information about data covid-19 in your country.\n" 42 | } 43 | ) 44 | -------------------------------------------------------------------------------- /userbot/modules/crbn.py: -------------------------------------------------------------------------------- 1 | from userbot import CMD_HELP 2 | 3 | CMD_HELP.update( 4 | { 5 | "carbon": "`.carbon` [or reply]\ 6 | \nUsage: Beautify your text\ 7 | \n(Grey background)\ 8 | \n\n`.carbon2` [or reply]\ 9 | \nUsage: Beautify your text\ 10 | \n(Purple text)\ 11 | \n\n`.carbon3` [or reply]\ 12 | \nUsage: Beautify your text.\ 13 | \n(Light Panel, Red Background)\ 14 | \n\n`.carbon4` [or reply]\ 15 | \nUsage: Beautify your text.\ 16 | \n(Dark Panel, Blue Background)\ 17 | \n\n`.carbon5` [or reply]\ 18 | \nUsage: Beautify your text.\ 19 | \n(Light Panel, Blue Background)\ 20 | " 21 | } 22 | ) 23 | -------------------------------------------------------------------------------- /userbot/modules/create.py: -------------------------------------------------------------------------------- 1 | # this module original created by @spechide 2 | # port to userbot by @afdulfauzan 3 | 4 | from telethon.tl import functions, types 5 | from userbot.events import register 6 | from userbot import CMD_HELP 7 | 8 | 9 | @register(outgoing=True, pattern="^.create (b|g|c)(?: |$)(.*)") 10 | async def telegraphs(grop): 11 | """ For .create command, Creating New Group & Channel """ 12 | if grop.text[0].isalpha() or grop.text[0] in ("/", "#", "@", "!"): 13 | return 14 | if grop.fwd_from: 15 | return 16 | type_of_group = grop.pattern_match.group(1) 17 | group_name = grop.pattern_match.group(2) 18 | if type_of_group == "b": 19 | try: 20 | result = await grop.client( 21 | functions.messages.CreateChatRequest( # pylint:disable=E0602 22 | users=["@EmiliaHikariBot"], 23 | # Not enough users (to create a chat, for example) 24 | # Telegram, no longer allows creating a chat with ourselves 25 | title=group_name, 26 | ) 27 | ) 28 | created_chat_id = result.chats[0].id 29 | await grop.client( 30 | functions.messages.DeleteChatUserRequest( 31 | chat_id=created_chat_id, user_id="@EmiliaHikariBot" 32 | ) 33 | ) 34 | result = await grop.client( 35 | functions.messages.ExportChatInviteRequest(peer=created_chat_id,) 36 | ) 37 | await grop.edit( 38 | "Your `{}` Group Created Successfully. Click [{}]({}) to join".format( 39 | group_name, group_name, result.link 40 | ) 41 | ) 42 | except Exception as e: # pylint:disable=C0103,W0703 43 | await grop.edit(str(e)) 44 | elif type_of_group in ["g", "c"]: 45 | try: 46 | r = await grop.client( 47 | functions.channels.CreateChannelRequest( # pylint:disable=E0602 48 | title=group_name, 49 | about="Welcome to this Channel", 50 | megagroup=False if type_of_group == "c" else True, 51 | ) 52 | ) 53 | created_chat_id = r.chats[0].id 54 | result = await grop.client( 55 | functions.messages.ExportChatInviteRequest(peer=created_chat_id,) 56 | ) 57 | await grop.edit( 58 | "Your `{}` Group/Channel Created Successfully. Click [{}]({}) to join".format( 59 | group_name, group_name, result.link 60 | ) 61 | ) 62 | except Exception as e: # pylint:disable=C0103,W0703 63 | await grop.edit(str(e)) 64 | 65 | 66 | CMD_HELP.update( 67 | { 68 | "create": "\ 69 | Create\ 70 | \nUsage: Create Channel, Group & Group With Bot.\ 71 | \n\n.create g \ 72 | \nUsage: Create a Private Group.\ 73 | \n\n.create b \ 74 | \nUsage: Create a Group with Bot.\ 75 | \n\n.create c \ 76 | \nUsage: Create a Channel.\ 77 | " 78 | } 79 | ) 80 | -------------------------------------------------------------------------------- /userbot/modules/deepfryer.py: -------------------------------------------------------------------------------- 1 | import os 2 | from telethon.errors.rpcerrorlist import YouBlockedUserError 3 | 4 | from userbot.events import register 5 | from userbot import bot, TEMP_DOWNLOAD_DIRECTORY, CMD_HELP 6 | 7 | 8 | @register(outgoing=True, pattern=r"^.df(:? |$)(\d)?") 9 | async def _(fry): 10 | await fry.edit("`Sending information...`") 11 | level = fry.pattern_match.group(2) 12 | if fry.fwd_from: 13 | return 14 | if not fry.reply_to_msg_id: 15 | await fry.edit("`Reply to any user message photo...`") 16 | return 17 | reply_message = await fry.get_reply_message() 18 | if not reply_message.media: 19 | await fry.edit("`No image found to fry...`") 20 | return 21 | if reply_message.sender.bot: 22 | await fry.edit("`Reply to actual user...`") 23 | return 24 | chat = "@image_deepfrybot" 25 | message_id_to_reply = fry.message.reply_to_msg_id 26 | async with fry.client.conversation(chat) as conv: 27 | try: 28 | msg = await conv.send_message(reply_message) 29 | if level: 30 | m = f"/deepfry {level}" 31 | msg_level = await conv.send_message(m, reply_to=msg.id) 32 | r = await conv.get_response() 33 | response = await conv.get_response() 34 | """ - don't spam notif - """ 35 | await bot.send_read_acknowledge(conv.chat_id) 36 | except YouBlockedUserError: 37 | await fry.reply("`Please unblock` @image_deepfrybot`...`") 38 | return 39 | if response.text.startswith("Forward"): 40 | await fry.edit("`Please disable your forward privacy setting...`") 41 | else: 42 | downloaded_file_name = await fry.client.download_media( 43 | response.media, TEMP_DOWNLOAD_DIRECTORY 44 | ) 45 | await fry.client.send_file( 46 | fry.chat_id, 47 | downloaded_file_name, 48 | force_document=False, 49 | reply_to=message_id_to_reply, 50 | ) 51 | """ - cleanup chat after completed - """ 52 | try: 53 | msg_level 54 | except NameError: 55 | await fry.client.delete_messages(conv.chat_id, [msg.id, response.id]) 56 | else: 57 | await fry.client.delete_messages( 58 | conv.chat_id, [msg.id, response.id, r.id, msg_level.id] 59 | ) 60 | await fry.delete() 61 | return os.remove(downloaded_file_name) 62 | 63 | 64 | CMD_HELP.update( 65 | { 66 | "deepfry": ">`.df` or >`.df [level(1-8)]`" 67 | "\nUsage: deepfry image/sticker from the reply." 68 | "\n@image_deepfrybot" 69 | } 70 | ) 71 | -------------------------------------------------------------------------------- /userbot/modules/figlet.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.d (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | 7 | import pyfiglet 8 | from userbot import CMD_HELP 9 | from userbot.events import register 10 | 11 | 12 | @register(outgoing=True, pattern="^\.figlet(?: |$)(.*)") 13 | async def figlet(e): 14 | if e.fwd_from: 15 | return 16 | CMD_FIG = { 17 | "slant": "slant", 18 | "3D": "3-d", 19 | "5line": "5lineoblique", 20 | "alpha": "alphabet", 21 | "banner": "banner3-D", 22 | "doh": "doh", 23 | "iso": "isometric1", 24 | "letter": "letters", 25 | "allig": "alligator", 26 | "dotm": "dotmatrix", 27 | "bubble": "bubble", 28 | "bulb": "bulbhead", 29 | "digi": "digital", 30 | } 31 | input_str = e.pattern_match.group(1) 32 | if "." in input_str: 33 | text, cmd = input_str.split(".", maxsplit=1) 34 | elif input_str is not None: 35 | cmd = None 36 | text = input_str 37 | else: 38 | await e.edit("`Please add some text to figlet`") 39 | return 40 | if cmd is not None: 41 | try: 42 | font = CMD_FIG[cmd] 43 | except KeyError: 44 | await e.edit("`Invalid selected font.`") 45 | return 46 | result = pyfiglet.figlet_format(text, font=font) 47 | else: 48 | result = pyfiglet.figlet_format(text) 49 | await e.respond("‌‌‎`{}`".format(result)) 50 | await e.delete() 51 | 52 | 53 | CMD_HELP.update( 54 | { 55 | "figlet": ">`.figlet`" 56 | "\nUsage: Enhance ur text to strip line with anvil." 57 | "\n\nExample: `.figlet TEXT.STYLE`" 58 | "\nSTYLE LIST: `slant`, `3D`, `5line`, `alpha`, `banner`, `doh`, `iso`, `letter`, `allig`, `dotm`, `bubble`, `bulb`, `digi`" 59 | } 60 | ) 61 | -------------------------------------------------------------------------------- /userbot/modules/gban.py: -------------------------------------------------------------------------------- 1 | """Globally Ban users from all the 2 | Group Administrations bots where you are SUDO 3 | Available Commands: 4 | .gban REASON 5 | .ungban REASON""" 6 | from telethon import events 7 | import asyncio 8 | from userbot.events import register 9 | from userbot import bot, CMD_HELP, G_BAN_LOGGER_GROUP, ALIVE_NAME 10 | 11 | # imported from uniborg by @heyworld 12 | 13 | # ================= CONSTANT ================= 14 | DEFAULTUSER = str(ALIVE_NAME) if ALIVE_NAME else uname().node 15 | # ============================================ 16 | 17 | 18 | @register(outgoing=True, pattern="^.gban(?: |$)(.*)") 19 | async def _(event): 20 | if G_BAN_LOGGER_GROUP is None: 21 | await event.edit("ENV VAR is not set. This module will not work.") 22 | return 23 | if event.fwd_from: 24 | return 25 | reason = event.pattern_match.group(1) 26 | if event.reply_to_msg_id: 27 | r = await event.get_reply_message() 28 | r_from_id = r.forward.from_id or r.from_id if r.forward else r.from_id 29 | await bot.send_message( 30 | G_BAN_LOGGER_GROUP, 31 | "/gban [user](tg://user?id={}) {}".format(r_from_id, reason), 32 | ) 33 | await event.delete() 34 | await event.reply("`gbanning...`") 35 | asyncio.sleep(3.5) 36 | await event.reply(f"**user gbanned by** `{DEFAULTUSER} `") 37 | 38 | 39 | @register(outgoing=True, pattern="^.ungban(?: |$)(.*)") 40 | async def _(event): 41 | if G_BAN_LOGGER_GROUP is None: 42 | await event.edit("ENV VAR is not set. This module will not work.") 43 | return 44 | if event.fwd_from: 45 | return 46 | reason = event.pattern_match.group(1) 47 | if event.reply_to_msg_id: 48 | r = await event.get_reply_message() 49 | r_from_id = r.from_id 50 | await bot.send_message( 51 | G_BAN_LOGGER_GROUP, 52 | "/ungban [user](tg://user?id={}) {}".format(r_from_id, reason), 53 | ) 54 | await event.delete() 55 | await event.reply("`ungbanning...`") 56 | asyncio.sleep(3.5) 57 | await event.reply(f"**user ungbanned by** `{DEFAULTUSER} `") 58 | 59 | 60 | CMD_HELP.update( 61 | { 62 | "gban": "\ 63 | `.gban reason`\ 64 | \nUsage: Globally Ban users from all the Group Administrations bots where you are SUDO.\ 65 | \n\n`.ungban reason`\ 66 | \nUsage: Globally unBan users from all the Group Administrations bots where you are SUDO" 67 | } 68 | ) 69 | -------------------------------------------------------------------------------- /userbot/modules/getmusic.py: -------------------------------------------------------------------------------- 1 | # AnggaR96s 2 | 3 | from telethon import events 4 | import subprocess 5 | from telethon.errors.rpcerrorlist import YouBlockedUserError 6 | import asyncio 7 | from userbot.events import register 8 | from userbot import bot, CMD_HELP 9 | import glob 10 | import os 11 | 12 | os.system("rm -rf *.mp3") 13 | 14 | 15 | def bruh(name): 16 | os.system("instantmusic -q -s " + name) 17 | 18 | 19 | @register(outgoing=True, pattern=r"^.song (.*)") 20 | async def _(event): 21 | if event.fwd_from: 22 | return 23 | cmd = event.pattern_match.group(1) 24 | reply_to_id = event.message.id 25 | if event.reply_to_msg_id: 26 | reply_to_id = event.reply_to_msg_id 27 | await event.edit("`Ok finding the song..`") 28 | bruh(str(cmd)) 29 | l = glob.glob("*.mp3") 30 | loa = l[0] 31 | await event.edit("`Sending song..`") 32 | await event.client.send_file( 33 | event.chat_id, 34 | loa, 35 | force_document=True, 36 | allow_cache=False, 37 | caption=cmd, 38 | reply_to=reply_to_id, 39 | ) 40 | os.system("rm -rf *.mp3") 41 | subprocess.check_output("rm -rf *.mp3", shell=True) 42 | await event.delete() 43 | 44 | 45 | @register(outgoing=True, pattern="^.smd(?: |$)(.*)") 46 | async def _(event): 47 | if event.fwd_from: 48 | return 49 | link = event.pattern_match.group(1) 50 | chat = "@SpotifyMusicDownloaderBot" 51 | await event.edit("```Getting Your Music```") 52 | async with bot.conversation(chat) as conv: 53 | await asyncio.sleep(2) 54 | await event.edit("`Downloading music taking some times, Stay Tuned.....`") 55 | try: 56 | response = conv.wait_event( 57 | events.NewMessage(incoming=True, from_users=752979930) 58 | ) 59 | await bot.send_message(chat, link) 60 | respond = await response 61 | await bot.send_read_acknowledge(conv.chat_id) 62 | except YouBlockedUserError: 63 | await event.reply( 64 | "```Please unblock @SpotifyMusicDownloaderBot and try again```" 65 | ) 66 | return 67 | await event.delete() 68 | await bot.forward_messages(event.chat_id, respond.message) 69 | await bot.send_read_acknowledge(event.chat_id) 70 | 71 | 72 | CMD_HELP.update( 73 | { 74 | "song": ">`.song` **atrist title**" 75 | "\nUsage: Finding and uploading song.\n" 76 | ">`.smd` ****" 77 | "\nUsage: **Download music from spotify**" 78 | } 79 | ) 80 | -------------------------------------------------------------------------------- /userbot/modules/github.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.d (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | 7 | import aiohttp 8 | import asyncio 9 | import os 10 | import time 11 | from github import Github 12 | from datetime import datetime 13 | from telethon import events 14 | from telethon.tl.types import DocumentAttributeVideo 15 | from userbot.events import register 16 | from userbot import CMD_HELP, GITHUB_ACCESS_TOKEN, GIT_REPO_NAME, bot 17 | 18 | GIT_TEMP_DIR = "./userbot/temp/" 19 | 20 | 21 | @register(outgoing=True, disable_errors=True, pattern="^.git(?: |$)(.*)") 22 | async def github(event): 23 | username = event.pattern_match.group(1) 24 | URL = f"https://api.github.com/users/{username}" 25 | chat = await event.get_chat() 26 | async with aiohttp.ClientSession() as session: 27 | async with session.get(URL) as request: 28 | if request.status == 404: 29 | return await event.reply(f"`{username} not found`") 30 | 31 | result = await request.json() 32 | 33 | url = result.get("html_url", None) 34 | name = result.get("name", None) 35 | company = result.get("company", None) 36 | bio = result.get("bio", None) 37 | created_at = result.get("created_at", "Not Found") 38 | 39 | REPLY = ( 40 | f"GitHub Info for `{username}`\n" 41 | f"Username: `{name}`\n" 42 | f"Bio: `{bio}`\n" 43 | f"URL: {url}\n" 44 | f"Company: `{company}`\n" 45 | f"Created at: `{created_at}`\n" 46 | f"More info : [Here](https://api.github.com/users/{username}/events/public)" 47 | ) 48 | 49 | if not result.get("repos_url", None): 50 | return await event.edit(REPLY) 51 | async with session.get(result.get("repos_url", None)) as request: 52 | result = request.json 53 | if request.status == 404: 54 | return await event.edit(REPLY) 55 | 56 | result = await request.json() 57 | 58 | REPLY += "\nRepos:\n" 59 | 60 | for nr in range(len(result)): 61 | REPLY += f"[{result[nr].get('name', None)}]({result[nr].get('html_url', None)})\n" 62 | 63 | await event.edit(REPLY) 64 | 65 | 66 | @register(outgoing=True, pattern="^.commit(?: |$)(.*)") 67 | async def download(event): 68 | if event.fwd_from: 69 | return 70 | if GITHUB_ACCESS_TOKEN is None: 71 | await event.edit("`Please ADD Proper Access Token from github.com`") 72 | return 73 | if GIT_REPO_NAME is None: 74 | await event.edit("`Please ADD Proper Github Repo Name of your userbot`") 75 | return 76 | mone = await event.reply("Processing ...") 77 | if not os.path.isdir(GIT_TEMP_DIR): 78 | os.makedirs(GIT_TEMP_DIR) 79 | start = datetime.now() 80 | reply_message = await event.get_reply_message() 81 | try: 82 | c_time = time.time() 83 | print("Downloading to TEMP directory") 84 | downloaded_file_name = await bot.download_media( 85 | reply_message.media, GIT_TEMP_DIR 86 | ) 87 | except Exception as e: 88 | await mone.edit(str(e)) 89 | else: 90 | end = datetime.now() 91 | ms = (end - start).seconds 92 | await event.delete() 93 | await mone.edit( 94 | "Downloaded to `{}` in {} seconds.".format(downloaded_file_name, ms) 95 | ) 96 | await mone.edit("Committing to Github....") 97 | await git_commit(downloaded_file_name, mone) 98 | 99 | 100 | async def git_commit(file_name, mone): 101 | content_list = [] 102 | access_token = GITHUB_ACCESS_TOKEN 103 | g = Github(access_token) 104 | file = open(file_name, "r", encoding="utf-8") 105 | commit_data = file.read() 106 | repo = g.get_repo(GIT_REPO_NAME) 107 | print(repo.name) 108 | create_file = True 109 | contents = repo.get_contents("") 110 | for content_file in contents: 111 | content_list.append(str(content_file)) 112 | print(content_file) 113 | for i in content_list: 114 | create_file = True 115 | if i == 'ContentFile(path="' + file_name + '")': 116 | return await mone.edit("`File Already Exists`") 117 | create_file = False 118 | file_name = "userbot/modules/" + file_name 119 | if create_file == True: 120 | file_name = file_name.replace("./userbot/temp/", "") 121 | print(file_name) 122 | try: 123 | repo.create_file( 124 | file_name, "Uploaded New Plugin", commit_data, branch="sql-extended" 125 | ) 126 | print("Committed File") 127 | ccess = GIT_REPO_NAME 128 | ccess = ccess.strip() 129 | await mone.edit( 130 | f"`Commited On Your Github Repo`\n\n[Your Modules](https://github.com/{ccess}/tree/sql-extended/userbot/modules/)" 131 | ) 132 | except: 133 | print("Cannot Create Plugin") 134 | await mone.edit("Cannot Upload Plugin") 135 | else: 136 | return await mone.edit("`Committed Suicide`") 137 | 138 | 139 | CMD_HELP.update( 140 | { 141 | "github": ">`.git` " 142 | "\nUsage: Like .whois but for GitHub usernames." 143 | "\n\n>`.commit` " 144 | "\nUsage: GITHUB File Uploader Plugin for userbot. Heroku Automation should be Enabled." 145 | } 146 | ) 147 | -------------------------------------------------------------------------------- /userbot/modules/hash.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | """ Userbot module containing hash and encode/decode commands. """ 7 | 8 | from subprocess import PIPE 9 | from subprocess import run as runapp 10 | import pybase64 11 | from userbot import CMD_HELP 12 | from userbot.events import register 13 | 14 | 15 | @register(outgoing=True, pattern="^.hash (.*)") 16 | async def gethash(hash_q): 17 | """ For .hash command, find the md5, sha1, sha256, sha512 of the string. """ 18 | hashtxt_ = hash_q.pattern_match.group(1) 19 | hashtxt = open("hashdis.txt", "w+") 20 | hashtxt.write(hashtxt_) 21 | hashtxt.close() 22 | md5 = runapp(["md5sum", "hashdis.txt"], stdout=PIPE) 23 | md5 = md5.stdout.decode() 24 | sha1 = runapp(["sha1sum", "hashdis.txt"], stdout=PIPE) 25 | sha1 = sha1.stdout.decode() 26 | sha256 = runapp(["sha256sum", "hashdis.txt"], stdout=PIPE) 27 | sha256 = sha256.stdout.decode() 28 | sha512 = runapp(["sha512sum", "hashdis.txt"], stdout=PIPE) 29 | runapp(["rm", "hashdis.txt"], stdout=PIPE) 30 | sha512 = sha512.stdout.decode() 31 | ans = ( 32 | "Text: `" 33 | + hashtxt_ 34 | + "`\nMD5: `" 35 | + md5 36 | + "`SHA1: `" 37 | + sha1 38 | + "`SHA256: `" 39 | + sha256 40 | + "`SHA512: `" 41 | + sha512[:-1] 42 | + "`" 43 | ) 44 | if len(ans) > 4096: 45 | hashfile = open("hashes.txt", "w+") 46 | hashfile.write(ans) 47 | hashfile.close() 48 | await hash_q.client.send_file( 49 | hash_q.chat_id, 50 | "hashes.txt", 51 | reply_to=hash_q.id, 52 | caption="`It's too big, sending a text file instead. `", 53 | ) 54 | runapp(["rm", "hashes.txt"], stdout=PIPE) 55 | else: 56 | await hash_q.reply(ans) 57 | 58 | 59 | @register(outgoing=True, pattern="^.base64 (en|de) (.*)") 60 | async def endecrypt(query): 61 | """ For .base64 command, find the base64 encoding of the given string. """ 62 | if query.pattern_match.group(1) == "en": 63 | lething = str(pybase64.b64encode(bytes(query.pattern_match.group(2), "utf-8")))[ 64 | 2: 65 | ] 66 | await query.reply("Encoded: `" + lething[:-1] + "`") 67 | else: 68 | lething = str( 69 | pybase64.b64decode( 70 | bytes(query.pattern_match.group(2), "utf-8"), validate=True 71 | ) 72 | )[2:] 73 | await query.reply("Decoded: `" + lething[:-1] + "`") 74 | 75 | 76 | CMD_HELP.update({"base64": "Find the base64 encoding of the given string"}) 77 | 78 | CMD_HELP.update( 79 | { 80 | "hash": "Find the md5, sha1, sha256, sha512 of the string when written into a txt file." 81 | } 82 | ) 83 | -------------------------------------------------------------------------------- /userbot/modules/hazmat.py: -------------------------------------------------------------------------------- 1 | # Based Code by @adekmaulana 2 | # Improve by @aidilaryanto 3 | # 4 | # 5 | import os 6 | from telethon.errors.rpcerrorlist import YouBlockedUserError 7 | from userbot.events import register 8 | from userbot import bot, TEMP_DOWNLOAD_DIRECTORY, CMD_HELP 9 | 10 | 11 | @register(outgoing=True, pattern=r"^.hz(:? |$)(.*)?") 12 | async def _(hazmat): 13 | await hazmat.edit("`Sending information...`") 14 | level = hazmat.pattern_match.group(2) 15 | if hazmat.fwd_from: 16 | return 17 | if not hazmat.reply_to_msg_id: 18 | await hazmat.edit("`WoWoWo Capt!, we are not going suit a ghost!...`") 19 | return 20 | reply_message = await hazmat.get_reply_message() 21 | if not reply_message.media: 22 | await hazmat.edit("`Word can destroy anything Capt!...`") 23 | return 24 | chat = "@hazmat_suit_bot" 25 | await hazmat.edit("```Suit Up Capt!, We are going to purge some virus...```") 26 | message_id_to_reply = hazmat.message.reply_to_msg_id 27 | msg_reply = None 28 | async with hazmat.client.conversation(chat) as conv: 29 | try: 30 | msg = await conv.send_message(reply_message) 31 | if level: 32 | m = f"/hazmat {level}" 33 | msg_reply = await conv.send_message(m, reply_to=msg.id) 34 | r = await conv.get_response() 35 | elif reply_message.gif: 36 | m = "/hazmat" 37 | msg_reply = await conv.send_message(m, reply_to=msg.id) 38 | r = await conv.get_response() 39 | response = await conv.get_response() 40 | """ - don't spam notif - """ 41 | await bot.send_read_acknowledge(conv.chat_id) 42 | except YouBlockedUserError: 43 | await hazmat.reply("`Please unblock` @hazmat_suit_bot`...`") 44 | return 45 | if response.text.startswith("I can't"): 46 | await hazmat.edit("`Can't handle this GIF...`") 47 | await hazmat.client.delete_messages( 48 | conv.chat_id, [msg.id, response.id, r.id, msg_reply.id] 49 | ) 50 | return 51 | else: 52 | downloaded_file_name = await hazmat.client.download_media( 53 | response.media, TEMP_DOWNLOAD_DIRECTORY 54 | ) 55 | await hazmat.client.send_file( 56 | hazmat.chat_id, 57 | downloaded_file_name, 58 | force_document=False, 59 | reply_to=message_id_to_reply, 60 | ) 61 | """ - cleanup chat after completed - """ 62 | if msg_reply is not None: 63 | await hazmat.client.delete_messages( 64 | conv.chat_id, [msg.id, msg_reply.id, r.id, response.id] 65 | ) 66 | else: 67 | await hazmat.client.delete_messages(conv.chat_id, [msg.id, response.id]) 68 | await hazmat.delete() 69 | return os.remove(downloaded_file_name) 70 | 71 | 72 | CMD_HELP.update( 73 | { 74 | "hazmat": ">`.hz` or >`.hz [flip, x2, rotate (degree), background (number), black]`" 75 | "\nUsage: Reply to a image / sticker to suit up!" 76 | } 77 | ) 78 | -------------------------------------------------------------------------------- /userbot/modules/help.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.d (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | """ Userbot help command """ 7 | 8 | from userbot import CMD_HELP 9 | from userbot.events import register 10 | 11 | 12 | @register(outgoing=True, pattern="^.help(?: |$)(.*)") 13 | async def help(event): 14 | """ For .help command,""" 15 | args = event.pattern_match.group(1).lower() 16 | # Prevent Channel Bug to get any information and commad from all modules 17 | if event.is_channel and not event.is_group: 18 | await event.edit("`Help Commad isn't permitted on channels`") 19 | return 20 | if args: 21 | if args in CMD_HELP: 22 | await event.edit(str(CMD_HELP[args])) 23 | else: 24 | await event.edit("Please specify a valid module name.") 25 | else: 26 | string = "**List of all loaded module(s)**\n\ 27 | \nSpecify which module do you want help for! \ 28 | \n**Usage:** `.help` \n\n" 29 | for i in CMD_HELP: 30 | string += "`" + str(i) 31 | string += "`\t\t\t•\t\t\t " 32 | await event.edit(f"{string[:-5]}") 33 | -------------------------------------------------------------------------------- /userbot/modules/invite.py: -------------------------------------------------------------------------------- 1 | from asyncio import sleep 2 | from telethon import functions 3 | from userbot import CMD_HELP 4 | from userbot.events import register 5 | 6 | 7 | @register(outgoing=True, pattern="^.invite(?: |$)(.*)") 8 | async def _(event): 9 | if event.fwd_from: 10 | return 11 | to_add_users = event.pattern_match.group(1) 12 | if event.is_private: 13 | await event.edit("`.invite` users to a chat, not to a Private Message") 14 | else: 15 | if not event.is_channel and event.is_group: 16 | # https://lonamiwebs.github.io/Telethon/methods/messages/add_chat_user.html 17 | for user_id in to_add_users.split(" "): 18 | try: 19 | await event.client( 20 | functions.messages.AddChatUserRequest( 21 | chat_id=event.chat_id, user_id=user_id, fwd_limit=1000000 22 | ) 23 | ) 24 | except Exception as e: 25 | await event.edit(str(e)) 26 | return 27 | else: 28 | # https://lonamiwebs.github.io/Telethon/methods/channels/invite_to_channel.html 29 | for user_id in to_add_users.split(" "): 30 | try: 31 | await event.client( 32 | functions.channels.InviteToChannelRequest( 33 | channel=event.chat_id, users=[user_id] 34 | ) 35 | ) 36 | except Exception as e: 37 | await event.edit(str(e)) 38 | return 39 | 40 | await event.edit("`Invited Successfully`") 41 | await sleep(2) 42 | await event.delete() 43 | 44 | 45 | CMD_HELP.update( 46 | { 47 | "invite": ".invite \ 48 | \nUsage: Invite some user or bots if u want." 49 | } 50 | ) 51 | -------------------------------------------------------------------------------- /userbot/modules/justwatch.py: -------------------------------------------------------------------------------- 1 | # Uniborg Plugin for getting list of sites where you can watch a particular Movie or TV-Show 2 | # Author: Sumanjay (https://github.com/cyberboysumanjay) (@cyberboysumanjay) 3 | # All rights reserved. 4 | 5 | """Syntax: .watch Movie/TV Show""" 6 | from telethon import events 7 | import requests 8 | from userbot.events import register 9 | from justwatch import JustWatch 10 | from userbot import bot, WATCH_COUNTRY, CMD_HELP 11 | 12 | 13 | def get_stream_data(query): 14 | stream_data = {} 15 | 16 | # Compatibility for Current Userge Users 17 | try: 18 | country = WATCH_COUNTRY 19 | except Exception: 20 | country = "ID" 21 | 22 | # Cooking Data 23 | just_watch = JustWatch(country=country) 24 | results = just_watch.search_for_item(query=query) 25 | movie = results["items"][0] 26 | stream_data["title"] = movie["title"] 27 | stream_data["movie_thumb"] = ( 28 | "https://images.justwatch.com" 29 | + movie["poster"].replace("{profile}", "") 30 | + "s592" 31 | ) 32 | stream_data["release_year"] = movie["original_release_year"] 33 | try: 34 | print(movie["cinema_release_date"]) 35 | stream_data["release_date"] = movie["cinema_release_date"] 36 | except KeyError: 37 | try: 38 | stream_data["release_date"] = movie["localized_release_date"] 39 | except KeyError: 40 | stream_data["release_date"] = None 41 | 42 | stream_data["type"] = movie["object_type"] 43 | 44 | available_streams = {} 45 | for provider in movie["offers"]: 46 | provider_ = get_provider(provider["urls"]["standard_web"]) 47 | available_streams[provider_] = provider["urls"]["standard_web"] 48 | 49 | stream_data["providers"] = available_streams 50 | 51 | scoring = {} 52 | for scorer in movie["scoring"]: 53 | if scorer["provider_type"] == "tmdb:score": 54 | scoring["tmdb"] = scorer["value"] 55 | 56 | if scorer["provider_type"] == "imdb:score": 57 | scoring["imdb"] = scorer["value"] 58 | stream_data["score"] = scoring 59 | return stream_data 60 | 61 | 62 | # Helper Functions 63 | def pretty(name): 64 | if name == "play": 65 | name = "Google Play Movies" 66 | return name[0].upper() + name[1:] 67 | 68 | 69 | def get_provider(url): 70 | url = url.replace("https://www.", "") 71 | url = url.replace("https://", "") 72 | url = url.replace("http://www.", "") 73 | url = url.replace("http://", "") 74 | url = url.split(".")[0] 75 | return url 76 | 77 | 78 | @register(outgoing=True, pattern="^\.watch (.*)") 79 | async def _(event): 80 | if event.fwd_from: 81 | return 82 | query = event.pattern_match.group(1) 83 | await event.edit("Finding Sites...") 84 | streams = get_stream_data(query) 85 | title = streams["title"] 86 | thumb_link = streams["movie_thumb"] 87 | release_year = streams["release_year"] 88 | release_date = streams["release_date"] 89 | scores = streams["score"] 90 | try: 91 | imdb_score = scores["imdb"] 92 | except KeyError: 93 | imdb_score = None 94 | 95 | try: 96 | tmdb_score = scores["tmdb"] 97 | except KeyError: 98 | tmdb_score = None 99 | 100 | stream_providers = streams["providers"] 101 | if release_date is None: 102 | release_date = release_year 103 | 104 | output_ = f"**Movie:**\n`{title}`\n**Release Date:**\n`{release_date}`" 105 | if imdb_score: 106 | output_ = output_ + f"\n**IMDB: **{imdb_score}" 107 | if tmdb_score: 108 | output_ = output_ + f"\n**TMDB: **{tmdb_score}" 109 | 110 | output_ = output_ + "\n\n**Available on:**\n" 111 | for provider, link in stream_providers.items(): 112 | if "sonyliv" in link: 113 | link = link.replace(" ", "%20") 114 | output_ += f"[{pretty(provider)}]({link})\n" 115 | 116 | await event.client.send_file( 117 | event.chat_id, 118 | caption=output_, 119 | file=thumb_link, 120 | force_document=False, 121 | allow_cache=False, 122 | silent=True, 123 | ) 124 | await event.delete() 125 | 126 | 127 | CMD_HELP.update( 128 | { 129 | "watch": ">`.watch` **Movies or TV Show" 130 | "\nUsage: Find data about Movies or TV Show at `justwatch.com`." 131 | } 132 | ) 133 | -------------------------------------------------------------------------------- /userbot/modules/locks.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | 6 | from telethon.tl.functions.messages import EditChatDefaultBannedRightsRequest 7 | from telethon.tl.types import ChatBannedRights 8 | 9 | from userbot import CMD_HELP 10 | from userbot.events import register 11 | 12 | 13 | @register(outgoing=True, pattern=r"^.lock ?(.*)") 14 | async def locks(event): 15 | input_str = event.pattern_match.group(1).lower() 16 | peer_id = event.chat_id 17 | msg = None 18 | media = None 19 | sticker = None 20 | gif = None 21 | gamee = None 22 | ainline = None 23 | gpoll = None 24 | adduser = None 25 | cpin = None 26 | changeinfo = None 27 | if input_str == "msg": 28 | msg = True 29 | what = "messages" 30 | elif input_str == "media": 31 | media = True 32 | what = "media" 33 | elif input_str == "sticker": 34 | sticker = True 35 | what = "stickers" 36 | elif input_str == "gif": 37 | gif = True 38 | what = "GIFs" 39 | elif input_str == "game": 40 | gamee = True 41 | what = "games" 42 | elif input_str == "inline": 43 | ainline = True 44 | what = "inline bots" 45 | elif input_str == "poll": 46 | gpoll = True 47 | what = "polls" 48 | elif input_str == "invite": 49 | adduser = True 50 | what = "invites" 51 | elif input_str == "pin": 52 | cpin = True 53 | what = "pins" 54 | elif input_str == "info": 55 | changeinfo = True 56 | what = "chat info" 57 | elif input_str == "all": 58 | msg = True 59 | media = True 60 | sticker = True 61 | gif = True 62 | gamee = True 63 | ainline = True 64 | gpoll = True 65 | adduser = True 66 | cpin = True 67 | changeinfo = True 68 | what = "everything" 69 | else: 70 | if not input_str: 71 | await event.edit("`I can't lock nothing !!`") 72 | else: 73 | await event.edit(f"`Invalid lock type:` {input_str}") 74 | return 75 | lock_rights = ChatBannedRights( 76 | until_date=None, 77 | send_messages=msg, 78 | send_media=media, 79 | send_stickers=sticker, 80 | send_gifs=gif, 81 | send_games=gamee, 82 | send_inline=ainline, 83 | send_polls=gpoll, 84 | invite_users=adduser, 85 | pin_messages=cpin, 86 | change_info=changeinfo, 87 | ) 88 | try: 89 | await event.client( 90 | EditChatDefaultBannedRightsRequest(peer=peer_id, banned_rights=lock_rights) 91 | ) 92 | await event.edit(f"`Locked {what} for this chat !!`") 93 | except BaseException as e: 94 | await event.edit(f"`Do I have proper rights for that ??`\n**Error:** {str(e)}") 95 | return 96 | 97 | 98 | @register(outgoing=True, pattern=r"^.unlock ?(.*)") 99 | async def rem_locks(event): 100 | input_str = event.pattern_match.group(1).lower() 101 | peer_id = event.chat_id 102 | msg = None 103 | media = None 104 | sticker = None 105 | gif = None 106 | gamee = None 107 | ainline = None 108 | gpoll = None 109 | adduser = None 110 | cpin = None 111 | changeinfo = None 112 | if input_str == "msg": 113 | msg = False 114 | what = "messages" 115 | elif input_str == "media": 116 | media = False 117 | what = "media" 118 | elif input_str == "sticker": 119 | sticker = False 120 | what = "stickers" 121 | elif input_str == "gif": 122 | gif = False 123 | what = "GIFs" 124 | elif input_str == "game": 125 | gamee = False 126 | what = "games" 127 | elif input_str == "inline": 128 | ainline = False 129 | what = "inline bots" 130 | elif input_str == "poll": 131 | gpoll = False 132 | what = "polls" 133 | elif input_str == "invite": 134 | adduser = False 135 | what = "invites" 136 | elif input_str == "pin": 137 | cpin = False 138 | what = "pins" 139 | elif input_str == "info": 140 | changeinfo = False 141 | what = "chat info" 142 | elif input_str == "all": 143 | msg = False 144 | media = False 145 | sticker = False 146 | gif = False 147 | gamee = False 148 | ainline = False 149 | gpoll = False 150 | adduser = False 151 | cpin = False 152 | changeinfo = False 153 | what = "everything" 154 | else: 155 | if not input_str: 156 | await event.edit("`I can't unlock nothing !!`") 157 | else: 158 | await event.edit(f"`Invalid unlock type:` {input_str}") 159 | return 160 | unlock_rights = ChatBannedRights( 161 | until_date=None, 162 | send_messages=msg, 163 | send_media=media, 164 | send_stickers=sticker, 165 | send_gifs=gif, 166 | send_games=gamee, 167 | send_inline=ainline, 168 | send_polls=gpoll, 169 | invite_users=adduser, 170 | pin_messages=cpin, 171 | change_info=changeinfo, 172 | ) 173 | try: 174 | await event.client( 175 | EditChatDefaultBannedRightsRequest( 176 | peer=peer_id, banned_rights=unlock_rights 177 | ) 178 | ) 179 | await event.edit(f"`Unlocked {what} for this chat !!`") 180 | except BaseException as e: 181 | await event.edit(f"`Do I have proper rights for that ??`\n**Error:** {str(e)}") 182 | return 183 | 184 | 185 | CMD_HELP.update( 186 | { 187 | "locks": ".lock or .unlock \ 188 | \nUsage: Allows you to lock/unlock some common message types in the chat.\ 189 | [NOTE: Requires proper admin rights in the chat !!]\ 190 | \n\nAvailable message types to lock/unlock are: \ 191 | \n`all, msg, media, sticker, gif, game, inline, poll, invite, pin, info`" 192 | } 193 | ) 194 | -------------------------------------------------------------------------------- /userbot/modules/lydia.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # credit goes to @snapdragon and @devpatel_73 for making it work on this userbot. 6 | # 7 | # Original author of the UniBorg module 'lydia' @Zero_cool7870 (Jaskaran) 8 | # 9 | """ 10 | Userbot module to use an AI To respond to people 11 | """ 12 | 13 | from coffeehouse.lydia import LydiaAI 14 | from coffeehouse.api import API 15 | import asyncio 16 | from userbot import LYDIA_API_KEY 17 | 18 | from userbot import BOTLOG, BOTLOG_CHATID, CMD_HELP, bot 19 | 20 | 21 | from userbot.events import register 22 | from telethon import events 23 | 24 | # Non-SQL Mode 25 | ACC_LYDIA = {} 26 | 27 | if LYDIA_API_KEY: 28 | api_key = LYDIA_API_KEY 29 | api_client = API(api_key) 30 | lydia = LydiaAI(api_client) 31 | 32 | 33 | @register(outgoing=True, pattern="^.repcf$") 34 | async def repcf(event): 35 | # Prevent Channel Bug to use repc 36 | if event.is_channel and not event.is_group: 37 | await event.edit("`repc Commad isn't permitted on channels`") 38 | return 39 | if event.fwd_from: 40 | return 41 | await event.edit("Processing...") 42 | try: 43 | session = lydia.create_session() 44 | session_id = session.id 45 | reply = await event.get_reply_message() 46 | msg = reply.text 47 | text_rep = session.think_thought(msg) 48 | await event.edit("**Lydia says**: {0}".format(text_rep)) 49 | except Exception as e: 50 | await event.edit(str(e)) 51 | 52 | 53 | @register(outgoing=True, pattern="^.addcf$") 54 | async def addcf(event): 55 | # Prevent Channel Bug to use addcf 56 | if event.is_channel and not event.is_group: 57 | await event.edit("`addcf Commad isn't permitted on channels`") 58 | return 59 | if event.fwd_from: 60 | return 61 | await event.edit("Running on SQL mode for now...") 62 | await asyncio.sleep(4) 63 | await event.edit("Processing...") 64 | reply_msg = await event.get_reply_message() 65 | if reply_msg: 66 | session = lydia.create_session() 67 | session_id = session.id 68 | if reply_msg.from_id is None: 69 | return await event.edit("Invalid user type.") 70 | ACC_LYDIA.update({(event.chat_id & reply_msg.from_id): session}) 71 | await event.edit( 72 | "Lydia successfully enabled for user: {} in chat: {}".format( 73 | str(reply_msg.from_id), str(event.chat_id) 74 | ) 75 | ) 76 | else: 77 | await event.edit("Reply to a user to activate Lydia AI on them") 78 | 79 | 80 | @register(outgoing=True, pattern="^.remcf$") 81 | async def remcf(event): 82 | # Prevent Channel Bug to use remcf 83 | if event.is_channel and not event.is_group: 84 | await event.edit("`remcf Commad isn't permitted on channels`") 85 | return 86 | if event.fwd_from: 87 | return 88 | await event.edit("Running on SQL mode for now...") 89 | await asyncio.sleep(4) 90 | await event.edit("Processing...") 91 | reply_msg = await event.get_reply_message() 92 | try: 93 | del ACC_LYDIA[event.chat_id & reply_msg.from_id] 94 | await event.edit( 95 | "Lydia successfully disabled for user: {} in chat: {}".format( 96 | str(reply_msg.from_id), str(event.chat_id) 97 | ) 98 | ) 99 | except Exception: 100 | await event.edit("This person does not have Lydia activated on him/her.") 101 | 102 | 103 | @register(incoming=True, disable_edited=True) 104 | async def user(event): 105 | user_text = event.text 106 | try: 107 | session = ACC_LYDIA[event.chat_id & event.from_id] 108 | async with event.client.action(event.chat_id, "typing"): 109 | msg = event.text 110 | text_rep = session.think_thought(msg) 111 | wait_time = 0 112 | for _ in text_rep: 113 | wait_time += 0.1 114 | await asyncio.sleep(wait_time) 115 | await event.reply(text_rep) 116 | except (KeyError, TypeError): 117 | return 118 | 119 | 120 | CMD_HELP.update( 121 | { 122 | "lydia": ".addcf \ 123 | \nUsage: add's lydia auto chat request in the chat.\ 124 | \n\n.remcf \ 125 | \nUsage: remove's lydia auto chat request in the chat.\ 126 | \n\n.repcf \ 127 | \nUsage: starts lydia repling to perticular person in the chat." 128 | } 129 | ) 130 | -------------------------------------------------------------------------------- /userbot/modules/lyrics.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | # 7 | import os 8 | import lyricsgenius 9 | 10 | from userbot.events import register 11 | from userbot import CMD_HELP, GENIUS, lastfm, LASTFM_USERNAME 12 | from pylast import User 13 | 14 | if GENIUS is not None: 15 | genius = lyricsgenius.Genius(GENIUS) 16 | 17 | 18 | @register(outgoing=True, pattern="^.lrc (?:(now)|(.*) - (.*))") 19 | async def lyrics(lyric): 20 | await lyric.edit("`Getting information...`") 21 | if GENIUS is None: 22 | await lyric.edit("`Provide genius access token to Heroku ConfigVars...`") 23 | return False 24 | if lyric.pattern_match.group(1) == "now": 25 | playing = User(LASTFM_USERNAME, lastfm).get_now_playing() 26 | if playing is None: 27 | await lyric.edit("`No information current lastfm scrobbling...`") 28 | return False 29 | artist = playing.get_artist() 30 | song = playing.get_title() 31 | else: 32 | artist = lyric.pattern_match.group(2) 33 | song = lyric.pattern_match.group(3) 34 | await lyric.edit(f"`Searching lyrics for {artist} - {song}...`") 35 | songs = genius.search_song(song, artist) 36 | if songs is None: 37 | await lyric.edit(f"`Song` **{artist} - {song}** `not found...`") 38 | return False 39 | if len(songs.lyrics) > 4096: 40 | await lyric.edit("`Lyrics is too big, view the file to see it.`") 41 | with open("lyrics.txt", "w+") as f: 42 | f.write(f"Search query: \n{artist} - {song}\n\n{songs.lyrics}") 43 | await lyric.client.send_file( 44 | lyric.chat_id, "lyrics.txt", reply_to=lyric.id, 45 | ) 46 | os.remove("lyrics.txt") 47 | else: 48 | await lyric.edit( 49 | f"**Search query**:\n`{artist}` - `{song}`" f"\n\n```{songs.lyrics}```" 50 | ) 51 | 52 | return True 53 | 54 | 55 | CMD_HELP.update( 56 | { 57 | "lyrics": ">`.lrc` ** - **" 58 | "\nUsage: Get lyrics matched artist and song." 59 | "\n\n>`.lrc now`" 60 | "\nUsage: Get lyrics artist and song from current lastfm scrobbling." 61 | } 62 | ) 63 | -------------------------------------------------------------------------------- /userbot/modules/nhentai.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 KeselekPermen69 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.d (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | 7 | import datetime 8 | from telethon import events 9 | from telethon.errors.rpcerrorlist import YouBlockedUserError 10 | from telethon.tl.functions.account import UpdateNotifySettingsRequest 11 | from userbot import bot, CMD_HELP 12 | from userbot.events import register 13 | 14 | 15 | @register(outgoing=True, pattern="^.nhentai(?: |$)(.*)") 16 | async def _(hentai): 17 | if hentai.fwd_from: 18 | return 19 | link = hentai.pattern_match.group(1) 20 | if not link: 21 | return await hentai.edit("`I can't search nothing`") 22 | chat = "@nHentaiBot" 23 | await hentai.edit("```Processing```") 24 | async with bot.conversation(chat) as conv: 25 | try: 26 | response = conv.wait_event( 27 | events.NewMessage(incoming=True, from_users=424466890) 28 | ) 29 | msg = await bot.send_message(chat, link) 30 | response = await response 31 | """ - don't spam notif - """ 32 | await bot.send_read_acknowledge(conv.chat_id) 33 | except YouBlockedUserError: 34 | await hentai.reply("```Please unblock @nHentaiBot and try again```") 35 | return 36 | if response.text.startswith("**Sorry I couldn't get manga from**"): 37 | await hentai.edit("```I think this is not the right link```") 38 | else: 39 | await hentai.delete() 40 | await bot.send_message(hentai.chat_id, response.message) 41 | await bot.send_read_acknowledge(hentai.chat_id) 42 | """ - cleanup chat after completed - """ 43 | await hentai.client.delete_messages(conv.chat_id, [msg.id, response.id]) 44 | 45 | 46 | CMD_HELP.update( 47 | {"nhentai": "`.nhentai` " "\nUsage: view nhentai in telegra.ph"} 48 | ) 49 | -------------------------------------------------------------------------------- /userbot/modules/ocr.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | 6 | from telethon import events 7 | import os 8 | import requests 9 | import logging 10 | from userbot import bot, OCR_SPACE_API_KEY, CMD_HELP, TEMP_DOWNLOAD_DIRECTORY 11 | from userbot.events import register 12 | 13 | 14 | async def ocr_space_file( 15 | filename, overlay=False, api_key=OCR_SPACE_API_KEY, language="eng" 16 | ): 17 | """ OCR.space API request with local file. 18 | Python3.5 - not tested on 2.7 19 | :param filename: Your file path & name. 20 | :param overlay: Is OCR.space overlay required in your response. 21 | Defaults to False. 22 | :param api_key: OCR.space API key. 23 | Defaults to 'helloworld'. 24 | :param language: Language code to be used in OCR. 25 | List of available language codes can be found on https://ocr.space/OCRAPI 26 | Defaults to 'en'. 27 | :return: Result in JSON format. 28 | """ 29 | 30 | payload = { 31 | "isOverlayRequired": overlay, 32 | "apikey": api_key, 33 | "language": language, 34 | } 35 | with open(filename, "rb") as f: 36 | r = requests.post( 37 | "https://api.ocr.space/parse/image", files={filename: f}, data=payload, 38 | ) 39 | return r.json() 40 | 41 | 42 | @register(pattern=r".ocr (.*)", outgoing=True) 43 | async def ocr(event): 44 | if not OCR_SPACE_API_KEY: 45 | return await event.edit( 46 | "`Error: OCR.Space API key is missing! Add it to environment variables or config.env.`" 47 | ) 48 | await event.edit("`Reading...`") 49 | if not os.path.isdir(TEMP_DOWNLOAD_DIRECTORY): 50 | os.makedirs(TEMP_DOWNLOAD_DIRECTORY) 51 | lang_code = event.pattern_match.group(1) 52 | downloaded_file_name = await bot.download_media( 53 | await event.get_reply_message(), TEMP_DOWNLOAD_DIRECTORY 54 | ) 55 | test_file = await ocr_space_file(filename=downloaded_file_name, language=lang_code) 56 | try: 57 | ParsedText = test_file["ParsedResults"][0]["ParsedText"] 58 | except BaseException: 59 | await event.edit("`Couldn't read it.`\n`I guess I need new glasses.`") 60 | else: 61 | await event.edit(f"`Here's what I could read from it:`\n\n{ParsedText}") 62 | os.remove(downloaded_file_name) 63 | 64 | 65 | CMD_HELP.update( 66 | { 67 | "ocr": ">`.ocr `" 68 | "\nUsage: Reply to an image or sticker to extract text from it." 69 | "\n\nGet language codes from [here](https://ocr.space/OCRAPI#PostParameters)" 70 | } 71 | ) 72 | -------------------------------------------------------------------------------- /userbot/modules/openuserbot.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | # You can find misc modules, which dont fit in anything xD 7 | """ Userbot module for other small commands. """ 8 | import sys 9 | from userbot import CMD_HELP 10 | from userbot.events import register 11 | 12 | 13 | @register(outgoing=True, pattern="^.oub$") 14 | async def shalom(e): 15 | await e.edit( 16 | "\n💰💰💰💰💰💰💰💰💰" 17 | "\n💰💰❄️❄️❄️❄️❄️💰💰" 18 | "\n💰❄️💰💰💰💰💰❄️💰" 19 | "\n💰❄️💰💰💰💰💰❄️💰" 20 | "\n💰❄️💰💰💰💰💰❄️💰" 21 | "\n💰💰❄️❄️❄️❄️❄️💰💰" 22 | "\n💰💰💰💰💰💰💰💰💰" 23 | "\n💰❄️❄️❄️❄️❄️❄️❄️💰" 24 | "\n💰💰💰💰❄️💰💰❄️💰" 25 | "\n💰💰💰💰❄️💰💰❄️💰" 26 | "\n💰💰💰💰❄️💰💰❄️💰" 27 | "\n💰💰💰💰💰❄️❄️💰💰" 28 | "\n💰💰💰💰💰💰💰💰💰" 29 | "\n💰❄️❄️❄️❄️❄️❄️❄️💰" 30 | "\n💰❄️💰💰❄️💰💰❄️💰" 31 | "\n💰❄️💰💰❄️💰💰❄️💰" 32 | "\n💰❄️💰💰❄️💰💰❄️💰" 33 | "\n💰❄️💰💰💰💰💰❄️💰" 34 | "\n💰💰💰💰💰💰💰💰💰" 35 | "\n💰❄️❄️❄️❄️❄️❄️❄️💰" 36 | "\n💰💰💰💰💰💰❄️💰💰" 37 | "\n💰💰💰💰💰❄️💰💰💰" 38 | "\n💰💰💰💰❄️💰💰💰💰" 39 | "\n💰❄️❄️❄️❄️❄️❄️❄️💰" 40 | "\n💰💰💰💰💰💰💰💰💰" 41 | "\n💰💰❄️❄️❄️❄️❄️❄️💰" 42 | "\n💰❄️💰💰💰💰💰💰💰" 43 | "\n💰❄️💰💰💰💰💰💰💰" 44 | "\n💰❄️💰💰💰💰💰💰💰" 45 | "\n💰💰❄️❄️❄️❄️❄️❄️💰" 46 | "\n💰💰💰💰💰💰💰💰💰" 47 | "\n💰❄️💰💰💰❄️❄️💰💰" 48 | "\n💰❄️💰💰❄️💰💰❄️💰" 49 | "\n💰❄️💰💰❄️💰💰❄️💰" 50 | "\n💰❄️💰💰❄️💰💰❄️💰" 51 | "\n💰💰❄️❄️💰💰💰❄️💰" 52 | "\n💰💰💰💰💰💰💰💰💰" 53 | "\n💰❄️❄️❄️❄️❄️❄️❄️💰" 54 | "\n💰❄️💰💰❄️💰💰❄️💰" 55 | "\n💰❄️💰💰❄️💰💰❄️💰" 56 | "\n💰❄️💰💰❄️💰💰❄️💰" 57 | "\n💰❄️💰💰💰💰💰❄️💰" 58 | "\n💰💰💰💰💰💰💰💰💰" 59 | "\n💰❄️❄️❄️❄️❄️❄️❄️💰" 60 | "\n💰💰💰💰❄️💰💰❄️💰" 61 | "\n💰💰💰❄️❄️💰💰❄️💰" 62 | "\n💰💰❄️💰❄️💰💰❄️💰" 63 | "\n💰❄️💰💰💰❄️❄️💰💰" 64 | "\n💰💰💰💰💰💰💰💰💰" 65 | "\n💰❄️❄️❄️❄️❄️❄️❄️💰" 66 | "\n💰❄️💰💰❄️💰💰❄️💰" 67 | "\n💰❄️💰💰❄️💰💰❄️💰" 68 | "\n💰❄️💰💰❄️💰💰❄️💰" 69 | "\n💰💰❄️❄️💰❄️❄️💰💰" 70 | "\n💰💰💰💰💰💰💰💰💰" 71 | "\n💰💰❄️❄️❄️❄️❄️💰💰" 72 | "\n💰❄️💰💰💰💰💰❄️💰" 73 | "\n💰❄️💰💰💰💰💰❄️💰" 74 | "\n💰❄️💰💰💰💰💰❄️💰" 75 | "\n💰💰❄️❄️❄️❄️❄️💰💰" 76 | "\n💰💰💰💰💰💰💰💰💰" 77 | "\n💰💰💰💰💰💰💰❄️💰" 78 | "\n💰💰💰💰💰💰💰❄️💰" 79 | "\n💰❄️❄️❄️❄️❄️❄️❄️💰" 80 | "\n💰💰💰💰💰💰💰❄️💰" 81 | "\n💰💰💰💰💰💰💰❄️💰" 82 | "\n💰💰💰💰💰💰💰💰💰" 83 | "\n💰💰💰💰💰💰💰💰💰" 84 | "\n💰💰💰💰💰💰💰💰💰" 85 | "\n💰❄️💰💰💰💰💰❄️💰" 86 | "\n💰❄️❄️❄️❄️❄️❄️❄️💰" 87 | "\n💰❄️💰💰💰💰💰❄️💰" 88 | "\n💰💰💰💰💰💰💰💰💰" 89 | "\n💰❄️💰💰💰❄️❄️💰💰" 90 | "\n💰❄️💰💰❄️💰💰❄️💰" 91 | "\n💰❄️💰💰❄️💰💰❄️💰" 92 | "\n💰❄️💰💰❄️💰💰❄️💰" 93 | "\n💰💰❄️❄️💰💰💰❄️💰" 94 | "\n💰💰💰💰💰💰💰💰💰" 95 | "\n💰💰💰💰💰💰💰💰💰" 96 | "\n💰💰💰💰💰💰💰💰💰" 97 | "\n💰💰💰💰💰💰💰❄️💰" 98 | "\n💰💰💰💰💰💰💰❄️💰" 99 | "\n💰❄️❄️❄️❄️❄️❄️❄️💰" 100 | "\n💰💰💰💰💰💰💰❄️💰" 101 | "\n💰💰💰💰💰💰💰❄️💰" 102 | "\n💰💰💰💰💰💰💰💰💰" 103 | "\n💰❄️❄️❄️❄️❄️❄️❄️💰" 104 | "\n💰💰💰💰❄️💰💰💰💰" 105 | "\n💰💰💰💰❄️💰💰💰💰" 106 | "\n💰💰💰💰❄️💰💰💰💰" 107 | "\n💰❄️❄️❄️❄️❄️❄️❄️💰" 108 | "\n💰💰💰💰💰💰💰💰💰" 109 | "\n💰❄️❄️❄️❄️❄️❄️❄️💰" 110 | "\n💰❄️💰💰❄️💰💰❄️💰" 111 | "\n💰❄️💰💰❄️💰💰❄️💰" 112 | "\n💰❄️💰💰❄️💰💰❄️💰" 113 | "\n💰❄️💰💰💰💰💰❄️💰" 114 | "\n💰💰💰💰💰💰💰💰💰" 115 | "\n💰💰💰💰💰💰💰💰💰" 116 | "\n💰💰💰💰💰💰💰💰💰" 117 | "\n💰❄️❄️❄️❄️❄️❄️❄️💰" 118 | "\n💰❄️💰💰❄️💰💰❄️💰" 119 | "\n💰❄️💰💰❄️💰💰❄️💰" 120 | "\n💰❄️💰💰❄️💰💰❄️💰" 121 | "\n💰💰❄️❄️💰❄️❄️💰💰" 122 | "\n💰💰💰💰💰💰💰💰💰" 123 | "\n💰❄️❄️❄️❄️❄️❄️❄️💰" 124 | "\n💰❄️💰💰❄️💰💰❄️💰" 125 | "\n💰❄️💰💰❄️💰💰❄️💰" 126 | "\n💰❄️💰💰❄️💰💰❄️💰" 127 | "\n💰❄️💰💰💰💰💰❄️💰" 128 | "\n💰💰💰💰💰💰💰💰💰" 129 | "\n💰❄️💰💰💰❄️❄️💰💰" 130 | "\n💰❄️💰💰❄️💰💰❄️💰" 131 | "\n💰❄️💰💰❄️💰💰❄️💰" 132 | "\n💰❄️💰💰❄️💰💰❄️💰" 133 | "\n💰💰❄️❄️💰💰💰❄️💰" 134 | "\n💰💰💰💰💰💰💰💰💰" 135 | "\n💰💰💰💰💰💰💰❄️💰" 136 | "\n💰💰💰💰💰💰💰❄️💰" 137 | "\n💰❄️❄️❄️❄️❄️❄️❄️💰" 138 | "\n💰💰💰💰💰💰💰❄️💰" 139 | "\n💰💰💰💰💰💰💰❄️💰" 140 | "\n💰💰💰💰💰💰💰💰💰" 141 | ) 142 | 143 | CMD_HELP.update( 144 | { 145 | "oub": ".oub\ 146 | \nUsage: gives a nice OPENUSERBOT as output." 147 | } 148 | ) 149 | -------------------------------------------------------------------------------- /userbot/modules/pics.py: -------------------------------------------------------------------------------- 1 | from io import BytesIO 2 | from userbot.events import register 3 | from userbot import CMD_HELP 4 | from telethon import types 5 | from asyncio import sleep 6 | from telethon.errors import PhotoInvalidDimensionsError 7 | from telethon.tl.functions.messages import SendMediaRequest 8 | 9 | 10 | @register(outgoing=True, pattern="^\.pic(?: |$)(.*)") 11 | async def on_file_to_photo(pics): 12 | await pics.edit("Converting Document image to Full Size Image\nPlease wait...") 13 | await sleep(2.5) 14 | await pics.delete() 15 | target = await pics.get_reply_message() 16 | try: 17 | image = target.media.document 18 | except AttributeError: 19 | return 20 | if not image.mime_type.startswith("image/"): 21 | return # This isn't an image 22 | if image.mime_type == "image/webp": 23 | return # Telegram doesn't let you directly send stickers as photos 24 | if image.size > 10 * 2560 * 1440: 25 | return # We'd get PhotoSaveFileInvalidError otherwise 26 | 27 | file = await pics.client.download_media(target, file=BytesIO()) 28 | file.seek(0) 29 | img = await pics.client.upload_file(file) 30 | img.name = "image.png" 31 | 32 | try: 33 | await pics.client( 34 | SendMediaRequest( 35 | peer=await pics.get_input_chat(), 36 | media=types.InputMediaUploadedPhoto(img), 37 | message=target.message, 38 | entities=target.entities, 39 | reply_to_msg_id=target.id, 40 | ) 41 | ) 42 | except PhotoInvalidDimensionsError: 43 | return 44 | 45 | 46 | CMD_HELP.update( 47 | { 48 | "pics": ".pic reply any document image\nUsage : Convert any Document Image to Full Size Image" 49 | } 50 | ) 51 | -------------------------------------------------------------------------------- /userbot/modules/purge.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | """ Userbot module for purging unneeded messages(usually spam or ot). """ 7 | 8 | from asyncio import sleep 9 | 10 | from telethon.errors import rpcbaseerrors 11 | 12 | from userbot import BOTLOG, BOTLOG_CHATID, CMD_HELP 13 | from userbot.events import register 14 | 15 | 16 | @register(outgoing=True, pattern="^.purge$") 17 | async def fastpurger(purg): 18 | """ For .purge command, purge all messages starting from the reply. """ 19 | chat = await purg.get_input_chat() 20 | msgs = [] 21 | itermsg = purg.client.iter_messages(chat, min_id=purg.reply_to_msg_id) 22 | count = 0 23 | 24 | if purg.reply_to_msg_id is not None: 25 | async for msg in itermsg: 26 | msgs.append(msg) 27 | count += 1 28 | msgs.append(purg.reply_to_msg_id) 29 | if len(msgs) == 100: 30 | await purg.client.delete_messages(chat, msgs) 31 | msgs = [] 32 | else: 33 | await purg.edit("`I need a mesasge to start purging from.`") 34 | return 35 | 36 | if msgs: 37 | await purg.client.delete_messages(chat, msgs) 38 | done = await purg.client.send_message( 39 | purg.chat_id, 40 | f"`Fast purge complete!`\ 41 | \nPurged {str(count)} messages", 42 | ) 43 | 44 | if BOTLOG: 45 | await purg.client.send_message( 46 | BOTLOG_CHATID, "Purge of " + str(count) + " messages done successfully." 47 | ) 48 | await sleep(2) 49 | await done.delete() 50 | 51 | 52 | @register(outgoing=True, pattern="^.purgeme") 53 | async def purgeme(delme): 54 | """ For .purgeme, delete x count of your latest message.""" 55 | message = delme.text 56 | count = int(message[9:]) 57 | i = 1 58 | 59 | async for message in delme.client.iter_messages(delme.chat_id, from_user="me"): 60 | if i > count + 1: 61 | break 62 | i += 1 63 | await message.delete() 64 | 65 | smsg = await delme.client.send_message( 66 | delme.chat_id, "`Purge complete!` Purged " + str(count) + " messages.", 67 | ) 68 | if BOTLOG: 69 | await delme.client.send_message( 70 | BOTLOG_CHATID, "Purge of " + str(count) + " messages done successfully." 71 | ) 72 | await sleep(2) 73 | i = 1 74 | await smsg.delete() 75 | 76 | 77 | @register(outgoing=True, pattern="^.del$") 78 | async def delete_it(delme): 79 | """ For .del command, delete the replied message. """ 80 | msg_src = await delme.get_reply_message() 81 | if delme.reply_to_msg_id: 82 | try: 83 | await msg_src.delete() 84 | await delme.delete() 85 | if BOTLOG: 86 | await delme.client.send_message( 87 | BOTLOG_CHATID, "Deletion of message was successful" 88 | ) 89 | except rpcbaseerrors.BadRequestError: 90 | if BOTLOG: 91 | await delme.client.send_message( 92 | BOTLOG_CHATID, "Well, I can't delete a message" 93 | ) 94 | 95 | 96 | @register(outgoing=True, pattern="^.edit") 97 | async def editer(edit): 98 | """ For .editme command, edit your last message. """ 99 | message = edit.text 100 | chat = await edit.get_input_chat() 101 | self_id = await edit.client.get_peer_id("me") 102 | string = str(message[6:]) 103 | i = 1 104 | async for message in edit.client.iter_messages(chat, self_id): 105 | if i == 2: 106 | await message.edit(string) 107 | await edit.delete() 108 | break 109 | i += 1 110 | if BOTLOG: 111 | await edit.client.send_message( 112 | BOTLOG_CHATID, "Edit query was executed successfully" 113 | ) 114 | 115 | 116 | @register(outgoing=True, pattern="^.sd") 117 | async def selfdestruct(destroy): 118 | """ For .sd command, make seflf-destructable messages. """ 119 | message = destroy.text 120 | counter = int(message[4:6]) 121 | text = str(destroy.text[6:]) 122 | await destroy.delete() 123 | smsg = await destroy.client.send_message(destroy.chat_id, text) 124 | await sleep(counter) 125 | await smsg.delete() 126 | if BOTLOG: 127 | await destroy.client.send_message(BOTLOG_CHATID, "sd query done successfully") 128 | 129 | 130 | CMD_HELP.update( 131 | { 132 | "purge": ".purge\ 133 | \nUsage: Purges all messages starting from the reply." 134 | } 135 | ) 136 | 137 | CMD_HELP.update( 138 | { 139 | "purgeme": ".purgeme \ 140 | \nUsage: Deletes x amount of your latest messages." 141 | } 142 | ) 143 | 144 | CMD_HELP.update( 145 | { 146 | "del": ".del\ 147 | \nUsage: Deletes the message you replied to." 148 | } 149 | ) 150 | 151 | CMD_HELP.update( 152 | { 153 | "edit": ".edit \ 154 | \nUsage: Replace your last message with ." 155 | } 156 | ) 157 | 158 | CMD_HELP.update( 159 | { 160 | "sd": ".sd \ 161 | \nUsage: Creates a message that selfdestructs in x seconds.\ 162 | \nKeep the seconds under 100 since it puts your bot to sleep." 163 | } 164 | ) 165 | -------------------------------------------------------------------------------- /userbot/modules/qrcode.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | # The entire source code is OSSRPL except 'makeqr and getqr' which is MPL 7 | # License: MPL and OSSRPL 8 | """ Userbot module containing commands related to QR Codes. """ 9 | 10 | import os 11 | import asyncio 12 | 13 | import qrcode 14 | import barcode 15 | from barcode.writer import ImageWriter 16 | 17 | from bs4 import BeautifulSoup 18 | 19 | from userbot import CMD_HELP, LOGS 20 | from userbot.events import register 21 | 22 | 23 | @register(pattern=r"^.decode$", outgoing=True) 24 | async def parseqr(qr_e): 25 | """ For .decode command, get QR Code/BarCode content from the replied photo. """ 26 | downloaded_file_name = await qr_e.client.download_media( 27 | await qr_e.get_reply_message() 28 | ) 29 | # parse the Official ZXing webpage to decode the QRCode 30 | command_to_exec = [ 31 | "curl", 32 | "-X", 33 | "POST", 34 | "-F", 35 | "f=@" + downloaded_file_name + "", 36 | "https://zxing.org/w/decode", 37 | ] 38 | process = await asyncio.create_subprocess_exec( 39 | *command_to_exec, 40 | # stdout must a pipe to be accessible as process.stdout 41 | stdout=asyncio.subprocess.PIPE, 42 | stderr=asyncio.subprocess.PIPE, 43 | ) 44 | # Wait for the subprocess to finish 45 | stdout, stderr = await process.communicate() 46 | e_response = stderr.decode().strip() 47 | t_response = stdout.decode().strip() 48 | os.remove(downloaded_file_name) 49 | if not t_response: 50 | LOGS.info(e_response) 51 | LOGS.info(t_response) 52 | return await qr_e.edit("Failed to decode.") 53 | soup = BeautifulSoup(t_response, "html.parser") 54 | qr_contents = soup.find_all("pre")[0].text 55 | await qr_e.edit(qr_contents) 56 | 57 | 58 | @register(pattern=r".barcode(?: |$)([\s\S]*)", outgoing=True) 59 | async def bq(event): 60 | """ For .barcode command, genrate a barcode containing the given content. """ 61 | await event.edit("`Processing..`") 62 | input_str = event.pattern_match.group(1) 63 | message = "SYNTAX: `.barcode `" 64 | reply_msg_id = event.message.id 65 | if input_str: 66 | message = input_str 67 | elif event.reply_to_msg_id: 68 | previous_message = await event.get_reply_message() 69 | reply_msg_id = previous_message.id 70 | if previous_message.media: 71 | downloaded_file_name = await event.client.download_media(previous_message) 72 | m_list = None 73 | with open(downloaded_file_name, "rb") as fd: 74 | m_list = fd.readlines() 75 | message = "" 76 | for m in m_list: 77 | message += m.decode("UTF-8") + "\r\n" 78 | os.remove(downloaded_file_name) 79 | else: 80 | message = previous_message.message 81 | else: 82 | return event.edit("SYNTAX: `.barcode `") 83 | 84 | bar_code_type = "code128" 85 | try: 86 | bar_code_mode_f = barcode.get(bar_code_type, message, writer=ImageWriter()) 87 | filename = bar_code_mode_f.save(bar_code_type) 88 | await event.client.send_file(event.chat_id, filename, reply_to=reply_msg_id) 89 | os.remove(filename) 90 | except Exception as e: 91 | return await event.edit(str(e)) 92 | await event.delete() 93 | 94 | 95 | @register(pattern=r".makeqr(?: |$)([\s\S]*)", outgoing=True) 96 | async def make_qr(makeqr): 97 | """ For .makeqr command, make a QR Code containing the given content. """ 98 | input_str = makeqr.pattern_match.group(1) 99 | message = "SYNTAX: `.makeqr `" 100 | reply_msg_id = None 101 | if input_str: 102 | message = input_str 103 | elif makeqr.reply_to_msg_id: 104 | previous_message = await makeqr.get_reply_message() 105 | reply_msg_id = previous_message.id 106 | if previous_message.media: 107 | downloaded_file_name = await makeqr.client.download_media(previous_message) 108 | m_list = None 109 | with open(downloaded_file_name, "rb") as file: 110 | m_list = file.readlines() 111 | message = "" 112 | for media in m_list: 113 | message += media.decode("UTF-8") + "\r\n" 114 | os.remove(downloaded_file_name) 115 | else: 116 | message = previous_message.message 117 | 118 | qr = qrcode.QRCode( 119 | version=1, 120 | error_correction=qrcode.constants.ERROR_CORRECT_L, 121 | box_size=10, 122 | border=4, 123 | ) 124 | qr.add_data(message) 125 | qr.make(fit=True) 126 | img = qr.make_image(fill_color="black", back_color="white") 127 | img.save("img_file.webp", "PNG") 128 | await makeqr.client.send_file( 129 | makeqr.chat_id, "img_file.webp", reply_to=reply_msg_id 130 | ) 131 | os.remove("img_file.webp") 132 | await makeqr.delete() 133 | 134 | 135 | CMD_HELP.update( 136 | { 137 | "qr": ".makeqr \ 138 | \nUsage: Make a QR Code from the given content.\ 139 | \nExample: .makeqr www.google.com\ 140 | \nNote: use .decode to get decoded content." 141 | } 142 | ) 143 | 144 | CMD_HELP.update( 145 | { 146 | "barcode": ".barcode \ 147 | \nUsage: Make a BarCode from the given content.\ 148 | \nExample: .barcode www.google.com\ 149 | \nNote: use .decode to get decoded content." 150 | } 151 | ) 152 | -------------------------------------------------------------------------------- /userbot/modules/quote.py: -------------------------------------------------------------------------------- 1 | #port to userbot by @MoveAngel 2 | 3 | import datetime 4 | from telethon import events 5 | from telethon.errors.rpcerrorlist import YouBlockedUserError 6 | from telethon.tl.functions.account import UpdateNotifySettingsRequest 7 | from userbot import bot, CMD_HELP 8 | from userbot.events import register 9 | 10 | @register(outgoing=True, pattern="^.q(?: |$)(.*)") 11 | async def _(event): 12 | if event.fwd_from: 13 | return 14 | if not event.reply_to_msg_id: 15 | await event.edit("```Reply to any user message.```") 16 | return 17 | reply_message = await event.get_reply_message() 18 | if not reply_message.text: 19 | await event.edit("```Reply to text message```") 20 | return 21 | chat = "@QuotLyBot" 22 | sender = reply_message.sender 23 | if reply_message.sender.bot: 24 | await event.edit("```Reply to actual users message.```") 25 | return 26 | await event.edit("```Making a Quote```") 27 | async with bot.conversation(chat) as conv: 28 | try: 29 | response = conv.wait_event(events.NewMessage(incoming=True,from_users=1031952739)) 30 | await bot.forward_messages(chat, reply_message) 31 | response = await response 32 | except YouBlockedUserError: 33 | await event.reply("```Please unblock @QuotLyBot and try again```") 34 | return 35 | if response.text.startswith("Hi!"): 36 | await event.edit("```Can you kindly disable your forward privacy settings for good?```") 37 | else: 38 | await event.delete() 39 | await bot.forward_messages(event.chat_id, response.message) 40 | 41 | CMD_HELP.update({ 42 | "quotly": 43 | ".q \ 44 | \nUsage: Enhance ur text to sticker.\n" 45 | }) 46 | -------------------------------------------------------------------------------- /userbot/modules/rastick.py: -------------------------------------------------------------------------------- 1 | import re 2 | import random 3 | from userbot import CMD_HELP, bot 4 | from userbot.events import register 5 | 6 | 7 | EMOJI_PATTERN = re.compile( 8 | "[" 9 | "\U0001F1E0-\U0001F1FF" # flags (iOS) 10 | "\U0001F300-\U0001F5FF" # symbols & pictographs 11 | "\U0001F600-\U0001F64F" # emoticons 12 | "\U0001F680-\U0001F6FF" # transport & map symbols 13 | "\U0001F700-\U0001F77F" # alchemical symbols 14 | "\U0001F780-\U0001F7FF" # Geometric Shapes Extended 15 | "\U0001F800-\U0001F8FF" # Supplemental Arrows-C 16 | "\U0001F900-\U0001F9FF" # Supplemental Symbols and Pictographs 17 | "\U0001FA00-\U0001FA6F" # Chess Symbols 18 | "\U0001FA70-\U0001FAFF" # Symbols and Pictographs Extended-A 19 | "\U00002702-\U000027B0" # Dingbats 20 | "]+" 21 | ) 22 | 23 | 24 | def deEmojify(inputString: str) -> str: 25 | return re.sub(EMOJI_PATTERN, "", inputString) 26 | 27 | 28 | @register(outgoing=True, pattern="^\.rs(?: |$)(.*)") 29 | async def rastick(animu): 30 | text = animu.pattern_match.group(1) 31 | if not text: 32 | if animu.is_reply: 33 | text = (await animu.get_reply_message()).message 34 | else: 35 | await animu.answer("`No text given, hence no stickers.`") 36 | return 37 | animus = [ 38 | 1, 39 | 2, 40 | 3, 41 | 4, 42 | 5, 43 | 6, 44 | 7, 45 | 8, 46 | 9, 47 | 10, 48 | 11, 49 | 12, 50 | 13, 51 | 14, 52 | 15, 53 | 16, 54 | 17, 55 | 18, 56 | 19, 57 | 20, 58 | 21, 59 | 22, 60 | 23, 61 | 24, 62 | 25, 63 | 26, 64 | 27, 65 | 28, 66 | 29, 67 | 30, 68 | 31, 69 | 32, 70 | 33, 71 | 34, 72 | 35, 73 | 36, 74 | 37, 75 | 38, 76 | 39, 77 | 40, 78 | 41, 79 | 42, 80 | 43, 81 | 44, 82 | 45, 83 | 46, 84 | 47, 85 | 48, 86 | 49, 87 | 50, 88 | 51, 89 | 52, 90 | 53, 91 | 54, 92 | 55, 93 | 56, 94 | 57, 95 | 58, 96 | 59, 97 | 60, 98 | 61, 99 | 62, 100 | 63, 101 | ] 102 | sticcers = await bot.inline_query( 103 | "stickerizerbot", f"#{random.choice(animus)}{(deEmojify(text))}" 104 | ) 105 | await sticcers[0].click( 106 | animu.chat_id, 107 | reply_to=animu.reply_to_msg_id, 108 | silent=True if animu.is_reply else False, 109 | hide_via=True, 110 | ) 111 | await animu.delete() 112 | 113 | 114 | CMD_HELP.update( 115 | { 116 | "rastick": ">`.rs`" 117 | "\nUsage: To stickerize your text with random sticker templates." 118 | } 119 | ) 120 | -------------------------------------------------------------------------------- /userbot/modules/remove_bg.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | 6 | # (c) Shrimadhav U K - UniBorg 7 | # Thanks to Prakasaka for porting. 8 | 9 | import io 10 | import os 11 | import requests 12 | from userbot.events import register 13 | from telethon.tl.types import MessageMediaPhoto 14 | from userbot import CMD_HELP, REM_BG_API_KEY, TEMP_DOWNLOAD_DIRECTORY 15 | 16 | 17 | @register(outgoing=True, pattern="^.rbg(?: |$)(.*)") 18 | async def kbg(remob): 19 | """ For .rbg command, Remove Image Background. """ 20 | if REM_BG_API_KEY is None: 21 | await remob.edit( 22 | "`Error: Remove.BG API key missing! Add it to environment vars or config.env.`" 23 | ) 24 | return 25 | input_str = remob.pattern_match.group(1) 26 | message_id = remob.message.id 27 | if remob.reply_to_msg_id: 28 | message_id = remob.reply_to_msg_id 29 | reply_message = await remob.get_reply_message() 30 | await remob.edit("`Processing..`") 31 | try: 32 | if isinstance( 33 | reply_message.media, MessageMediaPhoto 34 | ) or "image" in reply_message.media.document.mime_type.split("/"): 35 | downloaded_file_name = await remob.client.download_media( 36 | reply_message, TEMP_DOWNLOAD_DIRECTORY 37 | ) 38 | await remob.edit("`Removing background from this image..`") 39 | output_file_name = await ReTrieveFile(downloaded_file_name) 40 | os.remove(downloaded_file_name) 41 | else: 42 | await remob.edit("`How do I remove the background from this ?`") 43 | except Exception as e: 44 | await remob.edit(str(e)) 45 | return 46 | elif input_str: 47 | await remob.edit( 48 | f"`Removing background from online image hosted at`\n{input_str}" 49 | ) 50 | output_file_name = await ReTrieveURL(input_str) 51 | else: 52 | await remob.edit("`I need something to remove the background from.`") 53 | return 54 | contentType = output_file_name.headers.get("content-type") 55 | if "image" in contentType: 56 | with io.BytesIO(output_file_name.content) as remove_bg_image: 57 | remove_bg_image.name = "removed_bg.png" 58 | await remob.client.send_file( 59 | remob.chat_id, 60 | remove_bg_image, 61 | caption="Remove background successfully", 62 | force_document=True, 63 | reply_to=message_id, 64 | ) 65 | await remob.delete() 66 | else: 67 | await remob.edit( 68 | "**Error (Invalid API key, I guess ?)**\n`{}`".format( 69 | output_file_name.content.decode("UTF-8") 70 | ) 71 | ) 72 | 73 | 74 | # this method will call the API, and return in the appropriate format 75 | # with the name provided. 76 | async def ReTrieveFile(input_file_name): 77 | headers = { 78 | "X-API-Key": REM_BG_API_KEY, 79 | } 80 | files = { 81 | "image_file": (input_file_name, open(input_file_name, "rb")), 82 | } 83 | return requests.post( 84 | "https://api.remove.bg/v1.0/removebg", 85 | headers=headers, 86 | files=files, 87 | allow_redirects=True, 88 | stream=True, 89 | ) 90 | 91 | 92 | async def ReTrieveURL(input_url): 93 | headers = { 94 | "X-API-Key": REM_BG_API_KEY, 95 | } 96 | data = {"image_url": input_url} 97 | return requests.post( 98 | "https://api.remove.bg/v1.0/removebg", 99 | headers=headers, 100 | data=data, 101 | allow_redirects=True, 102 | stream=True, 103 | ) 104 | 105 | 106 | CMD_HELP.update( 107 | { 108 | "rbg": ".rbg or reply to any image (Warning: does not work on stickers.)\ 109 | \nUsage: Removes the background of images, using remove.bg API" 110 | } 111 | ) 112 | -------------------------------------------------------------------------------- /userbot/modules/reverse.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Thanks to @kandnub, for this awesome module !! 4 | # 5 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # 8 | """ Userbot module for reverse searching stickers and images on Google """ 9 | 10 | import io 11 | import os 12 | import urllib 13 | import requests 14 | from bs4 import BeautifulSoup 15 | import re 16 | from PIL import Image 17 | 18 | from userbot import bot, CMD_HELP 19 | from userbot.events import register 20 | 21 | opener = urllib.request.build_opener() 22 | useragent = "Mozilla/5.0 (Linux; Android 9; SM-G960F Build/PPR1.180610.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.70 Mobile Safari/537.36" 23 | opener.addheaders = [("User-agent", useragent)] 24 | 25 | 26 | @register(outgoing=True, pattern=r"^.reverse(?: |$)(\d*)") 27 | async def okgoogle(img): 28 | """ For .reverse command, Google search images and stickers. """ 29 | if os.path.isfile("okgoogle.png"): 30 | os.remove("okgoogle.png") 31 | 32 | message = await img.get_reply_message() 33 | if message and message.media: 34 | photo = io.BytesIO() 35 | await bot.download_media(message, photo) 36 | else: 37 | await img.edit("`Reply to photo or sticker nigger.`") 38 | return 39 | 40 | if photo: 41 | await img.edit("`Processing...`") 42 | try: 43 | image = Image.open(photo) 44 | except OSError: 45 | await img.edit("`Unsupported sexuality, most likely.`") 46 | return 47 | name = "okgoogle.png" 48 | image.save(name, "PNG") 49 | image.close() 50 | # https://stackoverflow.com/questions/23270175/google-reverse-image-search-using-post-request#28792943 51 | searchUrl = "https://www.google.com/searchbyimage/upload" 52 | multipart = {"encoded_image": (name, open(name, "rb")), "image_content": ""} 53 | response = requests.post(searchUrl, files=multipart, allow_redirects=False) 54 | fetchUrl = response.headers["Location"] 55 | 56 | if response != 400: 57 | await img.edit( 58 | "`Image successfully uploaded to Google. Maybe.`" 59 | "\n`Parsing source now. Maybe.`" 60 | ) 61 | else: 62 | await img.edit("`Google told me to fuck off.`") 63 | return 64 | 65 | os.remove(name) 66 | match = await ParseSauce(fetchUrl + "&preferences?hl=en&fg=1#languages") 67 | guess = match["best_guess"] 68 | imgspage = match["similar_images"] 69 | 70 | if guess and imgspage: 71 | await img.edit(f"[{guess}]({fetchUrl})\n\n`Looking for images...`") 72 | else: 73 | await img.edit("`Couldn't find anything for your uglyass.`") 74 | return 75 | 76 | lim = img.pattern_match.group(1) if img.pattern_match.group(1) else 3 77 | images = await scam(match, lim) 78 | yeet = [] 79 | for i in images: 80 | k = requests.get(i) 81 | yeet.append(k.content) 82 | try: 83 | await img.client.send_file( 84 | entity=await img.client.get_input_entity(img.chat_id), 85 | file=yeet, 86 | reply_to=img, 87 | ) 88 | except TypeError: 89 | pass 90 | await img.edit( 91 | f"[{guess}]({fetchUrl})\n\n[Visually similar images]({imgspage})" 92 | ) 93 | 94 | 95 | async def ParseSauce(googleurl): 96 | """Parse/Scrape the HTML code for the info we want.""" 97 | 98 | source = opener.open(googleurl).read() 99 | soup = BeautifulSoup(source, "html.parser") 100 | 101 | results = {"similar_images": "", "best_guess": ""} 102 | 103 | try: 104 | for similar_image in soup.findAll("input", {"class": "gLFyf"}): 105 | url = "https://www.google.com/search?tbm=isch&q=" + urllib.parse.quote_plus( 106 | similar_image.get("value") 107 | ) 108 | results["similar_images"] = url 109 | except BaseException: 110 | pass 111 | 112 | for best_guess in soup.findAll("div", attrs={"class": "r5a77d"}): 113 | results["best_guess"] = best_guess.get_text() 114 | 115 | return results 116 | 117 | 118 | async def scam(results, lim): 119 | 120 | single = opener.open(results["similar_images"]).read() 121 | decoded = single.decode("utf-8") 122 | 123 | imglinks = [] 124 | counter = 0 125 | 126 | pattern = r"^,\[\"(.*[.png|.jpg|.jpeg])\",[0-9]+,[0-9]+\]$" 127 | oboi = re.findall(pattern, decoded, re.I | re.M) 128 | 129 | for imglink in oboi: 130 | counter += 1 131 | if not counter >= int(lim): 132 | imglinks.append(imglink) 133 | else: 134 | break 135 | 136 | return imglinks 137 | 138 | 139 | CMD_HELP.update( 140 | { 141 | "reverse": ".reverse\ 142 | \nUsage: Reply to a pic/sticker to revers-search it on Google Images !!" 143 | } 144 | ) 145 | -------------------------------------------------------------------------------- /userbot/modules/sangmata.py: -------------------------------------------------------------------------------- 1 | # Port to userbot by @KeselekPermen69 2 | 3 | from telethon import events 4 | from telethon.errors.rpcerrorlist import YouBlockedUserError 5 | from asyncio.exceptions import TimeoutError 6 | from userbot.events import register 7 | import requests 8 | from userbot import bot, CMD_HELP 9 | 10 | @register(outgoing=True, pattern=r"^\.sg(?: |$)(.*)") 11 | async def lastname(steal): 12 | if steal.fwd_from: 13 | return 14 | if not steal.reply_to_msg_id: 15 | await steal.edit("`Reply to any user message.`") 16 | return 17 | message = await steal.get_reply_message() 18 | chat = "@SangMataInfo_bot" 19 | user_id = message.sender.id 20 | id = f"/search_id {user_id}" 21 | if message.sender.bot: 22 | await steal.edit("`Reply to actual users message.`") 23 | return 24 | await steal.edit("`Sit tight while I steal some data from NASA`") 25 | try: 26 | async with bot.conversation(chat) as conv: 27 | try: 28 | msg = await conv.send_message(id) 29 | r = await conv.get_response() 30 | response = await conv.get_response() 31 | except YouBlockedUserError: 32 | await steal.reply("`Please unblock @sangmatainfo_bot and try again`") 33 | return 34 | if response.text.startswith("No records found"): 35 | await steal.edit("`No records found for this user`") 36 | await steal.client.delete_messages( 37 | conv.chat_id, [msg.id, r.id, response.id] 38 | ) 39 | return 40 | else: 41 | respond = await conv.get_response() 42 | await steal.edit(f"{response.message}") 43 | await steal.client.delete_messages( 44 | conv.chat_id, [msg.id, r.id, response.id, respond.id] 45 | ) 46 | except TimeoutError: 47 | return await steal.edit("`Error: `@SangMataInfo_bot` is not responding!.`") 48 | 49 | 50 | 51 | CMD_HELP.update( 52 | { 53 | "sangmata": ".sg \ 54 | \nUsage: View user history.\n" 55 | } 56 | ) 57 | -------------------------------------------------------------------------------- /userbot/modules/screencap.py: -------------------------------------------------------------------------------- 1 | import io 2 | import requests 3 | from telethon import events 4 | from userbot import CMD_HELP, SS_LAYER_KEY, bot 5 | from userbot.events import register 6 | 7 | 8 | @register(outgoing=True, pattern="^.capscr(?: |$)(.*)") 9 | async def _(event): 10 | if event.fwd_from: 11 | return 12 | if SS_LAYER_KEY is None: 13 | await event.edit( 14 | "Need to get an API key from https://screenshotlayer.com/product \nModule stopping!" 15 | ) 16 | return 17 | await event.edit("Processing ...") 18 | sample_url = "https://api.screenshotlayer.com/api/capture?access_key={}&url={}&fullpage={}&viewport={}&format={}&force={}" 19 | input_str = event.pattern_match.group(1) 20 | response_api = requests.get( 21 | sample_url.format(SS_LAYER_KEY, input_str, "1", "2560x1440", "PNG", "1") 22 | ) 23 | # https://stackoverflow.com/a/23718458/4723940 24 | contentType = response_api.headers["content-type"] 25 | if "image" in contentType: 26 | with io.BytesIO(response_api.content) as screenshot_image: 27 | screenshot_image.name = "screencapture.png" 28 | try: 29 | await bot.send_file( 30 | event.chat_id, 31 | screenshot_image, 32 | caption=input_str, 33 | force_document=True, 34 | reply_to=event.message.reply_to_msg_id, 35 | ) 36 | await event.delete() 37 | except Exception as e: 38 | await event.edit(str(e)) 39 | else: 40 | await event.edit(response_api.text) 41 | 42 | 43 | CMD_HELP.update( 44 | { 45 | "screencap": ".capscr \ 46 | \nUsage get screenshot the url" 47 | } 48 | ) 49 | -------------------------------------------------------------------------------- /userbot/modules/screencapture.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | # The entire source code is OSSRPL except 'screencapture' which is MPL 7 | # License: MPL and OSSRPL 8 | 9 | import io 10 | 11 | from re import match 12 | from asyncio import sleep 13 | from userbot.events import register 14 | from userbot.utils import chrome, options 15 | from userbot import CMD_HELP 16 | 17 | 18 | @register(pattern=r".ss (.*)", outgoing=True) 19 | async def capture(url): 20 | """ For .ss command, capture a website's screenshot and send the photo. """ 21 | await url.edit("`Processing...`") 22 | chrome_options = await options() 23 | chrome_options.add_argument("--test-type") 24 | chrome_options.add_argument("--ignore-certificate-errors") 25 | chrome_options.arguments.remove("--window-size=1920x1080") 26 | driver = await chrome(chrome_options=chrome_options) 27 | input_str = url.pattern_match.group(1) 28 | link_match = match(r"\bhttps?://.*\.\S+", input_str) 29 | if link_match: 30 | link = link_match.group() 31 | else: 32 | return await url.edit("`I need a valid link to take screenshots from.`") 33 | driver.get(link) 34 | height = driver.execute_script( 35 | "return Math.max(document.body.scrollHeight, document.body.offsetHeight, " 36 | "document.documentElement.clientHeight, document.documentElement.scrollHeight, " 37 | "document.documentElement.offsetHeight);" 38 | ) 39 | width = driver.execute_script( 40 | "return Math.max(document.body.scrollWidth, document.body.offsetWidth, " 41 | "document.documentElement.clientWidth, document.documentElement.scrollWidth, " 42 | "document.documentElement.offsetWidth);" 43 | ) 44 | driver.set_window_size(width + 125, height + 125) 45 | wait_for = height / 1000 46 | await url.edit( 47 | "`Generating screenshot of the page...`" 48 | f"\n`Height of page = {height}px`" 49 | f"\n`Width of page = {width}px`" 50 | f"\n`Waiting ({int(wait_for)}s) for the page to load.`" 51 | ) 52 | await sleep(int(wait_for)) 53 | im_png = driver.get_screenshot_as_png() 54 | # saves screenshot of entire page 55 | driver.quit() 56 | message_id = url.message.id 57 | if url.reply_to_msg_id: 58 | message_id = url.reply_to_msg_id 59 | with io.BytesIO(im_png) as out_file: 60 | out_file.name = "screencapture.png" 61 | await url.edit("`Uploading screenshot as file..`") 62 | await url.client.send_file( 63 | url.chat_id, 64 | out_file, 65 | caption=input_str, 66 | force_document=True, 67 | reply_to=message_id, 68 | ) 69 | 70 | 71 | CMD_HELP.update( 72 | { 73 | "ss": ">`.ss `" 74 | "\nUsage: Takes a screenshot of a website and sends the screenshot." 75 | "\nExample of a valid URL : `https://www.google.com`" 76 | } 77 | ) 78 | -------------------------------------------------------------------------------- /userbot/modules/sed.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | # The entire source code is OSSRPL except 'sed' which is GPLv3 7 | # License: GPLv3 and OSSRPL 8 | """ Userbot command for sed. """ 9 | 10 | import re 11 | from sre_constants import error as sre_err 12 | from userbot import CMD_HELP 13 | from userbot.events import register 14 | 15 | DELIMITERS = ("/", ":", "|", "_") 16 | 17 | 18 | async def separate_sed(sed_string): 19 | """ Separate sed arguments. """ 20 | 21 | if len(sed_string) < 2: 22 | return 23 | 24 | if sed_string[2] in DELIMITERS and sed_string.count(sed_string[2]) >= 2: 25 | delim = sed_string[2] 26 | start = counter = 3 27 | while counter < len(sed_string): 28 | if sed_string[counter] == "\\": 29 | counter += 1 30 | 31 | elif sed_string[counter] == delim: 32 | replace = sed_string[start:counter] 33 | counter += 1 34 | start = counter 35 | break 36 | 37 | counter += 1 38 | 39 | else: 40 | return None 41 | 42 | while counter < len(sed_string): 43 | if ( 44 | sed_string[counter] == "\\" 45 | and counter + 1 < len(sed_string) 46 | and sed_string[counter + 1] == delim 47 | ): 48 | sed_string = sed_string[:counter] + sed_string[counter + 1 :] 49 | 50 | elif sed_string[counter] == delim: 51 | replace_with = sed_string[start:counter] 52 | counter += 1 53 | break 54 | 55 | counter += 1 56 | else: 57 | return replace, sed_string[start:], "" 58 | 59 | flags = "" 60 | if counter < len(sed_string): 61 | flags = sed_string[counter:] 62 | return replace, replace_with, flags.lower() 63 | return None 64 | 65 | 66 | @register(outgoing=True, pattern="^.s") 67 | async def sed(command): 68 | """ For sed command, use sed on Telegram. """ 69 | sed_result = await separate_sed(command.text) 70 | textx = await command.get_reply_message() 71 | if sed_result: 72 | if textx: 73 | to_fix = textx.text 74 | else: 75 | await command.edit( 76 | "`Master, I don't have brains. Well you too don't I guess.`" 77 | ) 78 | return 79 | 80 | repl, repl_with, flags = sed_result 81 | 82 | if not repl: 83 | await command.edit( 84 | "`Master, I don't have brains. Well you too don't I guess.`" 85 | ) 86 | return 87 | 88 | try: 89 | check = re.match(repl, to_fix, flags=re.IGNORECASE) 90 | if check and check.group(0).lower() == to_fix.lower(): 91 | await command.edit("`Boi!, that's a reply. Don't use sed`") 92 | return 93 | 94 | if "i" in flags and "g" in flags: 95 | text = re.sub(repl, repl_with, to_fix, flags=re.I).strip() 96 | elif "i" in flags: 97 | text = re.sub(repl, repl_with, to_fix, count=1, flags=re.I).strip() 98 | elif "g" in flags: 99 | text = re.sub(repl, repl_with, to_fix).strip() 100 | else: 101 | text = re.sub(repl, repl_with, to_fix, count=1).strip() 102 | except sre_err: 103 | await command.edit("B O I! [Learn Regex](https://regexone.com)") 104 | return 105 | if text: 106 | await command.edit(f"Did you mean? \n\n{text}") 107 | 108 | 109 | CMD_HELP.update( 110 | { 111 | "sed": ".s\ 112 | \nUsage: Replaces a word or words using sed.\ 113 | \nDelimiters: `/, :, |, _`" 114 | } 115 | ) 116 | -------------------------------------------------------------------------------- /userbot/modules/shalom.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | # You can find misc modules, which dont fit in anything xD 7 | """ Userbot module for other small commands. """ 8 | import sys 9 | from userbot import CMD_HELP 10 | from userbot.events import register 11 | 12 | 13 | @register(outgoing=True, pattern="^.shalom$") 14 | async def shalom(e): 15 | await e.edit( 16 | "\n☁️☁️☁️☁️☁️☁️☁️☁️☁️" 17 | "\n☁️⭐️☁️☁️☁️⭐️⭐️☁️☁️" 18 | "\n☁️⭐️☁️☁️⭐️☁️☁️⭐️☁️" 19 | "\n☁️⭐️☁️☁️⭐️☁️☁️⭐️☁️" 20 | "\n☁️⭐️☁️☁️⭐️☁️☁️⭐️☁️" 21 | "\n☁️☁️⭐️⭐️☁️☁️☁️⭐️☁️" 22 | "\n☁️☁️☁️☁️☁️☁️☁️☁️☁️" 23 | "\n☁️⭐️⭐️⭐️⭐️⭐️⭐️⭐️☁️" 24 | "\n☁️☁️☁️☁️⭐️☁️☁️☁️☁️" 25 | "\n☁️☁️☁️☁️⭐️☁️☁️☁️☁️" 26 | "\n☁️☁️☁️☁️⭐️☁️☁️☁️☁️" 27 | "\n☁️⭐️⭐️⭐️⭐️⭐️⭐️⭐️☁️" 28 | "\n☁️☁️☁️☁️☁️☁️☁️☁️☁️" 29 | "\n☁️⭐️⭐️⭐️⭐️⭐️⭐️☁️☁️" 30 | "\n☁️☁️☁️☁️⭐️☁️☁️⭐️☁️" 31 | "\n☁️☁️☁️☁️⭐️☁️☁️⭐️☁️" 32 | "\n☁️☁️☁️☁️⭐️☁️☁️⭐️☁️" 33 | "\n☁️⭐️⭐️⭐️⭐️⭐️⭐️☁️☁️" 34 | "\n☁️☁️☁️☁️☁️☁️☁️☁️☁️" 35 | "\n☁️⭐️⭐️⭐️⭐️⭐️⭐️⭐️☁️" 36 | "\n☁️⭐️☁️☁️☁️☁️☁️☁️☁️" 37 | "\n☁️⭐️☁️☁️☁️☁️☁️☁️☁️" 38 | "\n☁️⭐️☁️☁️☁️☁️☁️☁️☁️" 39 | "\n☁️⭐️☁️☁️☁️☁️☁️☁️☁️" 40 | "\n☁️☁️☁️☁️☁️☁️☁️☁️☁️" 41 | "\n☁️☁️⭐️⭐️⭐️⭐️⭐️☁️☁️" 42 | "\n☁️⭐️☁️☁️☁️☁️☁️⭐️☁️" 43 | "\n☁️⭐️☁️☁️☁️☁️☁️⭐️☁️" 44 | "\n☁️⭐️☁️☁️☁️☁️☁️⭐️☁️" 45 | "\n☁️☁️⭐️⭐️⭐️⭐️⭐️☁️☁️" 46 | "\n☁️☁️☁️☁️☁️☁️☁️☁️☁️" 47 | "\n☁️⭐️⭐️⭐️⭐️⭐️⭐️⭐️☁️" 48 | "\n☁️☁️☁️☁️☁️☁️⭐️☁️☁️" 49 | "\n☁️☁️☁️☁️⭐️⭐️☁️☁️☁️" 50 | "\n☁️☁️☁️☁️☁️☁️⭐️☁️☁️" 51 | "\n☁️⭐️⭐️⭐️⭐️⭐️⭐️⭐️☁️" 52 | "\n☁️☁️☁️☁️☁️☁️☁️☁️☁️" 53 | ) 54 | 55 | CMD_HELP.update( 56 | { 57 | "shalom": ".shalom\ 58 | \nUsage: gives a nice SHALOM as output." 59 | } 60 | ) 61 | -------------------------------------------------------------------------------- /userbot/modules/shortener.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 azrim. 2 | # All rights reserved. 3 | # 4 | # Licensed under the Raphielscape Public License, Version 1.d (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # 7 | 8 | from bitlyshortener import Shortener 9 | from re import match 10 | from userbot import CMD_HELP, BITLY_TOKEN, BOTLOG, BOTLOG_CHATID 11 | from userbot.events import register 12 | 13 | 14 | @register(outgoing=True, pattern=r"^\.bitly(?: |$)(.*)") 15 | async def shortener(short): 16 | """ 17 | Shorten link using bit.ly API 18 | """ 19 | if BITLY_TOKEN is not None: 20 | token = [f"{BITLY_TOKEN}"] 21 | reply = await short.get_reply_message() 22 | message = short.pattern_match.group(1) 23 | if message: 24 | pass 25 | elif reply: 26 | message = reply.text 27 | else: 28 | await short.edit("`Error! No URL given!`") 29 | return 30 | link_match = match(r"\bhttps?://.*\.\S+", message) 31 | if not link_match: 32 | await short.edit( 33 | "`Error! Please provide valid url!`\nexample: https://google.com" 34 | ) 35 | return 36 | urls = [f"{message}"] 37 | bitly = Shortener(tokens=token, max_cache_size=8192) 38 | raw_output = bitly.shorten_urls(urls) 39 | string_output = f"{raw_output}" 40 | output = string_output.replace("['", "").replace("']", "") 41 | await short.edit( 42 | f"`Your link shortened successfully!`\nHere is your link {output}" 43 | ) 44 | if BOTLOG: 45 | await short.client.send_message( 46 | BOTLOG_CHATID, f"`#SHORTLINK \nThis Your Link!`\n {output}" 47 | ) 48 | else: 49 | await short.edit( 50 | "Set bit.ly API token first\nGet from [here](https://bitly.com/a/sign_up)" 51 | ) 52 | 53 | 54 | CMD_HELP.update( 55 | { 56 | "bitly": ">`.bitly` or reply to message contains url" 57 | "\nUsage: Shorten link using bit.ly API" 58 | } 59 | ) 60 | -------------------------------------------------------------------------------- /userbot/modules/snips.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | """ Userbot module containing commands for keeping global notes. """ 6 | 7 | from sqlalchemy.orm.exc import UnmappedInstanceError 8 | 9 | from userbot.events import register 10 | from userbot import CMD_HELP, BOTLOG_CHATID 11 | 12 | 13 | @register(outgoing=True, pattern=r"\$\w*", ignore_unsafe=True, disable_errors=True) 14 | async def on_snip(event): 15 | """ Snips logic. """ 16 | try: 17 | from userbot.modules.sql_helper.snips_sql import get_snip 18 | except AttributeError: 19 | return 20 | name = event.text[1:] 21 | snip = get_snip(name) 22 | message_id_to_reply = event.message.reply_to_msg_id 23 | if not message_id_to_reply: 24 | message_id_to_reply = None 25 | if snip: 26 | if snip.f_mesg_id: 27 | msg_o = await event.client.get_messages( 28 | entity=BOTLOG_CHATID, ids=int(snip.f_mesg_id) 29 | ) 30 | await event.client.send_message( 31 | event.chat_id, 32 | msg_o.message, 33 | reply_to=message_id_to_reply, 34 | file=msg_o.media, 35 | ) 36 | elif snip.reply: 37 | await event.client.send_message( 38 | event.chat_id, snip.reply, reply_to=message_id_to_reply 39 | ) 40 | 41 | 42 | @register(outgoing=True, pattern="^.snip (\w*)") 43 | async def on_snip_save(event): 44 | """ For .snip command, saves snips for future use. """ 45 | try: 46 | from userbot.modules.sql_helper.snips_sql import add_snip 47 | except AtrributeError: 48 | await event.edit("`Running on Non-SQL mode!`") 49 | return 50 | keyword = event.pattern_match.group(1) 51 | string = event.text.partition(keyword)[2] 52 | msg = await event.get_reply_message() 53 | msg_id = None 54 | if msg and msg.media and not string: 55 | if BOTLOG_CHATID: 56 | await event.client.send_message( 57 | BOTLOG_CHATID, 58 | f"#SNIP\ 59 | \nKEYWORD: {keyword}\ 60 | \n\nThe following message is saved as the data for the snip, please do NOT delete it !!", 61 | ) 62 | msg_o = await event.client.forward_messages( 63 | entity=BOTLOG_CHATID, messages=msg, from_peer=event.chat_id, silent=True 64 | ) 65 | msg_id = msg_o.id 66 | else: 67 | await event.edit( 68 | "`Saving snips with media requires the BOTLOG_CHATID to be set.`" 69 | ) 70 | return 71 | elif event.reply_to_msg_id and not string: 72 | rep_msg = await event.get_reply_message() 73 | string = rep_msg.text 74 | success = "**Snip {} successfully. Use** `${}` **anywhere to get it**" 75 | try: 76 | if add_snip(keyword, string, msg_id) is False: 77 | await event.edit(success.format("updated", keyword)) 78 | else: 79 | await event.edit(success.format("saved", keyword)) 80 | except UnmappedInstanceError: 81 | return await event.edit( 82 | f"**Error: Snip** `{keyword}` **already exists.**") 83 | 84 | 85 | @register(outgoing=True, pattern="^.snips$") 86 | async def on_snip_list(event): 87 | """ For .snips command, lists snips saved by you. """ 88 | try: 89 | from userbot.modules.sql_helper.snips_sql import get_snips 90 | except AttributeError: 91 | await event.edit("`Running on Non-SQL mode!`") 92 | return 93 | 94 | message = "`No snips available right now.`" 95 | all_snips = get_snips() 96 | for a_snip in all_snips: 97 | if message == "`No snips available right now.`": 98 | message = "Available snips:\n" 99 | message += f"`${a_snip.snip}`\n" 100 | await event.edit(message) 101 | 102 | 103 | @register(outgoing=True, pattern="^.remsnip (\w*)") 104 | async def on_snip_delete(event): 105 | """ For .remsnip command, deletes a snip. """ 106 | try: 107 | from userbot.modules.sql_helper.snips_sql import remove_snip 108 | except AttributeError: 109 | await event.edit("`Running on Non-SQL mode!`") 110 | return 111 | name = event.pattern_match.group(1) 112 | if remove_snip(name) is True: 113 | await event.edit(f"`Successfully deleted snip:` **{name}**") 114 | else: 115 | await event.edit(f"`Couldn't find snip:` **{name}**") 116 | 117 | 118 | CMD_HELP.update( 119 | { 120 | "snips": "\ 121 | $\ 122 | \nUsage: Gets the specified snip, anywhere.\ 123 | \n\n.snip or reply to a message with .snip \ 124 | \nUsage: Saves the message as a snip (global note) with the name. (Works with pics, docs, and stickers too!)\ 125 | \n\n.snips\ 126 | \nUsage: Gets all saved snips.\ 127 | \n\n.remsnip \ 128 | \nUsage: Deletes the specified snip.\ 129 | " 130 | } 131 | ) 132 | -------------------------------------------------------------------------------- /userbot/modules/spam.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | 6 | import asyncio 7 | from asyncio import sleep 8 | 9 | from userbot import BOTLOG, BOTLOG_CHATID, CMD_HELP 10 | from userbot.events import register 11 | 12 | 13 | @register(outgoing=True, pattern="^.cspam (.*)") 14 | async def tmeme(e): 15 | cspam = str(e.pattern_match.group(1)) 16 | message = cspam.replace(" ", "") 17 | await e.delete() 18 | for letter in message: 19 | await e.respond(letter) 20 | if BOTLOG: 21 | await e.client.send_message( 22 | BOTLOG_CHATID, "#CSPAM\n" "TSpam was executed successfully" 23 | ) 24 | 25 | 26 | @register(outgoing=True, pattern="^.wspam (.*)") 27 | async def tmeme(e): 28 | wspam = str(e.pattern_match.group(1)) 29 | message = wspam.split() 30 | await e.delete() 31 | for word in message: 32 | await e.respond(word) 33 | if BOTLOG: 34 | await e.client.send_message( 35 | BOTLOG_CHATID, "#WSPAM\n" "WSpam was executed successfully" 36 | ) 37 | 38 | 39 | @register(outgoing=True, pattern="^.spam (.*)") 40 | async def spammer(e): 41 | counter = int(e.pattern_match.group(1).split(" ", 1)[0]) 42 | spam_message = str(e.pattern_match.group(1).split(" ", 1)[1]) 43 | await e.delete() 44 | await asyncio.wait([e.respond(spam_message) for i in range(counter)]) 45 | if BOTLOG: 46 | await e.client.send_message( 47 | BOTLOG_CHATID, "#SPAM\n" "Spam was executed successfully" 48 | ) 49 | 50 | 51 | @register(outgoing=True, pattern="^.picspam") 52 | async def tiny_pic_spam(e): 53 | message = e.text 54 | text = message.split() 55 | counter = int(text[1]) 56 | link = str(text[2]) 57 | await e.delete() 58 | for _ in range(1, counter): 59 | await e.client.send_file(e.chat_id, link) 60 | if BOTLOG: 61 | await e.client.send_message( 62 | BOTLOG_CHATID, "#PICSPAM\n" "PicSpam was executed successfully" 63 | ) 64 | 65 | 66 | @register(outgoing=True, pattern="^.delayspam (.*)") 67 | async def spammer(e): 68 | spamDelay = float(e.pattern_match.group(1).split(" ", 2)[0]) 69 | counter = int(e.pattern_match.group(1).split(" ", 2)[1]) 70 | spam_message = str(e.pattern_match.group(1).split(" ", 2)[2]) 71 | await e.delete() 72 | for _ in range(1, counter): 73 | await e.respond(spam_message) 74 | await sleep(spamDelay) 75 | if BOTLOG: 76 | await e.client.send_message( 77 | BOTLOG_CHATID, "#DelaySPAM\n" "DelaySpam was executed successfully" 78 | ) 79 | 80 | 81 | CMD_HELP.update( 82 | { 83 | "spam": ".cspam \ 84 | \nUsage: Spam the text letter by letter.\ 85 | \n\n.spam \ 86 | \nUsage: Floods text in the chat !!\ 87 | \n\n.wspam \ 88 | \nUsage: Spam the text word by word.\ 89 | \n\n.picspam \ 90 | \nUsage: As if text spam was not enough !!\ 91 | \n\n.delayspam \ 92 | \nUsage: .bigspam but with custom delay.\ 93 | \n\n\nNOTE : Spam at your own risk !!" 94 | } 95 | ) 96 | -------------------------------------------------------------------------------- /userbot/modules/sql_helper/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortifying/OUBnew/4bd421d606a22f99a5a0d599ba6327088cf1caa0/userbot/modules/sql_helper/.DS_Store -------------------------------------------------------------------------------- /userbot/modules/sql_helper/__init__.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | from sqlalchemy.ext.declarative import declarative_base 3 | from sqlalchemy.orm import sessionmaker, scoped_session 4 | from userbot import DB_URI 5 | 6 | BASE = declarative_base() 7 | 8 | 9 | def start() -> scoped_session: 10 | engine = create_engine(DB_URI) 11 | BASE.metadata.bind = engine 12 | BASE.metadata.create_all(engine) 13 | return scoped_session(sessionmaker(bind=engine, autoflush=False)) 14 | 15 | 16 | def delete_table(table_name): 17 | metadata = MetaData() 18 | metadata.reflect(engine) 19 | table = metadata.tables.get(table_name) 20 | if table is not None: 21 | LOGS.info(f"Deleting '{table_name}' table...") 22 | BASE.metadata.drop_all(engine, [table], checkfirst=True) 23 | 24 | 25 | SESSION = start() 26 | -------------------------------------------------------------------------------- /userbot/modules/sql_helper/blacklist_sql.py: -------------------------------------------------------------------------------- 1 | try: 2 | from userbot.modules.sql_helper import SESSION, BASE 3 | except ImportError: 4 | raise AttributeError 5 | from sqlalchemy import Column, UnicodeText, Numeric, String 6 | import threading 7 | 8 | 9 | class BlackListFilters(BASE): 10 | __tablename__ = "blacklist" 11 | chat_id = Column(String(14), primary_key=True) 12 | trigger = Column(UnicodeText, primary_key=True, nullable=False) 13 | 14 | def __init__(self, chat_id, trigger): 15 | self.chat_id = str(chat_id) # ensure string 16 | self.trigger = trigger 17 | 18 | def __repr__(self): 19 | return "" % (self.trigger, self.chat_id) 20 | 21 | def __eq__(self, other): 22 | return bool( 23 | isinstance(other, BlackListFilters) 24 | and self.chat_id == other.chat_id 25 | and self.trigger == other.trigger 26 | ) 27 | 28 | 29 | BlackListFilters.__table__.create(checkfirst=True) 30 | 31 | BLACKLIST_FILTER_INSERTION_LOCK = threading.RLock() 32 | 33 | CHAT_BLACKLISTS = {} 34 | 35 | 36 | def add_to_blacklist(chat_id, trigger): 37 | with BLACKLIST_FILTER_INSERTION_LOCK: 38 | blacklist_filt = BlackListFilters(str(chat_id), trigger) 39 | 40 | SESSION.merge(blacklist_filt) # merge to avoid duplicate key issues 41 | SESSION.commit() 42 | CHAT_BLACKLISTS.setdefault(str(chat_id), set()).add(trigger) 43 | 44 | 45 | def rm_from_blacklist(chat_id, trigger): 46 | with BLACKLIST_FILTER_INSERTION_LOCK: 47 | blacklist_filt = SESSION.query(BlackListFilters).get((str(chat_id), trigger)) 48 | if blacklist_filt: 49 | if trigger in CHAT_BLACKLISTS.get(str(chat_id), set()): # sanity check 50 | CHAT_BLACKLISTS.get(str(chat_id), set()).remove(trigger) 51 | 52 | SESSION.delete(blacklist_filt) 53 | SESSION.commit() 54 | return True 55 | 56 | SESSION.close() 57 | return False 58 | 59 | 60 | def get_chat_blacklist(chat_id): 61 | return CHAT_BLACKLISTS.get(str(chat_id), set()) 62 | 63 | 64 | def num_blacklist_filters(): 65 | try: 66 | return SESSION.query(BlackListFilters).count() 67 | finally: 68 | SESSION.close() 69 | 70 | 71 | def num_blacklist_chat_filters(chat_id): 72 | try: 73 | return ( 74 | SESSION.query(BlackListFilters.chat_id) 75 | .filter(BlackListFilters.chat_id == str(chat_id)) 76 | .count() 77 | ) 78 | finally: 79 | SESSION.close() 80 | 81 | 82 | def num_blacklist_filter_chats(): 83 | try: 84 | return SESSION.query(func.count(distinct(BlackListFilters.chat_id))).scalar() 85 | finally: 86 | SESSION.close() 87 | 88 | 89 | def __load_chat_blacklists(): 90 | global CHAT_BLACKLISTS 91 | try: 92 | chats = SESSION.query(BlackListFilters.chat_id).distinct().all() 93 | for (chat_id,) in chats: # remove tuple by ( ,) 94 | CHAT_BLACKLISTS[chat_id] = [] 95 | 96 | all_filters = SESSION.query(BlackListFilters).all() 97 | for x in all_filters: 98 | CHAT_BLACKLISTS[x.chat_id] += [x.trigger] 99 | 100 | CHAT_BLACKLISTS = {x: set(y) for x, y in CHAT_BLACKLISTS.items()} 101 | 102 | finally: 103 | SESSION.close() 104 | 105 | 106 | __load_chat_blacklists() 107 | -------------------------------------------------------------------------------- /userbot/modules/sql_helper/fban_sql.py: -------------------------------------------------------------------------------- 1 | try: 2 | from userbot.modules.sql_helper import SESSION, BASE 3 | except ImportError: 4 | raise AttributeError 5 | 6 | from sqlalchemy import Column, String, UnicodeText 7 | 8 | 9 | class Fban(BASE): 10 | __tablename__ = "fban" 11 | chat_id = Column(String(14), primary_key=True) 12 | fed_name = Column(UnicodeText) 13 | 14 | def __init__(self, chat_id, fed_name): 15 | self.chat_id = str(chat_id) 16 | self.fed_name = fed_name 17 | 18 | 19 | Fban.__table__.create(checkfirst=True) 20 | 21 | 22 | def get_flist(): 23 | try: 24 | return SESSION.query(Fban).all() 25 | finally: 26 | SESSION.close() 27 | 28 | 29 | def add_flist(chat_id, fed_name): 30 | adder = Fban(str(chat_id), fed_name) 31 | SESSION.add(adder) 32 | SESSION.commit() 33 | 34 | 35 | def del_flist(chat_id): 36 | rem = SESSION.query(Fban).get(str(chat_id)) 37 | if rem: 38 | SESSION.delete(rem) 39 | SESSION.commit() 40 | -------------------------------------------------------------------------------- /userbot/modules/sql_helper/filter_sql.py: -------------------------------------------------------------------------------- 1 | try: 2 | from userbot.modules.sql_helper import SESSION, BASE 3 | except ImportError: 4 | raise AttributeError 5 | from sqlalchemy import Column, UnicodeText, Numeric, String 6 | 7 | 8 | class Filters(BASE): 9 | __tablename__ = "filters" 10 | chat_id = Column(String(14), primary_key=True) 11 | keyword = Column(UnicodeText, primary_key=True, nullable=False) 12 | reply = Column(UnicodeText) 13 | f_mesg_id = Column(Numeric) 14 | 15 | def __init__(self, chat_id, keyword, reply, f_mesg_id): 16 | self.chat_id = str(chat_id) 17 | self.keyword = keyword 18 | self.reply = reply 19 | self.f_mesg_id = f_mesg_id 20 | 21 | def __eq__(self, other): 22 | return bool( 23 | isinstance(other, Filters) 24 | and self.chat_id == other.chat_id 25 | and self.keyword == other.keyword 26 | ) 27 | 28 | 29 | Filters.__table__.create(checkfirst=True) 30 | 31 | 32 | def get_filter(chat_id, keyword): 33 | try: 34 | return SESSION.query(Filters).get((str(chat_id), keyword)) 35 | finally: 36 | SESSION.close() 37 | 38 | 39 | def get_filters(chat_id): 40 | try: 41 | return SESSION.query(Filters).filter(Filters.chat_id == str(chat_id)).all() 42 | finally: 43 | SESSION.close() 44 | 45 | 46 | def add_filter(chat_id, keyword, reply, f_mesg_id): 47 | to_check = get_filter(chat_id, keyword) 48 | if not to_check: 49 | adder = Filters(str(chat_id), keyword, reply, f_mesg_id) 50 | SESSION.add(adder) 51 | SESSION.commit() 52 | return True 53 | else: 54 | rem = SESSION.query(Filters).get((str(chat_id), keyword)) 55 | SESSION.delete(rem) 56 | SESSION.commit() 57 | adder = Filters(str(chat_id), keyword, reply, f_mesg_id) 58 | SESSION.add(adder) 59 | SESSION.commit() 60 | return False 61 | 62 | 63 | def remove_filter(chat_id, keyword): 64 | to_check = get_filter(chat_id, keyword) 65 | if not to_check: 66 | return False 67 | else: 68 | rem = SESSION.query(Filters).get((str(chat_id), keyword)) 69 | SESSION.delete(rem) 70 | SESSION.commit() 71 | return True 72 | -------------------------------------------------------------------------------- /userbot/modules/sql_helper/globals.py: -------------------------------------------------------------------------------- 1 | try: 2 | from userbot.modules.sql_helper import SESSION, BASE 3 | except ImportError: 4 | raise AttributeError 5 | 6 | from sqlalchemy import Column, String, UnicodeText 7 | 8 | 9 | class Globals(BASE): 10 | __tablename__ = "globals" 11 | variable = Column(String, primary_key=True, nullable=False) 12 | value = Column(UnicodeText, primary_key=True, nullable=False) 13 | 14 | def __init__(self, variable, value): 15 | self.variable = str(variable) 16 | self.value = value 17 | 18 | 19 | Globals.__table__.create(checkfirst=True) 20 | 21 | 22 | def gvarstatus(variable): 23 | try: 24 | return ( 25 | SESSION.query(Globals) 26 | .filter(Globals.variable == str(variable)) 27 | .first() 28 | .value 29 | ) 30 | except BaseException: 31 | return None 32 | finally: 33 | SESSION.close() 34 | 35 | 36 | def addgvar(variable, value): 37 | if SESSION.query(Globals).filter(Globals.variable == str(variable)).one_or_none(): 38 | delgvar(variable) 39 | adder = Globals(str(variable), value) 40 | SESSION.add(adder) 41 | SESSION.commit() 42 | 43 | 44 | def delgvar(variable): 45 | rem = ( 46 | SESSION.query(Globals) 47 | .filter(Globals.variable == str(variable)) 48 | .delete(synchronize_session="fetch") 49 | ) 50 | if rem: 51 | SESSION.commit() 52 | -------------------------------------------------------------------------------- /userbot/modules/sql_helper/gmute_sql.py: -------------------------------------------------------------------------------- 1 | try: 2 | from userbot.modules.sql_helper import SESSION, BASE 3 | except ImportError: 4 | raise AttributeError 5 | 6 | from sqlalchemy import Column, String, UnicodeText 7 | 8 | 9 | class GMute(BASE): 10 | __tablename__ = "gmute" 11 | sender = Column(String(14), primary_key=True) 12 | 13 | def __init__(self, sender): 14 | self.sender = str(sender) 15 | 16 | 17 | GMute.__table__.create(checkfirst=True) 18 | 19 | 20 | def is_gmuted(_sender_id): 21 | try: 22 | return SESSION.query(GMute).all() 23 | except BaseException: 24 | return None 25 | finally: 26 | SESSION.close() 27 | 28 | 29 | def gmute(sender): 30 | adder = GMute(str(sender)) 31 | SESSION.add(adder) 32 | SESSION.commit() 33 | 34 | 35 | def ungmute(sender): 36 | rem = SESSION.query(GMute).get((str(sender))) 37 | if rem: 38 | SESSION.delete(rem) 39 | SESSION.commit() 40 | -------------------------------------------------------------------------------- /userbot/modules/sql_helper/google_drive_sql.py: -------------------------------------------------------------------------------- 1 | from userbot.modules.sql_helper import SESSION, BASE 2 | from sqlalchemy import Column, String, Text 3 | 4 | 5 | class GoogleDriveCreds(BASE): 6 | __tablename__ = "gdrive" 7 | user = Column(String, primary_key=True) 8 | credentials = Column(Text, nullable=False) 9 | 10 | def __init__(self, user): 11 | self.user = user 12 | 13 | 14 | GoogleDriveCreds.__table__.create(checkfirst=True) 15 | 16 | 17 | def save_credentials(user, credentials): 18 | saved_credentials = SESSION.query(GoogleDriveCreds).get(user) 19 | if not saved_credentials: 20 | saved_credentials = GoogleDriveCreds(user) 21 | 22 | saved_credentials.credentials = credentials 23 | 24 | SESSION.add(saved_credentials) 25 | SESSION.commit() 26 | return True 27 | 28 | 29 | def get_credentials(user): 30 | try: 31 | saved_credentials = SESSION.query(GoogleDriveCreds).get(user) 32 | creds = None 33 | 34 | if saved_credentials is not None: 35 | creds = saved_credentials.credentials 36 | return creds 37 | finally: 38 | SESSION.close() 39 | 40 | 41 | def clear_credentials(user): 42 | saved_credentials = SESSION.query(GoogleDriveCreds).get(user) 43 | if saved_credentials: 44 | SESSION.delete(saved_credentials) 45 | SESSION.commit() 46 | return True 47 | -------------------------------------------------------------------------------- /userbot/modules/sql_helper/keep_read_sql.py: -------------------------------------------------------------------------------- 1 | try: 2 | from userbot.modules.sql_helper import SESSION, BASE 3 | except ImportError: 4 | raise AttributeError 5 | 6 | from sqlalchemy import Column, String 7 | 8 | 9 | class KRead(BASE): 10 | __tablename__ = "kread" 11 | groupid = Column(String(14), primary_key=True) 12 | 13 | def __init__(self, sender): 14 | self.groupid = str(sender) 15 | 16 | 17 | KRead.__table__.create(checkfirst=True) 18 | 19 | 20 | def is_kread(): 21 | try: 22 | return SESSION.query(KRead).all() 23 | except BaseException: 24 | return None 25 | finally: 26 | SESSION.close() 27 | 28 | 29 | def kread(chat): 30 | adder = KRead(str(chat)) 31 | SESSION.add(adder) 32 | SESSION.commit() 33 | 34 | 35 | def unkread(chat): 36 | rem = SESSION.query(KRead).get((str(chat))) 37 | if rem: 38 | SESSION.delete(rem) 39 | SESSION.commit() 40 | -------------------------------------------------------------------------------- /userbot/modules/sql_helper/lydia_sql.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import Column, UnicodeText, LargeBinary, Numeric 2 | from sql_helpers import SESSION, BASE 3 | 4 | 5 | class LydiaAI(BASE): 6 | __tablename__ = "lydia_ai" 7 | user_id = Column(Numeric, primary_key=True) 8 | chat_id = Column(Numeric, primary_key=True) 9 | session_id = Column(UnicodeText) 10 | session_expires = Column(Numeric) 11 | 12 | def __init__(self, user_id, chat_id, session_id, session_expires): 13 | self.user_id = user_id 14 | self.chat_id = chat_id 15 | self.session_id = session_id 16 | self.session_expires = session_expires 17 | 18 | 19 | LydiaAI.__table__.create(checkfirst=True) 20 | 21 | 22 | def get_s(user_id, chat_id): 23 | try: 24 | return SESSION.query(LydiaAI).get((user_id, chat_id)) 25 | except: 26 | return None 27 | finally: 28 | SESSION.close() 29 | 30 | 31 | def get_all_s(): 32 | try: 33 | return SESSION.query(LydiaAI).all() 34 | except: 35 | return None 36 | finally: 37 | SESSION.close() 38 | 39 | 40 | def add_s(user_id, chat_id, session_id, session_expires): 41 | adder = SESSION.query(LydiaAI).get((user_id, chat_id)) 42 | if adder: 43 | adder.session_id = session_id 44 | adder.session_expires = session_expires 45 | else: 46 | adder = LydiaAI(user_id, chat_id, session_id, session_expires) 47 | SESSION.add(adder) 48 | SESSION.commit() 49 | 50 | 51 | def remove_s(user_id, chat_id): 52 | note = SESSION.query(LydiaAI).get((user_id, chat_id)) 53 | if note: 54 | SESSION.delete(note) 55 | SESSION.commit() 56 | -------------------------------------------------------------------------------- /userbot/modules/sql_helper/notes_sql.py: -------------------------------------------------------------------------------- 1 | try: 2 | from userbot.modules.sql_helper import SESSION, BASE 3 | except ImportError: 4 | raise AttributeError 5 | from sqlalchemy import Column, UnicodeText, Numeric, String 6 | 7 | 8 | class Notes(BASE): 9 | __tablename__ = "notes" 10 | chat_id = Column(String(14), primary_key=True) 11 | keyword = Column(UnicodeText, primary_key=True, nullable=False) 12 | reply = Column(UnicodeText) 13 | f_mesg_id = Column(Numeric) 14 | 15 | def __init__(self, chat_id, keyword, reply, f_mesg_id): 16 | self.chat_id = str(chat_id) 17 | self.keyword = keyword 18 | self.reply = reply 19 | self.f_mesg_id = f_mesg_id 20 | 21 | 22 | Notes.__table__.create(checkfirst=True) 23 | 24 | 25 | def get_note(chat_id, keyword): 26 | try: 27 | return SESSION.query(Notes).get((str(chat_id), keyword)) 28 | finally: 29 | SESSION.close() 30 | 31 | 32 | def get_notes(chat_id): 33 | try: 34 | return SESSION.query(Notes).filter(Notes.chat_id == str(chat_id)).all() 35 | finally: 36 | SESSION.close() 37 | 38 | 39 | def add_note(chat_id, keyword, reply, f_mesg_id): 40 | to_check = get_note(chat_id, keyword) 41 | if not to_check: 42 | adder = Notes(str(chat_id), keyword, reply, f_mesg_id) 43 | SESSION.add(adder) 44 | SESSION.commit() 45 | return True 46 | else: 47 | rem = SESSION.query(Notes).get((str(chat_id), keyword)) 48 | SESSION.delete(rem) 49 | SESSION.commit() 50 | adder = Notes(str(chat_id), keyword, reply, f_mesg_id) 51 | SESSION.add(adder) 52 | SESSION.commit() 53 | return False 54 | 55 | 56 | def rm_note(chat_id, keyword): 57 | to_check = get_note(chat_id, keyword) 58 | if not to_check: 59 | return False 60 | else: 61 | rem = SESSION.query(Notes).get((str(chat_id), keyword)) 62 | SESSION.delete(rem) 63 | SESSION.commit() 64 | return True 65 | -------------------------------------------------------------------------------- /userbot/modules/sql_helper/pm_permit_sql.py: -------------------------------------------------------------------------------- 1 | try: 2 | from userbot.modules.sql_helper import SESSION, BASE 3 | except ImportError: 4 | raise AttributeError 5 | from sqlalchemy import Column, String, UnicodeText, Boolean, Integer, distinct, func 6 | 7 | 8 | class PMPermit(BASE): 9 | __tablename__ = "pmpermit" 10 | chat_id = Column(String(14), primary_key=True) 11 | 12 | def __init__(self, chat_id): 13 | self.chat_id = str(chat_id) # ensure string 14 | 15 | 16 | PMPermit.__table__.create(checkfirst=True) 17 | 18 | 19 | def is_approved(chat_id): 20 | try: 21 | return SESSION.query(PMPermit).filter(PMPermit.chat_id == str(chat_id)).one() 22 | except BaseException: 23 | return None 24 | finally: 25 | SESSION.close() 26 | 27 | 28 | def approve(chat_id): 29 | adder = PMPermit(str(chat_id)) 30 | SESSION.add(adder) 31 | SESSION.commit() 32 | 33 | 34 | def dissprove(chat_id): 35 | rem = SESSION.query(PMPermit).get(str(chat_id)) 36 | if rem: 37 | SESSION.delete(rem) 38 | SESSION.commit() 39 | -------------------------------------------------------------------------------- /userbot/modules/sql_helper/snips_sql.py: -------------------------------------------------------------------------------- 1 | try: 2 | from userbot.modules.sql_helper import SESSION, BASE 3 | except ImportError: 4 | raise AttributeError 5 | 6 | from sqlalchemy import Column, UnicodeText, LargeBinary, Numeric 7 | 8 | 9 | class Snips(BASE): 10 | __tablename__ = "snips" 11 | snip = Column(UnicodeText, primary_key=True) 12 | reply = Column(UnicodeText) 13 | f_mesg_id = Column(Numeric) 14 | 15 | def __init__(self, snip, reply, f_mesg_id): 16 | self.snip = snip 17 | self.reply = reply 18 | self.f_mesg_id = f_mesg_id 19 | 20 | 21 | Snips.__table__.create(checkfirst=True) 22 | 23 | 24 | def get_snip(keyword): 25 | try: 26 | return SESSION.query(Snips).get(keyword) 27 | finally: 28 | SESSION.close() 29 | 30 | 31 | def get_snips(): 32 | try: 33 | return SESSION.query(Snips).all() 34 | finally: 35 | SESSION.close() 36 | 37 | 38 | def add_snip(keyword, reply, f_mesg_id): 39 | to_check = get_snip(keyword) 40 | if not to_check: 41 | adder = Snips(keyword, reply, f_mesg_id) 42 | SESSION.add(adder) 43 | SESSION.commit() 44 | return True 45 | else: 46 | rem = SESSION.query(Snips).filter(Snips.snip == keyword) 47 | SESSION.delete(rem) 48 | SESSION.commit() 49 | adder = Snips(keyword, reply, f_mesg_id) 50 | SESSION.add(adder) 51 | SESSION.commit() 52 | return False 53 | 54 | 55 | def remove_snip(keyword): 56 | to_check = get_snip(keyword) 57 | if not to_check: 58 | return False 59 | else: 60 | rem = SESSION.query(Snips).filter(Snips.snip == keyword) 61 | rem.delete() 62 | SESSION.commit() 63 | return True 64 | -------------------------------------------------------------------------------- /userbot/modules/sql_helper/spam_mute_sql.py: -------------------------------------------------------------------------------- 1 | try: 2 | from userbot.modules.sql_helper import SESSION, BASE 3 | except ImportError: 4 | raise AttributeError 5 | 6 | from sqlalchemy import Column, String 7 | 8 | 9 | class Mute(BASE): 10 | __tablename__ = "muted" 11 | chat_id = Column(String(14), primary_key=True) 12 | sender = Column(String(14), primary_key=True) 13 | 14 | def __init__(self, chat_id, sender): 15 | self.chat_id = str(chat_id) # ensure string 16 | self.sender = str(sender) 17 | 18 | 19 | Mute.__table__.create(checkfirst=True) 20 | 21 | 22 | def is_muted(chat_id): 23 | try: 24 | return SESSION.query(Mute).filter(Mute.chat_id == str(chat_id)).all() 25 | except BaseException: 26 | return None 27 | finally: 28 | SESSION.close() 29 | 30 | 31 | def mute(chat_id, sender): 32 | adder = Mute(str(chat_id), str(sender)) 33 | SESSION.add(adder) 34 | SESSION.commit() 35 | 36 | 37 | def unmute(chat_id, sender): 38 | rem = SESSION.query(Mute).get(((str(chat_id)), (str(sender)))) 39 | if rem: 40 | SESSION.delete(rem) 41 | SESSION.commit() 42 | -------------------------------------------------------------------------------- /userbot/modules/sql_helper/welcome_sql.py: -------------------------------------------------------------------------------- 1 | try: 2 | from userbot.modules.sql_helper import SESSION, BASE 3 | except ImportError: 4 | raise AttributeError 5 | 6 | from sqlalchemy import BigInteger, Column, Numeric, String, UnicodeText 7 | 8 | 9 | class Welcome(BASE): 10 | __tablename__ = "welcome" 11 | chat_id = Column(String(14), primary_key=True) 12 | previous_welcome = Column(BigInteger) 13 | reply = Column(UnicodeText) 14 | f_mesg_id = Column(Numeric) 15 | 16 | def __init__(self, chat_id, previous_welcome, reply, f_mesg_id): 17 | self.chat_id = str(chat_id) 18 | self.previous_welcome = previous_welcome 19 | self.reply = reply 20 | self.f_mesg_id = f_mesg_id 21 | 22 | 23 | Welcome.__table__.create(checkfirst=True) 24 | 25 | 26 | def get_welcome(chat_id): 27 | try: 28 | return SESSION.query(Welcome).get(str(chat_id)) 29 | finally: 30 | SESSION.close() 31 | 32 | 33 | def get_current_welcome_settings(chat_id): 34 | try: 35 | return SESSION.query(Welcome).filter(Welcome.chat_id == str(chat_id)).one() 36 | except BaseException: 37 | return None 38 | finally: 39 | SESSION.close() 40 | 41 | 42 | def add_welcome_setting(chat_id, previous_welcome, reply, f_mesg_id): 43 | to_check = get_welcome(chat_id) 44 | if not to_check: 45 | adder = Welcome(chat_id, previous_welcome, reply, f_mesg_id) 46 | SESSION.add(adder) 47 | SESSION.commit() 48 | return True 49 | else: 50 | rem = SESSION.query(Welcome).get(str(chat_id)) 51 | SESSION.delete(rem) 52 | SESSION.commit() 53 | adder = Welcome(chat_id, previous_welcome, reply, f_mesg_id) 54 | SESSION.commit() 55 | return False 56 | 57 | 58 | def rm_welcome_setting(chat_id): 59 | try: 60 | rem = SESSION.query(Welcome).get(str(chat_id)) 61 | if rem: 62 | SESSION.delete(rem) 63 | SESSION.commit() 64 | return True 65 | except BaseException: 66 | return False 67 | 68 | 69 | def update_previous_welcome(chat_id, previous_welcome): 70 | row = SESSION.query(Welcome).get(str(chat_id)) 71 | row.previous_welcome = previous_welcome 72 | SESSION.commit() 73 | -------------------------------------------------------------------------------- /userbot/modules/ssvideo.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Alfiananda P.A 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.d (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | 7 | import asyncio 8 | import os 9 | import time 10 | 11 | from telethon.tl.types import DocumentAttributeFilename 12 | from userbot import CMD_HELP, bot 13 | from userbot.events import register 14 | from userbot.utils import progress 15 | 16 | 17 | @register(outgoing=True, pattern=r"^\.ssvideo(?: |$)(.*)") 18 | async def ssvideo(framecap): 19 | if not framecap.reply_to_msg_id: 20 | return await framecap.edit("`reply to video!`") 21 | reply_message = await framecap.get_reply_message() 22 | if not reply_message.media: 23 | return await framecap.edit("`reply to a video!`") 24 | try: 25 | frame = int(framecap.pattern_match.group(1)) 26 | if frame > 10: 27 | return await framecap.edit("`hey..dont put that much`") 28 | except BaseException: 29 | return await framecap.edit("`Please input number of frame!`") 30 | if (reply_message.photo 31 | or (DocumentAttributeFilename(file_name="AnimatedSticker.tgs") 32 | in reply_message.media.document.attributes) 33 | or (DocumentAttributeFilename(file_name="sticker.webp") 34 | in reply_message.media.document.attributes) 35 | ): 36 | return await framecap.edit("`Unsupported files!`") 37 | c_time = time.time() 38 | await framecap.edit("`Downloading media...`") 39 | ss = await bot.download_media( 40 | reply_message, 41 | "anu.mp4", 42 | progress_callback=lambda d, t: asyncio.get_event_loop().create_task( 43 | progress(d, t, framecap, c_time, "[DOWNLOAD]") 44 | ), 45 | ) 46 | try: 47 | await framecap.edit("`Proccessing...`") 48 | command = f"vcsi -g {frame}x{frame} {ss} -o ss.png " 49 | os.system(command) 50 | await framecap.client.send_file( 51 | framecap.chat_id, 52 | "ss.png", 53 | reply_to=framecap.reply_to_msg_id, 54 | ) 55 | await framecap.delete() 56 | except BaseException as e: 57 | await framecap.edit(f"{e}") 58 | os.system("rm -rf *.png *.mp4") 59 | 60 | 61 | CMD_HELP.update( 62 | { 63 | "ssvideo": ".ssvideo \ 64 | \nUsage: Capture video frames by x .\ 65 | \n*max grid is 10." 66 | } 67 | ) 68 | -------------------------------------------------------------------------------- /userbot/modules/sticklet.py: -------------------------------------------------------------------------------- 1 | # Random RGB Sticklet by @PhycoNinja13b 2 | # modified by @AnggaR96s 3 | 4 | import io 5 | import os 6 | import random 7 | import textwrap 8 | 9 | from PIL import Image, ImageDraw, ImageFont 10 | from telethon.tl.types import InputMessagesFilterDocument 11 | from userbot import CMD_HELP 12 | from userbot.events import register 13 | 14 | 15 | @register(outgoing=True, pattern=r"^.rgb (.*)") 16 | async def sticklet(event): 17 | R = random.randint(0, 256) 18 | G = random.randint(0, 256) 19 | B = random.randint(0, 256) 20 | 21 | # get the input text 22 | # the text on which we would like to do the magic on 23 | sticktext = event.pattern_match.group(1) 24 | 25 | # delete the userbot command, 26 | # i don't know why this is required 27 | await event.delete() 28 | 29 | # https://docs.python.org/3/library/textwrap.html#textwrap.wrap 30 | sticktext = textwrap.wrap(sticktext, width=10) 31 | # converts back the list to a string 32 | sticktext = "\n".join(sticktext) 33 | 34 | image = Image.new("RGBA", (512, 512), (255, 255, 255, 0)) 35 | draw = ImageDraw.Draw(image) 36 | fontsize = 230 37 | 38 | FONT_FILE = await get_font_file(event.client, "@FontRes") 39 | 40 | font = ImageFont.truetype(FONT_FILE, size=fontsize) 41 | 42 | while draw.multiline_textsize(sticktext, font=font) > (512, 512): 43 | fontsize -= 3 44 | font = ImageFont.truetype(FONT_FILE, size=fontsize) 45 | 46 | width, height = draw.multiline_textsize(sticktext, font=font) 47 | draw.multiline_text( 48 | ((512 - width) / 2, (512 - height) / 2), sticktext, font=font, fill=(R, G, B) 49 | ) 50 | 51 | image_stream = io.BytesIO() 52 | image_stream.name = "dclxvi.webp" 53 | image.save(image_stream, "WebP") 54 | image_stream.seek(0) 55 | 56 | # finally, reply the sticker 57 | await event.client.send_file( 58 | event.chat_id, 59 | image_stream, 60 | force_document=False, 61 | reply_to=event.message.reply_to_msg_id, 62 | ) 63 | 64 | # cleanup 65 | try: 66 | os.remove(FONT_FILE) 67 | except: 68 | pass 69 | 70 | 71 | async def get_font_file(client, channel_id): 72 | # first get the font messages 73 | font_file_message_s = await client.get_messages( 74 | entity=channel_id, 75 | filter=InputMessagesFilterDocument, 76 | # this might cause FLOOD WAIT, 77 | # if used too many times 78 | limit=None, 79 | ) 80 | # get a random font from the list of fonts 81 | # https://docs.python.org/3/library/random.html#random.choice 82 | font_file_message = random.choice(font_file_message_s) 83 | # download and return the file path 84 | return await client.download_media(font_file_message) 85 | 86 | 87 | CMD_HELP.update({"sticklet": ">`.rgb` " "\nUsage: Create RGB sticker."}) 88 | -------------------------------------------------------------------------------- /userbot/modules/telegraph.py: -------------------------------------------------------------------------------- 1 | from telethon import events 2 | import os 3 | from PIL import Image 4 | from datetime import datetime 5 | from telegraph import Telegraph, upload_file, exceptions 6 | from userbot import TEMP_DOWNLOAD_DIRECTORY, BOTLOG_CHATID, CMD_HELP, bot 7 | from userbot.events import register 8 | 9 | telegraph = Telegraph() 10 | r = telegraph.create_account(short_name="telegraph") 11 | auth_url = r["auth_url"] 12 | 13 | 14 | @register(outgoing=True, pattern="^.telegraph (media|text)$") 15 | async def telegraphs(graph): 16 | """ For .telegraph command, upload media & text to telegraph site. """ 17 | if graph.text[0].isalpha() or graph.text[0] in ("/", "#", "@", "!"): 18 | return 19 | if graph.fwd_from: 20 | return 21 | if not os.path.isdir(TEMP_DOWNLOAD_DIRECTORY): 22 | os.makedirs(TEMP_DOWNLOAD_DIRECTORY) 23 | if graph.reply_to_msg_id: 24 | start = datetime.now() 25 | r_message = await graph.get_reply_message() 26 | input_str = graph.pattern_match.group(1) 27 | if input_str == "media": 28 | downloaded_file_name = await bot.download_media( 29 | r_message, TEMP_DOWNLOAD_DIRECTORY 30 | ) 31 | end = datetime.now() 32 | ms = (end - start).seconds 33 | await graph.edit( 34 | "Downloaded to {} in {} seconds.".format(downloaded_file_name, ms) 35 | ) 36 | if downloaded_file_name.endswith((".webp")): 37 | resize_image(downloaded_file_name) 38 | try: 39 | start = datetime.now() 40 | media_urls = upload_file(downloaded_file_name) 41 | except exceptions.TelegraphException as exc: 42 | await graph.edit("ERROR: " + str(exc)) 43 | os.remove(downloaded_file_name) 44 | else: 45 | end = datetime.now() 46 | ms_two = (end - start).seconds 47 | os.remove(downloaded_file_name) 48 | await graph.edit( 49 | "Uploaded to https://telegra.ph{} in {} seconds.".format( 50 | media_urls[0], (ms + ms_two) 51 | ), 52 | link_preview=True, 53 | ) 54 | elif input_str == "text": 55 | user_object = await bot.get_entity(r_message.from_id) 56 | title_of_page = user_object.first_name # + " " + user_object.last_name 57 | # apparently, all Users do not have last_name field 58 | page_content = r_message.message 59 | if r_message.media: 60 | if page_content != "": 61 | title_of_page = page_content 62 | downloaded_file_name = await bot.download_media( 63 | r_message, TEMP_DOWNLOAD_DIRECTORY 64 | ) 65 | m_list = None 66 | with open(downloaded_file_name, "rb") as fd: 67 | m_list = fd.readlines() 68 | for m in m_list: 69 | page_content += m.decode("UTF-8") + "\n" 70 | os.remove(downloaded_file_name) 71 | page_content = page_content.replace("\n", "
") 72 | response = telegraph.create_page(title_of_page, html_content=page_content) 73 | end = datetime.now() 74 | ms = (end - start).seconds 75 | await graph.edit( 76 | "Pasted to https://telegra.ph/{} in {} seconds.".format( 77 | response["path"], ms 78 | ), 79 | link_preview=True, 80 | ) 81 | else: 82 | await graph.edit("Reply to a message to get a permanent telegra.ph link.") 83 | 84 | 85 | def resize_image(image): 86 | im = Image.open(image) 87 | im.save(image, "PNG") 88 | 89 | 90 | CMD_HELP.update( 91 | { 92 | "telegraph": ">`.telegraph media | text`\ 93 | \nUsage: Upload text & media on Telegraph." 94 | } 95 | ) 96 | -------------------------------------------------------------------------------- /userbot/modules/time.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | """ Userbot module for getting the date 7 | and time of any country or the userbot server. """ 8 | 9 | from datetime import datetime as dt 10 | 11 | from pytz import country_names as c_n 12 | from pytz import country_timezones as c_tz 13 | from pytz import timezone as tz 14 | 15 | from userbot import CMD_HELP, COUNTRY, TZ_NUMBER 16 | from userbot.events import register 17 | 18 | 19 | async def get_tz(con): 20 | """ Get time zone of the given country. """ 21 | if "(Uk)" in con: 22 | con = con.replace("Uk", "UK") 23 | if "(Us)" in con: 24 | con = con.replace("Us", "US") 25 | if " Of " in con: 26 | con = con.replace(" Of ", " of ") 27 | if "(Western)" in con: 28 | con = con.replace("(Western)", "(western)") 29 | if "Minor Outlying Islands" in con: 30 | con = con.replace("Minor Outlying Islands", "minor outlying islands") 31 | if "Nl" in con: 32 | con = con.replace("Nl", "NL") 33 | 34 | for c_code in c_n: 35 | if con == c_n[c_code]: 36 | return c_tz[c_code] 37 | try: 38 | if c_n[con]: 39 | return c_tz[con] 40 | except KeyError: 41 | return 42 | 43 | 44 | @register(outgoing=True, pattern="^.time(?: |$)(.*)(? 4: 58 | try: 59 | c_name = c_n[con] 60 | except KeyError: 61 | c_name = con 62 | timezones = await get_tz(con) 63 | elif COUNTRY: 64 | c_name = COUNTRY 65 | tz_num = TZ_NUMBER 66 | timezones = await get_tz(COUNTRY) 67 | else: 68 | await tdata.edit(f"`It's` **{dt.now().strftime(t_form)}** `here.`") 69 | return 70 | 71 | if not timezones: 72 | await tdata.edit("`Invaild country.`") 73 | return 74 | 75 | if len(timezones) == 1: 76 | time_zone = timezones[0] 77 | elif len(timezones) > 1: 78 | if tz_num: 79 | tz_num = int(tz_num) 80 | time_zone = timezones[tz_num - 1] 81 | else: 82 | return_str = f"`{c_name} has multiple timezones:`\n\n" 83 | 84 | for i, item in enumerate(timezones): 85 | return_str += f"`{i+1}. {item}`\n" 86 | 87 | return_str += "\n`Choose one by typing the number " 88 | return_str += "in the command.`\n" 89 | return_str += f"`Example: .time {c_name} 2`" 90 | 91 | await tdata.edit(return_str) 92 | return 93 | 94 | dtnow = dt.now(tz(time_zone)).strftime(t_form) 95 | 96 | if c_name != COUNTRY: 97 | await tdata.edit(f"`It's` **{dtnow}** `in {c_name}({time_zone} timezone).`") 98 | return 99 | 100 | elif COUNTRY: 101 | await tdata.edit( 102 | f"`It's` **{dtnow}** `here, in {COUNTRY}" f"({time_zone} timezone).`" 103 | ) 104 | return 105 | 106 | 107 | @register(outgoing=True, pattern="^.date(?: |$)(.*)(? 4: 121 | try: 122 | c_name = c_n[con] 123 | except KeyError: 124 | c_name = con 125 | timezones = await get_tz(con) 126 | elif COUNTRY: 127 | c_name = COUNTRY 128 | tz_num = TZ_NUMBER 129 | timezones = await get_tz(COUNTRY) 130 | else: 131 | await dat.edit(f"`It's` **{dt.now().strftime(d_form)}** `here.`") 132 | return 133 | 134 | if not timezones: 135 | await dat.edit("`Invaild country.`") 136 | return 137 | 138 | if len(timezones) == 1: 139 | time_zone = timezones[0] 140 | elif len(timezones) > 1: 141 | if tz_num: 142 | tz_num = int(tz_num) 143 | time_zone = timezones[tz_num - 1] 144 | else: 145 | return_str = f"`{c_name} has multiple timezones:`\n" 146 | 147 | for i, item in enumerate(timezones): 148 | return_str += f"`{i+1}. {item}`\n" 149 | 150 | return_str += "\n`Choose one by typing the number " 151 | return_str += "in the command.`\n" 152 | return_str += f"Example: .date {c_name} 2" 153 | 154 | await dat.edit(return_str) 155 | return 156 | 157 | dtnow = dt.now(tz(time_zone)).strftime(d_form) 158 | 159 | if c_name != COUNTRY: 160 | await dat.edit(f"`It's` **{dtnow}** `in {c_name}({time_zone} timezone).`") 161 | return 162 | 163 | elif COUNTRY: 164 | await dat.edit( 165 | f"`It's` **{dtnow}** `here, in {COUNTRY}" f"({time_zone} timezone).`" 166 | ) 167 | return 168 | 169 | 170 | CMD_HELP.update( 171 | { 172 | "time": ".time " 173 | "\nUsage: Get the time of a country. If a country has " 174 | "multiple timezones, it will list all of them " 175 | "and let you select one." 176 | } 177 | ) 178 | CMD_HELP.update( 179 | { 180 | "date": ".date " 181 | "\nUsage: Get the date of a country. If a country has " 182 | "multiple timezones, it will list all of them " 183 | "and let you select one." 184 | } 185 | ) 186 | -------------------------------------------------------------------------------- /userbot/modules/torrent.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 GengKapak and AnggaR96s. 2 | # All rights reserved. 3 | 4 | import requests 5 | import json 6 | import codecs 7 | import os 8 | from userbot import CMD_HELP, TEMP_DOWNLOAD_DIRECTORY 9 | from userbot.events import register 10 | 11 | 12 | @register(outgoing=True, pattern="^\.ts (.*)") 13 | async def gengkapak(e): 14 | await e.edit("`Please wait, fetching results...`") 15 | query = e.pattern_match.group(1) 16 | response = requests.get( 17 | f"https://sjprojectsapi.herokuapp.com/torrent/?query={query}" 18 | ) 19 | ts = json.loads(response.text) 20 | if not ts == response.json(): 21 | await e.edit("**Some error occured**\n`Try Again Later`") 22 | return 23 | listdata = "" 24 | run = 0 25 | while True: 26 | try: 27 | run += 1 28 | r1 = ts[run] 29 | list1 = "<-----{}----->\nName: {}\nSeeders: {}\nSize: {}\nAge: {}\n<--Magnet Below-->\n{}\n\n\n".format( 30 | run, r1["name"], r1["seeder"], r1["size"], r1["age"], r1["magnet"] 31 | ) 32 | listdata = listdata + list1 33 | except: 34 | break 35 | 36 | if not listdata: 37 | return await e.edit("`Error: No results found`") 38 | 39 | tsfileloc = f"{TEMP_DOWNLOAD_DIRECTORY}/{query}.txt" 40 | with open(tsfileloc, "w+", encoding="utf8") as out_file: 41 | out_file.write(str(listdata)) 42 | fd = codecs.open(tsfileloc, "r", encoding="utf-8") 43 | data = fd.read() 44 | key = ( 45 | requests.post("https://nekobin.com/api/documents", json={"content": data}) 46 | .json() 47 | .get("result") 48 | .get("key") 49 | ) 50 | url = f"https://nekobin.com/raw/{key}" 51 | caption = f"Here are the results for the query: {query}\nNekofied to : {url}" 52 | await e.client.send_file( 53 | e.chat_id, tsfileloc, caption=caption, force_document=False 54 | ) 55 | os.remove(tsfileloc) 56 | await e.delete() 57 | 58 | 59 | CMD_HELP.update( 60 | { 61 | "torrent": ">`.ts` **Query**" 62 | "\nUsage: Search for torrent query and display results." 63 | } 64 | ) 65 | -------------------------------------------------------------------------------- /userbot/modules/waifu.py: -------------------------------------------------------------------------------- 1 | # Imported from ppe-remix 2 | 3 | import re 4 | import random 5 | from userbot import CMD_HELP, bot 6 | from userbot.events import register 7 | 8 | 9 | EMOJI_PATTERN = re.compile( 10 | "[" 11 | "\U0001F1E0-\U0001F1FF" # flags (iOS) 12 | "\U0001F300-\U0001F5FF" # symbols & pictographs 13 | "\U0001F600-\U0001F64F" # emoticons 14 | "\U0001F680-\U0001F6FF" # transport & map symbols 15 | "\U0001F700-\U0001F77F" # alchemical symbols 16 | "\U0001F780-\U0001F7FF" # Geometric Shapes Extended 17 | "\U0001F800-\U0001F8FF" # Supplemental Arrows-C 18 | "\U0001F900-\U0001F9FF" # Supplemental Symbols and Pictographs 19 | "\U0001FA00-\U0001FA6F" # Chess Symbols 20 | "\U0001FA70-\U0001FAFF" # Symbols and Pictographs Extended-A 21 | "\U00002702-\U000027B0" # Dingbats 22 | "]+" 23 | ) 24 | 25 | 26 | def deEmojify(inputString: str) -> str: 27 | return re.sub(EMOJI_PATTERN, "", inputString) 28 | 29 | 30 | @register(outgoing=True, pattern="^.waifu(?: |$)(.*)") 31 | async def waifu(animu): 32 | text = animu.pattern_match.group(1) 33 | if not text: 34 | if animu.is_reply: 35 | text = (await animu.get_reply_message()).message 36 | else: 37 | await animu.answer("`No text given, hence the waifu ran away.`") 38 | return 39 | animus = [20, 32, 33, 40, 41, 42, 58] 40 | sticcers = await bot.inline_query( 41 | "stickerizerbot", f"#{random.choice(animus)}{(deEmojify(text))}" 42 | ) 43 | await sticcers[0].click( 44 | animu.chat_id, 45 | reply_to=animu.reply_to_msg_id, 46 | silent=True if animu.is_reply else False, 47 | hide_via=True, 48 | ) 49 | await animu.delete() 50 | 51 | 52 | CMD_HELP.update( 53 | { 54 | "waifu": ">`.waifu`" 55 | "\nUsage: To stickerize your text with beautiful anime girl templates." 56 | } 57 | ) 58 | -------------------------------------------------------------------------------- /userbot/modules/weather.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | """ Userbot module for getting the weather of a city. """ 7 | 8 | 9 | import json 10 | from requests import get 11 | from datetime import datetime 12 | from pytz import country_timezones as c_tz 13 | from pytz import timezone as tz 14 | from pytz import country_names as c_n 15 | 16 | from userbot import CMD_HELP, WEATHER_DEFCITY 17 | from userbot import OPEN_WEATHER_MAP_APPID as OWM_API 18 | from userbot.events import register 19 | 20 | # ===== CONSTANT ===== 21 | DEFCITY = WEATHER_DEFCITY if WEATHER_DEFCITY else None 22 | # ==================== 23 | 24 | 25 | async def get_tz(con): 26 | """ Get time zone of the given country. """ 27 | """ Credits: @aragon12 and @zakaryan2004. """ 28 | for c_code in c_n: 29 | if con == c_n[c_code]: 30 | return tz(c_tz[c_code][0]) 31 | try: 32 | if c_n[con]: 33 | return tz(c_tz[con][0]) 34 | except KeyError: 35 | return 36 | 37 | 38 | @register(outgoing=True, pattern="^.weather(?: |$)(.*)") 39 | async def get_weather(weather): 40 | """ For .weather command, gets the current weather of a city. """ 41 | 42 | if not OWM_API: 43 | await weather.edit("`Get an API key from` https://openweathermap.org/ `first.`") 44 | return 45 | 46 | APPID = OWM_API 47 | 48 | if not weather.pattern_match.group(1): 49 | CITY = DEFCITY 50 | if not CITY: 51 | await weather.edit( 52 | "`Please specify a city or set one as default using the WEATHER_DEFCITY config variable.`" 53 | ) 54 | return 55 | else: 56 | CITY = weather.pattern_match.group(1) 57 | 58 | timezone_countries = { 59 | timezone: country 60 | for country, timezones in c_tz.items() 61 | for timezone in timezones 62 | } 63 | 64 | if "," in CITY: 65 | newcity = CITY.split(",") 66 | if len(newcity[1]) == 2: 67 | CITY = newcity[0].strip() + "," + newcity[1].strip() 68 | else: 69 | country = await get_tz((newcity[1].strip()).title()) 70 | try: 71 | countrycode = timezone_countries[f"{country}"] 72 | except KeyError: 73 | await weather.edit("`Invalid country.`") 74 | return 75 | CITY = newcity[0].strip() + "," + countrycode.strip() 76 | 77 | url = f"https://api.openweathermap.org/data/2.5/weather?q={CITY}&appid={APPID}" 78 | request = get(url) 79 | result = json.loads(request.text) 80 | 81 | if request.status_code != 200: 82 | await weather.edit("`Invalid country.`") 83 | return 84 | 85 | cityname = result["name"] 86 | curtemp = result["main"]["temp"] 87 | humidity = result["main"]["humidity"] 88 | min_temp = result["main"]["temp_min"] 89 | max_temp = result["main"]["temp_max"] 90 | desc = result["weather"][0] 91 | desc = desc["main"] 92 | country = result["sys"]["country"] 93 | sunrise = result["sys"]["sunrise"] 94 | sunset = result["sys"]["sunset"] 95 | wind = result["wind"]["speed"] 96 | winddir = result["wind"]["deg"] 97 | 98 | ctimezone = tz(c_tz[country][0]) 99 | time = datetime.now(ctimezone).strftime("%A, %I:%M %p") 100 | fullc_n = c_n[f"{country}"] 101 | 102 | dirs = ["N", "NE", "E", "SE", "S", "SW", "W", "NW"] 103 | 104 | div = 360 / len(dirs) 105 | funmath = int((winddir + (div / 2)) / div) 106 | findir = dirs[funmath % len(dirs)] 107 | kmph = str(wind * 3.6).split(".") 108 | mph = str(wind * 2.237).split(".") 109 | 110 | def fahrenheit(f): 111 | temp = str(((f - 273.15) * 9 / 5 + 32)).split(".") 112 | return temp[0] 113 | 114 | def celsius(c): 115 | temp = str((c - 273.15)).split(".") 116 | return temp[0] 117 | 118 | def sun(unix): 119 | return datetime.fromtimestamp(unix, tz=ctimezone).strftime("%I:%M %p") 120 | 121 | await weather.edit( 122 | f"**Temperature:** `{celsius(curtemp)}°C | {fahrenheit(curtemp)}°F`\n" 123 | + f"**Min. Temp.:** `{celsius(min_temp)}°C | {fahrenheit(min_temp)}°F`\n" 124 | + f"**Max. Temp.:** `{celsius(max_temp)}°C | {fahrenheit(max_temp)}°F`\n" 125 | + f"**Humidity:** `{humidity}%`\n" 126 | + f"**Wind:** `{kmph[0]} kmh | {mph[0]} mph, {findir}`\n" 127 | + f"**Sunrise:** `{sun(sunrise)}`\n" 128 | + f"**Sunset:** `{sun(sunset)}`\n\n" 129 | + f"**{desc}**\n" 130 | + f"`{cityname}, {fullc_n}`\n" 131 | + f"`{time}`" 132 | ) 133 | 134 | 135 | CMD_HELP.update( 136 | { 137 | "weather": ".weather or .weather , \ 138 | \nUsage: Gets the weather of a city." 139 | } 140 | ) 141 | -------------------------------------------------------------------------------- /userbot/modules/webupload.py: -------------------------------------------------------------------------------- 1 | # Kanged from UniBorg 2 | # Modified by AnggaR96s 3 | 4 | import asyncio 5 | import json 6 | import os 7 | 8 | from userbot.events import register 9 | from userbot import CMD_HELP, TEMP_DOWNLOAD_DIRECTORY 10 | 11 | 12 | @register( 13 | outgoing=True, 14 | pattern="^\.web ?(.+?|) (anonfiles|transfer|filebin|anonymousfiles|megaupload|bayfiles|letsupload|0x0)", 15 | ) 16 | async def _(event): 17 | await event.edit("`Processing ...`") 18 | PROCESS_RUN_TIME = 100 19 | input_str = event.pattern_match.group(1) 20 | selected_transfer = event.pattern_match.group(2) 21 | if input_str: 22 | file_name = input_str 23 | else: 24 | reply = await event.get_reply_message() 25 | file_name = await event.client.download_media( 26 | reply.media, TEMP_DOWNLOAD_DIRECTORY 27 | ) 28 | 29 | CMD_WEB = { 30 | "anonfiles": 'curl -F "file=@{full_file_path}" https://anonfiles.com/api/upload', 31 | "transfer": 'curl --upload-file "{full_file_path}" https://transfer.sh/{bare_local_name}', 32 | "filebin": 'curl -X POST --data-binary "@{full_file_path}" -H "filename: {bare_local_name}" "https://filebin.net"', 33 | "anonymousfiles": 'curl -F file="@{full_file_path}" https://api.anonymousfiles.io/', 34 | "megaupload": 'curl -F "file=@{full_file_path}" https://megaupload.is/api/upload', 35 | "bayfiles": 'curl -F "file=@{full_file_path}" https://bayfiles.com/api/upload', 36 | "letsupload": 'curl -F "file=@{full_file_path}" https://api.letsupload.cc/upload', 37 | "0x0": 'curl -F "file=@{full_file_path}" https://0x0.st', 38 | } 39 | filename = os.path.basename(file_name) 40 | try: 41 | selected_one = CMD_WEB[selected_transfer].format( 42 | full_file_path=file_name, bare_local_name=filename 43 | ) 44 | except KeyError: 45 | await event.edit("`Invalid selected Transfer.`") 46 | return 47 | cmd = selected_one 48 | # start the subprocess $SHELL 49 | process = await asyncio.create_subprocess_shell( 50 | cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE 51 | ) 52 | stdout, stderr = await process.communicate() 53 | e_response = stderr.decode().strip() 54 | # logger.info(e_response) 55 | t_response = stdout.decode().strip() 56 | # logger.info(t_response) 57 | """if e_response: 58 | await event.edit(f"**FAILED** to __transload__: `{e_response}`") 59 | return""" 60 | if t_response: 61 | try: 62 | t_response = json.dumps(json.loads(t_response), sort_keys=True, indent=4) 63 | except Exception as e: 64 | # some sites don't return valid JSONs 65 | pass 66 | # assuming, the return values won't be longer than 67 | # 4096 characters 68 | await event.edit(t_response) 69 | 70 | 71 | CMD_HELP.update( 72 | { 73 | "webupload": ">`.web` **File** **Server**" 74 | "\nServer List: anonfiles|transfer|filebin|anonymousfiles|megaupload|bayfiles|lestupload|0x0" 75 | "\nUsage: Upload file to web." 76 | } 77 | ) 78 | -------------------------------------------------------------------------------- /userbot/modules/www.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.c (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | """ Userbot module containing commands related to the \ 7 | Information Superhighway (yes, Internet). """ 8 | 9 | from datetime import datetime 10 | 11 | from speedtest import Speedtest 12 | from telethon import functions 13 | from userbot import CMD_HELP 14 | from userbot.events import register 15 | from userbot.utils import humanbytes 16 | 17 | 18 | @register(outgoing=True, pattern=r"^\.speedtest$") 19 | async def speedtst(event): 20 | """ For .speed command, use SpeedTest to check server speeds. """ 21 | await event.edit("**Running speed test...**") 22 | 23 | test = Speedtest() 24 | test.get_best_server() 25 | test.download() 26 | test.upload() 27 | test.results.share() 28 | result = test.results.dict() 29 | 30 | msg = ( 31 | f"**Ping:** `{result['ping']}`\n" 32 | f"**Upload:** `{humanbytes(result['upload'])}/s`\n" 33 | f"**Download:** `{humanbytes(result['download'])}/s`\n\n" 34 | "**Client**\n" 35 | f"**ISP:** `{result['client']['isp']}`\n" 36 | f"**Country:** `{result['client']['country']}`\n\n" 37 | "**Server**\n" 38 | f"**Name:** `{result['server']['name']}`\n" 39 | f"**Country:** `{result['server']['country']}`\n" 40 | f"**Sponsor:** `{result['server']['sponsor']}`\n\n" 41 | ) 42 | 43 | await event.client.send_file( 44 | event.chat_id, 45 | result["share"], 46 | caption=msg, 47 | ) 48 | await event.delete() 49 | 50 | 51 | @register(outgoing=True, pattern="^.dc$") 52 | async def neardc(event): 53 | # Prevent Channel Bug to use dc 54 | if event.is_channel and not event.is_group: 55 | await event.edit("`dc Commad isn't permitted on channels`") 56 | return 57 | """ For .dc command, get the nearest datacenter information. """ 58 | result = await event.client(functions.help.GetNearestDcRequest()) 59 | await event.edit( 60 | f"**Country:** `{result.country}`\n" 61 | f"**Nearest datacenter:** `{result.nearest_dc}`\n" 62 | f"**This datacenter:** `{result.this_dc}`" 63 | ) 64 | 65 | 66 | @register(outgoing=True, pattern="^.ping$") 67 | async def pingme(pong): 68 | # Prevent Channel Bug to use ping 69 | if pong.is_channel and not pong.is_group: 70 | await pong.edit("`Ping Commad isn't permitted on channels`") 71 | return 72 | """ For .ping command, ping the userbot from any chat. """ 73 | start = datetime.now() 74 | await pong.edit("`Pong!`") 75 | end = datetime.now() 76 | duration = (end - start).microseconds / 1000 77 | await pong.edit("`Pong!\n%sms`" % (duration)) 78 | 79 | 80 | CMD_HELP.update( 81 | { 82 | "speedtest": ">`.speedtest`" "\nUsage: Does a speedtest and shows the results.", 83 | "dc": ">`.dc`" "\nUsage: Finds the nearest datacenter from your server.", 84 | "ping": ">`.ping`" "\nUsage: Shows how long it takes to ping your bot.", 85 | } 86 | ) 87 | -------------------------------------------------------------------------------- /userbot/modules/zipfile.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 The Raphielscape Company LLC. 2 | # 3 | # Licensed under the Raphielscape Public License, Version 1.d (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # 6 | # Port from UniBorg by yincen17 7 | 8 | import asyncio 9 | import zipfile 10 | from userbot.events import register 11 | from datetime import date 12 | import time 13 | import os 14 | from userbot import TEMP_DOWNLOAD_DIRECTORY, ZIP_DOWNLOAD_DIRECTORY, bot, CMD_HELP 15 | from userbot.utils import progress 16 | 17 | # ==================== 18 | today = date.today() 19 | # ==================== 20 | 21 | 22 | @register(outgoing=True, pattern=r"^\.compress(?: |$)(.*)") 23 | async def _(event): 24 | # Prevent Channel Bug to use update 25 | if event.is_channel and not event.is_group: 26 | await event.edit("`Compress Command isn't permitted on channels`") 27 | return 28 | if event.fwd_from: 29 | return 30 | if not event.is_reply: 31 | await event.edit("`Reply to a file to compress it.`") 32 | return 33 | mone = await event.edit("`Processing...`") 34 | if not os.path.isdir(TEMP_DOWNLOAD_DIRECTORY): 35 | os.makedirs(TEMP_DOWNLOAD_DIRECTORY) 36 | if event.reply_to_msg_id: 37 | reply_message = await event.get_reply_message() 38 | try: 39 | c_time = time.time() 40 | downloaded_file_name = await bot.download_media( 41 | reply_message, 42 | TEMP_DOWNLOAD_DIRECTORY, 43 | progress_callback=lambda d, t: asyncio.get_event_loop().create_task( 44 | progress(d, t, mone, c_time, "[DOWNLOADING]") 45 | ), 46 | ) 47 | directory_name = downloaded_file_name 48 | await event.edit( 49 | f"Downloaded to `{directory_name}`" "`\ncompressing file...`" 50 | ) 51 | except Exception as e: # pylint:disable=C0103,W0703 52 | await mone.edit(str(e)) 53 | zipfile.ZipFile(directory_name + ".zip", "w", zipfile.ZIP_DEFLATED).write( 54 | directory_name 55 | ) 56 | c_time = time.time() 57 | await bot.send_file( 58 | event.chat_id, 59 | directory_name + ".zip", 60 | force_document=True, 61 | allow_cache=False, 62 | reply_to=event.message.id, 63 | progress_callback=lambda d, t: asyncio.get_event_loop().create_task( 64 | progress(d, t, mone, c_time, "[UPLOADING]") 65 | ), 66 | ) 67 | await event.edit("`Done!!`") 68 | await asyncio.sleep(7) 69 | await event.delete() 70 | 71 | 72 | @register(outgoing=True, pattern=r"^\.addzip(?: |$)(.*)") 73 | async def addzip(add): 74 | """ Copyright (c) 2020 azrim @github""" 75 | # Prevent Channel Bug to use update 76 | if add.is_channel and not add.is_group: 77 | await add.edit("`Command isn't permitted on channels`") 78 | return 79 | if add.fwd_from: 80 | return 81 | if not add.is_reply: 82 | await add.edit("`Reply to a file to compress it.`") 83 | return 84 | mone = await add.edit("`Processing...`") 85 | if not os.path.isdir(ZIP_DOWNLOAD_DIRECTORY): 86 | os.makedirs(ZIP_DOWNLOAD_DIRECTORY) 87 | if add.reply_to_msg_id: 88 | reply_message = await add.get_reply_message() 89 | try: 90 | c_time = time.time() 91 | downloaded_file_name = await bot.download_media( 92 | reply_message, 93 | ZIP_DOWNLOAD_DIRECTORY, 94 | progress_callback=lambda d, t: asyncio.get_event_loop().create_task( 95 | progress(d, t, mone, c_time, "[DOWNLOADING]") 96 | ), 97 | ) 98 | success = str(downloaded_file_name).replace("./zips/", "") 99 | await add.edit(f"`{success} Successfully added to list`") 100 | except Exception as e: # pylint:disable=C0103,W0703 101 | await mone.edit(str(e)) 102 | return 103 | 104 | 105 | @register(outgoing=True, pattern=r"^\.upzip(?: |$)(.*)") 106 | async def upload_zip(up): 107 | if not os.path.isdir(ZIP_DOWNLOAD_DIRECTORY): 108 | await up.edit("`Files not found`") 109 | return 110 | mone = await up.edit("`Zipping File...`") 111 | input_str = up.pattern_match.group(1) 112 | curdate = today.strftime("%m%d%y") 113 | title = str(input_str) if input_str else "zipfile" + f"{curdate}" 114 | zipf = zipfile.ZipFile(title + ".zip", "w", zipfile.ZIP_DEFLATED) 115 | zipdir(ZIP_DOWNLOAD_DIRECTORY, zipf) 116 | zipf.close() 117 | c_time = time.time() 118 | await bot.send_file( 119 | up.chat_id, 120 | title + ".zip", 121 | force_document=True, 122 | allow_cache=False, 123 | reply_to=up.message.id, 124 | progress_callback=lambda d, t: asyncio.get_event_loop().create_task( 125 | progress(d, t, mone, c_time, "[UPLOADING]", input_str) 126 | ), 127 | ) 128 | os.rmdir(ZIP_DOWNLOAD_DIRECTORY) 129 | await up.delete() 130 | 131 | 132 | @register(outgoing=True, pattern=r"^\.rmzip(?: |$)(.*)") 133 | async def remove_dir(rm): 134 | if not os.path.isdir(ZIP_DOWNLOAD_DIRECTORY): 135 | await rm.edit("`Directory not found`") 136 | return 137 | os.rmdir(ZIP_DOWNLOAD_DIRECTORY) 138 | await rm.edit("`Zip list removed`") 139 | 140 | 141 | def zipdir(path, ziph): 142 | # ziph is zipfile handle 143 | for root, _, files in os.walk(path): 144 | for file in files: 145 | ziph.write(os.path.join(root, file)) 146 | os.remove(os.path.join(root, file)) 147 | 148 | 149 | CMD_HELP.update( 150 | { 151 | "zipfile": "`.compress` [optional: ]" 152 | "\nUsage: make files to zip." 153 | "\n\n`.addzip` " 154 | "\nUsage: add files to zip list." 155 | "\n\n`.upzip` [optional: ]" 156 | "\nUsage: upload zip list." 157 | "\n\n`.rmzip` [optional: ]" 158 | "\nUsage: clear zip list." 159 | } 160 | ) 161 | -------------------------------------------------------------------------------- /userbot/util.py: -------------------------------------------------------------------------------- 1 | # This Source Code Form is subject to the terms of the Mozilla Public 2 | # License, v. 2.0. If a copy of the MPL was not distributed with this 3 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | 5 | import re 6 | import math 7 | import os 8 | import time 9 | 10 | from telethon import events 11 | from telethon.tl.functions.messages import GetPeerDialogsRequest 12 | 13 | # the secret configuration specific things 14 | ENV = bool(os.environ.get("ENV", False)) 15 | if ENV: 16 | from sample_config import Config 17 | else: 18 | if os.path.exists("config.py"): 19 | from config import Development as Config 20 | 21 | 22 | def admin_cmd(**args): 23 | pattern = args.get("pattern", None) 24 | allow_sudo = args.get("allow_sudo", False) 25 | 26 | # get the pattern from the decorator 27 | if pattern is not None: 28 | if pattern.startswith("\#"): 29 | # special fix for snip.py 30 | args["pattern"] = re.compile(pattern) 31 | else: 32 | args["pattern"] = re.compile(Config.COMMAND_HAND_LER + pattern) 33 | 34 | args["outgoing"] = True 35 | # should this command be available for other users? 36 | if allow_sudo: 37 | args["from_users"] = list(Config.SUDO_USERS) 38 | # Mutually exclusive with outgoing (can only set one of either). 39 | args["incoming"] = True 40 | del args["allow_sudo"] 41 | 42 | # error handling condition check 43 | elif "incoming" in args and not args["incoming"]: 44 | args["outgoing"] = True 45 | 46 | # add blacklist chats, UB should not respond in these chats 47 | args["blacklist_chats"] = True 48 | black_list_chats = list(Config.UB_BLACK_LIST_CHAT) 49 | if black_list_chats: 50 | args["chats"] = black_list_chats 51 | if "allow_edited_updates" in args and args["allow_edited_updates"]: 52 | del args["allow_edited_updates"] 53 | 54 | return events.NewMessage(**args) 55 | 56 | 57 | async def is_read(borg, entity, message, is_out=None): 58 | """ 59 | Returns True if the given message (or id) has been read 60 | if a id is given, is_out needs to be a bool 61 | """ 62 | is_out = getattr(message, "out", is_out) 63 | if not isinstance(is_out, bool): 64 | raise ValueError("Message was id but is_out not provided or not a bool") 65 | message_id = getattr(message, "id", message) 66 | if not isinstance(message_id, int): 67 | raise ValueError("Failed to extract id from message") 68 | 69 | dialog = (await borg(GetPeerDialogsRequest([entity]))).dialogs[0] 70 | max_id = dialog.read_outbox_max_id if is_out else dialog.read_inbox_max_id 71 | return message_id <= max_id 72 | 73 | 74 | async def progress(current, total, event, start, type_of_ps): 75 | """Generic progress_callback for both 76 | upload.py and download.py""" 77 | now = time.time() 78 | diff = now - start 79 | if round(diff % 10.00) == 0 or current == total: 80 | percentage = current * 100 / total 81 | speed = current / diff 82 | elapsed_time = round(diff) * 1000 83 | time_to_completion = round((total - current) / speed) * 1000 84 | estimated_total_time = elapsed_time + time_to_completion 85 | progress_str = "[{0}{1}]\nPercent: {2}%\n".format( 86 | "".join(["█" for i in range(math.floor(percentage / 5))]), 87 | "".join(["░" for i in range(20 - math.floor(percentage / 5))]), 88 | round(percentage, 2), 89 | ) 90 | tmp = progress_str + "{0} of {1}\nETA: {2}".format( 91 | humanbytes(current), humanbytes(total), time_formatter(estimated_total_time) 92 | ) 93 | await event.edit("{}\n {}".format(type_of_ps, tmp)) 94 | 95 | 96 | def humanbytes(size): 97 | """Input size in bytes, 98 | outputs in a human readable format""" 99 | # https://stackoverflow.com/a/49361727/4723940 100 | if not size: 101 | return "" 102 | # 2 ** 10 = 1024 103 | power = 2 ** 10 104 | raised_to_pow = 0 105 | dict_power_n = {0: "", 1: "Ki", 2: "Mi", 3: "Gi", 4: "Ti"} 106 | while size > power: 107 | size /= power 108 | raised_to_pow += 1 109 | return str(round(size, 2)) + " " + dict_power_n[raised_to_pow] + "B" 110 | 111 | 112 | def time_formatter(milliseconds: int) -> str: 113 | """Inputs time in milliseconds, to get beautified time, 114 | as string""" 115 | seconds, milliseconds = divmod(int(milliseconds), 1000) 116 | minutes, seconds = divmod(seconds, 60) 117 | hours, minutes = divmod(minutes, 60) 118 | days, hours = divmod(hours, 24) 119 | tmp = ( 120 | ((str(days) + "d, ") if days else "") 121 | + ((str(hours) + "h, ") if hours else "") 122 | + ((str(minutes) + "m, ") if minutes else "") 123 | + ((str(seconds) + "s, ") if seconds else "") 124 | + ((str(milliseconds) + "ms, ") if milliseconds else "") 125 | ) 126 | return tmp[:-2] 127 | -------------------------------------------------------------------------------- /userbot/utils/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Adek Maulana 2 | # 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | from .chrome import chrome, options 18 | from .google_images_download import googleimagesdownload 19 | from .progress import progress 20 | 21 | from .tools import ( 22 | humanbytes, 23 | time_formatter, 24 | human_to_bytes, 25 | md5, 26 | run_cmd 27 | ) 28 | -------------------------------------------------------------------------------- /userbot/utils/chrome.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Adek Maulana 2 | # 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | import os 19 | 20 | from selenium import webdriver 21 | from selenium.webdriver.chrome.options import Options 22 | 23 | from userbot import TEMP_DOWNLOAD_DIRECTORY, GOOGLE_CHROME_BIN, CHROME_DRIVER 24 | 25 | 26 | async def chrome(chrome_options=None): 27 | if chrome_options is None: 28 | chrome_options = await options() 29 | if not os.path.isdir(TEMP_DOWNLOAD_DIRECTORY): 30 | os.mkdir(TEMP_DOWNLOAD_DIRECTORY) 31 | prefs = {"download.default_directory": TEMP_DOWNLOAD_DIRECTORY} 32 | chrome_options.add_experimental_option("prefs", prefs) 33 | return webdriver.Chrome(executable_path=CHROME_DRIVER, options=chrome_options) 34 | 35 | 36 | async def options(): 37 | chrome_options = Options() 38 | chrome_options.binary_location = GOOGLE_CHROME_BIN 39 | chrome_options.add_argument("--headless") 40 | chrome_options.add_argument("--window-size=1920x1080") 41 | chrome_options.add_argument("--disable-dev-shm-usage") 42 | chrome_options.add_argument("--no-sandbox") 43 | chrome_options.add_argument("--disable-gpu") 44 | return chrome_options 45 | -------------------------------------------------------------------------------- /userbot/utils/exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Adek Maulana 2 | # 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | class CancelProcess(Exception): 19 | """ 20 | Cancel Process 21 | """ 22 | -------------------------------------------------------------------------------- /userbot/utils/progress.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Adek Maulana 2 | # 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | import time 19 | import math 20 | 21 | from .tools import humanbytes, time_formatter 22 | from .exceptions import CancelProcess 23 | 24 | 25 | async def progress( 26 | current, total, event, start, prog_type, file_name=None, is_cancelled=False 27 | ): 28 | now = time.time() 29 | diff = now - start 30 | if is_cancelled is True: 31 | raise CancelProcess 32 | 33 | if round(diff % 10.00) == 0 or current == total: 34 | percentage = current * 100 / total 35 | speed = current / diff 36 | elapsed_time = round(diff) 37 | eta = round((total - current) / speed) 38 | if "upload" in prog_type.lower(): 39 | status = "Uploading" 40 | elif "download" in prog_type.lower(): 41 | status = "Downloading" 42 | else: 43 | status = "Unknown" 44 | progress_str = "`{0}` | [{1}{2}] `{3}%`".format( 45 | status, 46 | "".join(["●" for i in range(math.floor(percentage / 10))]), 47 | "".join(["○" for i in range(10 - math.floor(percentage / 10))]), 48 | round(percentage, 2), 49 | ) 50 | tmp = ( 51 | f"{progress_str}\n" 52 | f"`{humanbytes(current)} of {humanbytes(total)}" 53 | f" @ {humanbytes(speed)}`\n" 54 | f"`ETA` -> {time_formatter(eta)}\n" 55 | f"`Duration` -> {time_formatter(elapsed_time)}" 56 | ) 57 | await event.edit(f"`{prog_type}`\n\n" f"`Status`\n{tmp}") 58 | -------------------------------------------------------------------------------- /userbot/utils/tools.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Adek Maulana 2 | # 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | import asyncio 19 | import hashlib 20 | import re 21 | from typing import List 22 | 23 | 24 | async def md5(fname: str) -> str: 25 | hash_md5 = hashlib.md5() 26 | with open(fname, "rb") as f: 27 | for chunk in iter(lambda: f.read(4096), b""): 28 | hash_md5.update(chunk) 29 | return hash_md5.hexdigest() 30 | 31 | 32 | def humanbytes(size: int) -> str: 33 | if size is None or isinstance(size, str): 34 | return "" 35 | 36 | power = 2 ** 10 37 | raised_to_pow = 0 38 | dict_power_n = {0: "", 1: "Ki", 2: "Mi", 3: "Gi", 4: "Ti"} 39 | while size > power: 40 | size /= power 41 | raised_to_pow += 1 42 | return str(round(size, 2)) + " " + dict_power_n[raised_to_pow] + "B" 43 | 44 | 45 | def time_formatter(seconds: int) -> str: 46 | minutes, seconds = divmod(seconds, 60) 47 | hours, minutes = divmod(minutes, 60) 48 | days, hours = divmod(hours, 24) 49 | tmp = ( 50 | ((str(days) + " day(s), ") if days else "") 51 | + ((str(hours) + " hour(s), ") if hours else "") 52 | + ((str(minutes) + " minute(s), ") if minutes else "") 53 | + ((str(seconds) + " second(s), ") if seconds else "") 54 | ) 55 | return tmp[:-2] 56 | 57 | 58 | def human_to_bytes(size: str) -> int: 59 | units = { 60 | "M": 2 ** 20, 61 | "MB": 2 ** 20, 62 | "G": 2 ** 30, 63 | "GB": 2 ** 30, 64 | "T": 2 ** 40, 65 | "TB": 2 ** 40, 66 | } 67 | 68 | size = size.upper() 69 | if not re.match(r" ", size): 70 | size = re.sub(r"([KMGT])", r" \1", size) 71 | number, unit = [string.strip() for string in size.split()] 72 | return int(float(number) * units[unit]) 73 | 74 | 75 | async def run_cmd(cmd: List) -> (str, str): 76 | process = await asyncio.create_subprocess_exec( 77 | *cmd, 78 | stdout=asyncio.subprocess.PIPE, 79 | stderr=asyncio.subprocess.PIPE, 80 | ) 81 | out, err = await process.communicate() 82 | t_resp = out.strip() 83 | e_resp = err.strip() 84 | return t_resp, e_resp 85 | -------------------------------------------------------------------------------- /windows_startup_script.py: -------------------------------------------------------------------------------- 1 | from telethon import TelegramClient, events 2 | 3 | API_KEY = "Type that here" 4 | API_HASH = "Type that here" 5 | # get it from my.telegram.org 6 | bot = TelegramClient("userbot", API_KEY, API_HASH) 7 | bot.start() 8 | 9 | # This script wont run your bot, it just generates a session. 10 | --------------------------------------------------------------------------------