├── .github ├── FUNDING.yml └── workflows │ └── pythonapp.yml ├── .gitignore ├── CODE_OF_CONDUCT ├── Dockerfile ├── LICENSE ├── Procfile.txt ├── README.md ├── app.json ├── generate_session_file.py ├── heroku.yml ├── requirements.txt ├── resources └── MutantAcademyStyle.ttf ├── sample_config.env ├── string_session.py ├── terminal_getstring.sh ├── 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 │ ├── blacklist.py │ ├── chat.py │ ├── chatinfo.py │ ├── covid.py │ ├── create.py │ ├── deezload.py │ ├── direct_links.py │ ├── dogbin.py │ ├── evaluators.py │ ├── fban.py │ ├── figlet.py │ ├── filemanager.py │ ├── filter.py │ ├── fonts.py │ ├── gdrive.py │ ├── getmusic.py │ ├── github.py │ ├── hash.py │ ├── help.py │ ├── heroku.py │ ├── invite.py │ ├── lastfm.py │ ├── locks.py │ ├── lyrics.py │ ├── mega_downloader.py │ ├── memes.py │ ├── misc.py │ ├── multimemes.py │ ├── nhentai.py │ ├── notes.py │ ├── ocr.py │ ├── pics.py │ ├── pmpermit.py │ ├── profile.py │ ├── purge.py │ ├── qrcode.py │ ├── remove_bg.py │ ├── reverse.py │ ├── scrapers.py │ ├── screencapture.py │ ├── sed.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 │ ├── system_stats.py │ ├── telegraph.py │ ├── time.py │ ├── torrent.py │ ├── updater.py │ ├── upload_download.py │ ├── weather.py │ ├── welcomes.py │ ├── whois.py │ ├── www.py │ └── zipfile.py └── utils │ ├── __init__.py │ ├── chrome.py │ ├── exceptions.py │ ├── google_images_download.py │ ├── progress.py │ └── tools.py └── windows_startup_script.py /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [MoveAngel] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: [Mina-Project] # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/workflows/pythonapp.yml: -------------------------------------------------------------------------------- 1 | name: FailedChecker 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 | bin/* 12 | -------------------------------------------------------------------------------- /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 movecrew/one4ubot:alpine-latest 2 | 3 | RUN mkdir /One4uBot && chmod 777 /One4uBot 4 | ENV PATH="/One4uBot/bin:$PATH" 5 | WORKDIR /One4uBot 6 | 7 | RUN git clone https://github.com/MoveAngel/One4uBot -b sql-extended /One4uBot 8 | 9 | # 10 | # Copies session and config(if it exists) 11 | # 12 | COPY ./sample_config.env ./userbot.session* ./config.env* /One4uBot/ 13 | 14 | # 15 | # Make open port TCP 16 | # 17 | EXPOSE 80 443 18 | 19 | # 20 | # Finalization 21 | # 22 | CMD ["python3","-m","userbot"] 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | RAPHIELSCAPE PUBLIC LICENSE 2 | Version 1.d, February 2020 3 | 4 | Copyright (C) 2020 Devscapes Open Source Holding GmbH. 5 | 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, and changing it is prohibited. 8 | 9 | RAPHIELSCAPE PUBLIC LICENSE 10 | A-1. DEFINITIONS 11 | 12 | 0. “This License” refers to version 1.d of the Raphielscape Public License. 13 | 14 | 1. “Copyright” also means copyright-like laws that apply to other kinds of works. 15 | 16 | 2. “The Work" refers to any copyrightable work licensed under this License. 17 | Each licensee is addressed as “you”. “Licensees” and “recipients” may be 18 | individuals or organizations. 19 | 20 | 3. To “modify” a work means to copy from or adapt all or part of the work 21 | in a fashion requiring copyright permission, other than the making of 22 | an exact copy. The resulting work is called a “modified version” of 23 | the earlier work or a work “based on” the earlier work. 24 | 25 | 4. Source Form. The “source form” for a work means the preferred form 26 | of the work for making modifications to it. “Object code” means any 27 | non-source form of a work. 28 | 29 | The “Corresponding Source” for a work in object code form means all 30 | the source code needed to generate, install, and (for an executable work) 31 | run the object code and to modify the work, including scripts to control 32 | those activities. 33 | 34 | The Corresponding Source need not include anything that users can 35 | regenerate automatically from other parts of the Corresponding Source. 36 | The Corresponding Source for a work in source code form is that same work. 37 | 38 | 5. "The author" refers to "author" of the code, which is the one that made 39 | the particular code that exists inside of the Corresponding Source. 40 | 41 | 6. "Owner" refers to any parties which are owning the Corresponding Source. 42 | 43 | 7. "Maintainers" refers to any parties which are keeping in existence or 44 | continuance, preserving and retaining The Work and the Corresponding Source. 45 | 46 | 8. “Deprecation” refers to an act of The author and Owner without Maintainers' 47 | agreement to discontinuing the maintainership of The Work. 48 | 49 | 9. "Discontinuation" refers to all Maintainers, The Author, and Owner to 50 | discontinuing the maintainership of The Work. 51 | 52 | 10. "Upstream" refers to the place or site where The Work and the 53 | Corresponding Source getting worked on and where all Maintainers, 54 | The Author, and Owner keeping the existence, continuance, preservation, 55 | and retainment of The Work and Corresponding Source. 56 | 57 | A-2. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 58 | 59 | 0. You must give any other recipients of the Work or Derivative 60 | Works a copy of this License; and 61 | 62 | 1. You must cause any modified files to carry prominent notices 63 | stating that You changed the files; and 64 | 65 | 2. You must retain, in the Source form of any Derivative Works 66 | that You distribute, this license, all copyright, patent, trademark, 67 | authorships, and attribution notices from the Source form of the Work; and 68 | 69 | 3. You must cause the maintainers of the works to democratically 70 | selecting the new Owner in case of Deprecation with the Signoffs from 71 | all Maintainers and final Signoff from The Author of The Work and the 72 | Corresponding Source. 73 | 74 | If the works are Discontinued, the Owner should archive The Work and 75 | the Corresponding Source or optionally removing The Work entirely and 76 | may stop the distribution of The Work and the Corresponding Source. 77 | 78 | The Owner or The Author may give The Work or the Corresponding Source 79 | to a specific person for a new maintainership structure in case 80 | The Owner, Author, and The Maintainers failed to democratically 81 | selecting a new Owner to continuing, preserving and retaining 82 | The Work and the Corresponding Source; and 83 | 84 | 4. Respecting the author and owner of works that are distributed in 85 | any way. In the means that decisions that are taken by Upstream are 86 | immediately imposed on both Upstream and Modified Version of 87 | The Works and Corresponding Source. 88 | 89 | Any use, reproduction, or distribution of Your modifications, or 90 | for any such Derivative Works as a whole, provided Your use, reproduction, 91 | and distribution of the Work should comply with the conditions stated in 92 | this License. 93 | 94 | B. DISCLAIMER OF WARRANTY 95 | 96 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' 97 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 98 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 99 | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR 100 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 101 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 102 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 103 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 104 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 105 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 106 | 107 | 108 | C. REVISED VERSION OF THIS LICENSE 109 | 110 | The Devscapes Open Source Holding GmbH. may publish revised and/or new versions 111 | of the Raphielscape Public License from time to time. Such new versions will be 112 | similar in spirit to the present version but may differ in detail to address new 113 | problems or concerns. 114 | 115 | Each version is given a distinguishing version number. If the Program specifies 116 | that a certain numbered version of the Raphielscape Public License 117 | "or any later version" applies to it, you have the option of following the terms 118 | and conditions either of that numbered version or of any later version published 119 | by the Devscapes Open Source Holding GmbH. If the Program does not specify a 120 | version number of the Raphielscape Public License, you may use the latest version 121 | published by the Devscapes Open Source Holding GmbH. 122 | 123 | END OF LICENSE -------------------------------------------------------------------------------- /Procfile.txt: -------------------------------------------------------------------------------- 1 | build: 2 | docker: 3 | worker: Dockerfile 4 | run: 5 | worker: python3 -m userbot 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # One4uBot userbot project 2 | 3 |

4 | FailedChecker 5 | codacy badge
6 | Commit 7 | Contributors 8 | Watch 9 | Stars 10 | Fork 11 | Docker Image
12 | Support 13 |

14 | 15 | ![logo](https://i.ibb.co/02QVkHC/headersmina.jpg) 16 | 17 | ``` 18 | #include 19 | /** 20 | Your Telegram account may get banned. 21 | I am not responsible for any improper use of this bot 22 | This bot is intended for the purpose of having fun with memes, 23 | as well as efficiently managing groups. 24 | You ended up spamming groups, getting reported left and right, 25 | and you ended up in a Finale Battle with Telegram and at the end 26 | Telegram Team deleted your account? 27 | And after that, then you pointed your fingers at us 28 | for getting your acoount deleted? 29 | I will be rolling on the floor laughing at you. 30 | /** 31 | ``` 32 | 33 | ## Generate String Session 34 | Easy way to get STRING_SESSION. Click the button and then click button colored green in top 'Run' 35 | 36 | ### Run on repl.it 37 | [![Run repl.it](https://img.shields.io/badge/run-string__session.py-blue?style=flat-square&logo=repl.it)](https://repl.it/@MoveAngel/UserbotSession?lite=1&outputonly=1) 38 | 39 | ### or Run on your terminal 40 | ``` 41 | wget https://raw.githubusercontent.com/MoveAngel/One4uBot/sql-extended/terminal_getstring.sh && bash terminal_getstring.sh 42 | ``` 43 | 44 | ## How To Host? 45 | 46 | The easiest way to deploy this great bot! is click on button below. 47 | Make sure you have an account of heroku and follow all the steps required. 48 | 49 |

Deploy to Heroku

50 | 51 | For further guide you can head to [Groups and Support](https://github.com/MoveAngel/One4uBot#Groups-and-Support) or read this [guide](https://telegra.ph/How-to-host-a-Telegram-Userbot-07-01-2) 52 | 53 | ## Groups and Support 54 | 55 | if you want new features, or announcements, you can follow our [UserbotIndo Channel](https://t.me/userbotindocloud). 56 | 57 | For discussion, bug reporting, and help, you can join [UserbotIndo Support Group](https://t.me/userbotindo). 58 | 59 | ## Credits 60 | 61 | Thanks: 62 | * [RaphielGang](https://github.com/RaphielGang) - Telegram-Paperplane 63 | * [AvinashReddy3108](https://github.com/AvinashReddy3108) - PaperplaneExtended 64 | * [kandnub](https://github.com/kandnub) - TG-UserBot 65 | * [AdekMaulana](https://github.com/adekmaulana) - ProjectBish 66 | * [Mr.Miss](https://github.com/keselekpermen69) - Userbutt 67 | * [GengKapak](https://github.com/GengKapak) - DCLXVI 68 | * [Mkaraniya](https://github.com/mkaraniya) & [Dev73](https://github.com/Devp73) - OpenUserBot 69 | 70 | and many more people who aren't mentioned here, but may be found in [Contributors](https://github.com/MoveAngel/One4uBot/graphs/contributors). 71 | 72 | ## License 73 | 74 | This userbot licensed on [Raphielscape Public License](https://github.com/MoveAngel/One4uBot/blob/sql-extended/LICENSE) - Version 1.d, February 2020 -------------------------------------------------------------------------------- /generate_session_file.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 | # 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 | cffi 7 | coffeehouse 8 | covid 9 | cryptg 10 | dnspython 11 | deezloader 12 | emoji 13 | gitpython 14 | glitch_this 15 | google-api-python-client 16 | google-auth-httplib2 17 | google-auth-oauthlib 18 | google_images_download 19 | google_trans_new 20 | gTTS 21 | gTTS-token 22 | hachoir 23 | heroku3 24 | html_telegraph_poster 25 | httplib2 26 | humanize 27 | jikanpy 28 | lxml 29 | lyricsgenius 30 | oauth2client 31 | pendulum 32 | Pillow 33 | psutil 34 | psycopg2 35 | psycopg2-binary 36 | pybase64 37 | pyfiglet 38 | pylast 39 | pySmartDL 40 | python-barcode 41 | python-dotenv 42 | youtube-dl 43 | pytz 44 | qrcode 45 | redis 46 | requests 47 | search-engine-parser 48 | speedtest-cli 49 | sqlalchemy 50 | TgCrypto 51 | telethon 52 | telethon-session-sqlalchemy 53 | telegraph 54 | urbandict 55 | wikipedia 56 | PyGithub 57 | python-dateutil 58 | vcsi 59 | youtube_search 60 | -------------------------------------------------------------------------------- /resources/MutantAcademyStyle.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoveAngel/One4uBot/e153f632feb419bbc93909198e809c513cd0e988/resources/MutantAcademyStyle.ttf -------------------------------------------------------------------------------- /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 = "YOUR API KEY" 6 | API_HASH = "YOUR API HASH" 7 | 8 | # OpenWeather Map API Key for .weather command 9 | # Get from https://openweathermap.org/ 10 | OPEN_WEATHER_MAP_APPID = "" 11 | WEATHER_DEFCITY = "" 12 | WEATHER_DEFLANG = "" 13 | 14 | # Location of ChromeDriver for .carbon module 15 | # Example for Linux Machines : "/usr/bin/chromedriver" 16 | CHROME_DRIVER = "" 17 | 18 | # Get this value by running python3 string_session.py locally 19 | STRING_SESSION = "" 20 | 21 | # Headless GoogleChrome location for .carbon module 22 | # Example for Linux Machines : "/usr/bin/chromium-browser" 23 | GOOGLE_CHROME_BIN = "" 24 | 25 | # OCR Space API Key for .ocr command 26 | # Get from https://ocr.space/ocrapi 27 | OCR_SPACE_API_KEY = "" 28 | 29 | # remove.bg API Key for .rbg command 30 | # Get from https://www.remove.bg/api 31 | REM_BG_API_KEY = "" 32 | 33 | # ChatID for the Log group 34 | # Add a Hypen or a Negative Sign before ID 35 | # This is a integer, Please don't use Strings 36 | BOTLOG_CHATID = # this is an integer, please don't use quotes. 37 | 38 | # Incase you want to turn off logging, put this to false 39 | BOTLOG = False 40 | 41 | # Set this to True if you want the error logs to be stored in 42 | # the userbot log, rather than spamming other chats with it. 43 | # Note that this requires a valid BOTLOG_CHATID to be set. 44 | LOGSPAMMER = False 45 | 46 | # If you need Verbosity on the Logging 47 | CONSOLE_LOGGER_VERBOSE = False 48 | 49 | # PM Auto-Ban Feature Switch 50 | PM_AUTO_BAN = False 51 | 52 | # Custom Default name for .alive 53 | ALIVE_NAME = "" 54 | 55 | # Your Database URL 56 | # Example: 'postgres://userbot:userbot@localhost:5432/userbot' 57 | DATABASE_URL = "" 58 | 59 | # YouTube Data API Key for .yt command 60 | # Get from https://console.cloud.google.com 61 | YOUTUBE_API_KEY = "" 62 | 63 | # Country and Time Zone setup for 64 | # .time and .date modules 65 | COUNTRY = "" 66 | TZ_NUMBER = # this is an integer, please don't use quotes. 67 | 68 | # Google Drive Credentials 69 | # for .gdrive module. 70 | # Get from https://console.cloud.google.com 71 | G_DRIVE_CLIENT_ID = "" 72 | G_DRIVE_CLIENT_SECRET = "" 73 | G_DRIVE_AUTH_TOKEN_DATA = "" 74 | TEMP_DOWNLOAD_DIRECTORY = "" 75 | 76 | # You have to have your own unique two values for API_KEY and API_SECRET 77 | # Obtain yours from https://www.last.fm/api/account/create for Last.fm 78 | LASTFM_API = "" 79 | LASTFM_SECRET = "" 80 | LASTFM_USERNAME = "Your last.fm username" 81 | LASTFM_PASSWORD = "Your last.fm password" 82 | 83 | # Bot will add before song name. For last.fm module. 84 | # Example: GitHub: MacTavishAO : Skillet - Feel Invincible 85 | BIO_PREFIX = "" 86 | 87 | # default bio message 88 | DEFAULT_BIO = "" 89 | 90 | # FOR Lydia Access 91 | LYDIA_API_KEY = "" 92 | LYDIA_ANTI-PM = "" 93 | 94 | 95 | # Report or kick some known spammer bots after 96 | # they joins 97 | ANTI_SPAMBOT = False 98 | ANTI_SPAMBOT_SHOUT = False 99 | 100 | # Wolfram ID 101 | # Get an API KEY from products.wolframalpha.com/api/ 102 | WOLFRAM_ID="" 103 | -------------------------------------------------------------------------------- /string_session.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8-*- 3 | # 4 | # (c) https://t.me/TelethonChat/37677 and SpEcHiDe 5 | # 6 | # Licensed under the Raphielscape Public License, Version 1.d (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # 9 | 10 | from telethon.sync import TelegramClient 11 | from telethon.sessions import StringSession 12 | 13 | print("""Please go-to my.telegram.org 14 | Login using your Telegram account 15 | Click on API Development Tools 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 | -------------------------------------------------------------------------------- /terminal_getstring.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (C) 2020 KeselekPermen69 4 | # 5 | # SPDX-License-Identifier: GPL-3.0-or-later 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | export LANG=C.UTF-8 20 | 21 | echo -e "\nChecking dependencies...\n" 22 | 23 | if command -v python3 >/dev/null 2>&1 ; then 24 | echo -e "python3 found " 25 | echo -e "version: $(python3 -V)" 26 | else 27 | echo -e "python not found " 28 | if [ "$(command -v pkg)" != "" ]; then 29 | arr+=(python ) #termux python3 is in python 30 | else 31 | arr+=(python3 ) 32 | fi 33 | fi 34 | 35 | sleep 1 36 | 37 | if command -v wget >/dev/null 2>&1 ; then 38 | echo -e "\nwget found\n" 39 | else 40 | echo -e "\nwget not found\n" 41 | arr+=(wget ) 42 | fi 43 | 44 | DEPENDENCIES=${arr[@]} 45 | sleep 1 46 | 47 | if [ ! -z "$DEPENDENCIES" ]; then 48 | echo -e "\nInstalling required dependencies\n" 49 | sleep 1 50 | 51 | if [ "$(command -v pkg)" != "" ]; then # termux 52 | pkg install "$DEPENDENCIES" -y 53 | 54 | elif [ "$(command -v apt-get)" != "" ]; then # debian 55 | sudo apt-get install "$DEPENDENCIES" -y 56 | 57 | elif [ "$(command -v pacman)" != "" ]; then # arch 58 | sudo pacman -S "$DEPENDENCIES" -y 59 | 60 | # Free to PR to add others 61 | else 62 | echo -e "\nDistro not supported \nInstall this packages yourself: $DEPENDENCIES\n" 63 | fi 64 | 65 | else 66 | echo -e "\nDependencies have been installed. \nContinuing to install python packages(PyPI)\n" 67 | sleep 1 68 | fi 69 | 70 | echo -e "\nUpgrading python pip\n" 71 | pip3 install --upgrade pip setuptools 72 | echo -e "\nInstalling telethon...\n" 73 | pip3 install telethon 74 | sleep 2 75 | 76 | if [ ! -e string_session.py ]; then 77 | echo -e "\nDownloading string_session.py\n" 78 | wget https://raw.githubusercontent.com/MoveAngel/One4uBot/sql-extended/string_session.py 79 | 80 | echo -e "\nRunning script...\n" 81 | sleep 1 82 | python3 string_session.py 83 | else 84 | echo -e "\nstring_session.py detected... \nrunning file\n" 85 | sleep 1 86 | python3 string_session.py 87 | fi 88 | 89 | echo -e "Do you want to cleanup your file?" 90 | echo -e "[1] cleanup: this delete string_session.py and this file" 91 | echo -e "[2] exit" 92 | echo -ne "\nEnter your choice[1-2]: " 93 | read choice 94 | if [ "$choice" = "1" ]; then 95 | echo -e "Cleanup: removing file" 96 | rm -f string_session.py terminal_getstring.sh 97 | elif [ "$choice" = "2" ]; then 98 | exit 99 | fi -------------------------------------------------------------------------------- /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.d (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 13 | from userbot.modules import ALL_MODULES 14 | 15 | 16 | INVALID_PH = '\nERROR: The Phone No. entered is INVALID' \ 17 | '\n Tip: Use Country Code along with number.' \ 18 | '\n or check your phone number and try again !' 19 | 20 | try: 21 | bot.start() 22 | except PhoneNumberInvalidError: 23 | print(INVALID_PH) 24 | exit(1) 25 | 26 | for module_name in ALL_MODULES: 27 | imported_module = import_module("userbot.modules." + module_name) 28 | 29 | LOGS.info("You are running One4uBot [v3.7]") 30 | 31 | LOGS.info( 32 | "Congratulations, your userbot is now running !! Test it by typing .alive / .on in any chat." 33 | "If you need assistance, head to https://t.me/userbotindo") 34 | 35 | if len(argv) not in (1, 3, 4): 36 | bot.disconnect() 37 | else: 38 | bot.run_until_disconnected() 39 | -------------------------------------------------------------------------------- /userbot/events.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 module for managing events. 7 | One of the main components of the userbot. """ 8 | 9 | import sys 10 | from asyncio import create_subprocess_shell as asyncsubshell 11 | from asyncio import subprocess as asyncsub 12 | from os import remove 13 | from time import gmtime, strftime 14 | from traceback import format_exc 15 | 16 | from telethon import events 17 | 18 | from userbot import LOGSPAMMER, bot 19 | 20 | 21 | def register(**args): 22 | """ Register a new event. """ 23 | pattern = args.get('pattern', None) 24 | disable_edited = args.get('disable_edited', False) 25 | ignore_unsafe = args.get('ignore_unsafe', False) 26 | unsafe_pattern = r'^[^/!#@\$A-Za-z]' 27 | groups_only = args.get('groups_only', False) 28 | trigger_on_fwd = args.get('trigger_on_fwd', False) 29 | disable_errors = args.get('disable_errors', False) 30 | insecure = args.get('insecure', False) 31 | 32 | if pattern is not None and not pattern.startswith('(?i)'): 33 | args['pattern'] = '(?i)' + pattern 34 | 35 | if "disable_edited" in args: 36 | del args['disable_edited'] 37 | 38 | if "ignore_unsafe" in args: 39 | del args['ignore_unsafe'] 40 | 41 | if "groups_only" in args: 42 | del args['groups_only'] 43 | 44 | if "disable_errors" in args: 45 | del args['disable_errors'] 46 | 47 | if "trigger_on_fwd" in args: 48 | del args['trigger_on_fwd'] 49 | 50 | if "insecure" in args: 51 | del args['insecure'] 52 | 53 | if pattern: 54 | if not ignore_unsafe: 55 | args['pattern'] = pattern.replace('^.', unsafe_pattern, 1) 56 | 57 | def decorator(func): 58 | async def wrapper(check): 59 | if check.edit_date and check.is_channel and not check.is_group: 60 | # Messages sent in channels can be edited by other users. 61 | # Ignore edits that take place in channels. 62 | return 63 | if not LOGSPAMMER: 64 | check.chat_id 65 | else: 66 | pass 67 | 68 | if not trigger_on_fwd and check.fwd_from: 69 | return 70 | 71 | if groups_only and not check.is_group: 72 | await check.respond("`I don't think this is a group.`") 73 | return 74 | 75 | if check.via_bot_id and not insecure and check.out: 76 | return 77 | 78 | try: 79 | await func(check) 80 | 81 | # Thanks to @kandnub for this HACK. 82 | # Raise StopPropagation to Raise StopPropagation 83 | # This needed for AFK to working properly 84 | 85 | except events.StopPropagation: 86 | raise events.StopPropagation 87 | # This is a gay exception and must be passed out. So that it doesnt 88 | # spam chats 89 | except KeyboardInterrupt: 90 | pass 91 | except BaseException: 92 | 93 | # Check if we have to disable it. 94 | # If not silence the log spam on the console, 95 | # with a dumb except. 96 | 97 | if not disable_errors: 98 | date = strftime("%Y-%m-%d %H:%M:%S", gmtime()) 99 | 100 | text = "**USERBOT ERROR REPORT**\n" 101 | link = "[Userbot Indo Support](https://t.me/userbotindo)" 102 | text += "If you want to, you can report it" 103 | text += f". Head and forward this message to {link}.\n" 104 | text += "Nothing is logged except the fact of error and date\n" 105 | 106 | ftext = "========== DISCLAIMER ==========" 107 | ftext += "\nThis file uploaded ONLY here," 108 | ftext += "\nwe logged only fact of error and date," 109 | ftext += "\nwe respect your privacy," 110 | ftext += "\nyou may not report this error if you've" 111 | ftext += "\nany confidential data here, no one will see your data\n" 112 | ftext += "================================\n\n" 113 | ftext += "--------BEGIN USERBOT TRACEBACK LOG--------\n" 114 | ftext += "\nDate: " + date 115 | ftext += "\nChat ID: " + str(check.chat_id) 116 | ftext += "\nSender ID: " + str(check.sender_id) 117 | ftext += "\n\nEvent Trigger:\n" 118 | ftext += str(check.text) 119 | ftext += "\n\nTraceback info:\n" 120 | ftext += str(format_exc()) 121 | ftext += "\n\nError text:\n" 122 | ftext += str(sys.exc_info()[1]) 123 | ftext += "\n\n--------END USERBOT TRACEBACK LOG--------" 124 | 125 | command = "git log --pretty=format:\"%an: %s\" -10" 126 | 127 | ftext += "\n\n\nLast 10 commits:\n" 128 | 129 | process = await asyncsubshell(command, 130 | stdout=asyncsub.PIPE, 131 | stderr=asyncsub.PIPE) 132 | stdout, stderr = await process.communicate() 133 | result = str(stdout.decode().strip()) \ 134 | + str(stderr.decode().strip()) 135 | 136 | ftext += result 137 | 138 | file = open("error.log", "w+") 139 | file.write(ftext) 140 | file.close() 141 | 142 | # if LOGSPAMMER: 143 | # await check.respond( 144 | # "`Sorry, my userbot has crashed.\ 145 | # \nThe error logs are stored in the userbot's log chat.`" 146 | # ) 147 | 148 | # await check.client.send_file(send_to, 149 | # "error.log", 150 | # caption=text) 151 | remove("error.log") 152 | else: 153 | pass 154 | 155 | if not disable_edited: 156 | bot.add_event_handler(wrapper, events.MessageEdited(**args)) 157 | bot.add_event_handler(wrapper, events.NewMessage(**args)) 158 | return wrapper 159 | 160 | return decorator 161 | -------------------------------------------------------------------------------- /userbot/modules/__init__.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 | """ Init file which loads all of the modules """ 7 | from userbot import LOGS 8 | 9 | 10 | def __list_all_modules(): 11 | import glob 12 | from os.path import basename, dirname, isfile 13 | 14 | mod_paths = glob.glob(dirname(__file__) + "/*.py") 15 | all_modules = [ 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 | return all_modules 21 | 22 | 23 | ALL_MODULES = sorted(__list_all_modules()) 24 | LOGS.info("Modules to load: %s", str(ALL_MODULES)) 25 | __all__ = ALL_MODULES + ["ALL_MODULES"] 26 | -------------------------------------------------------------------------------- /userbot/modules/adzan.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | import requests 4 | 5 | from userbot import CMD_HELP 6 | from userbot.events import register 7 | 8 | PLACE = "" 9 | 10 | 11 | @register(pattern="^.adzan(?: |$)(.*)") 12 | async def get_adzan(adzan): 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 | timezone = parsed["results"]["location"]["timezone"] 32 | date = parsed["results"]["datetime"][0]["date"]["gregorian"] 33 | 34 | imsak = parsed["results"]["datetime"][0]["times"]["Imsak"] 35 | subuh = parsed["results"]["datetime"][0]["times"]["Fajr"] 36 | zuhur = parsed["results"]["datetime"][0]["times"]["Dhuhr"] 37 | ashar = parsed["results"]["datetime"][0]["times"]["Asr"] 38 | maghrib = parsed["results"]["datetime"][0]["times"]["Maghrib"] 39 | isya = parsed["results"]["datetime"][0]["times"]["Isha"] 40 | 41 | result = ( 42 | f"**Jadwal Sholat**:\n" 43 | f"📅 `{date} | {timezone}`\n" 44 | f"📍 `{city} | {country}`\n\n" 45 | f"**Imsak :** `{imsak}`\n" 46 | f"**Subuh :** `{subuh}`\n" 47 | f"**Zuhur :** `{zuhur}`\n" 48 | f"**Ashar :** `{ashar}`\n" 49 | f"**Maghrib :** `{maghrib}`\n" 50 | f"**Isya :** `{isya}`\n" 51 | ) 52 | 53 | await adzan.edit(result) 54 | 55 | 56 | CMD_HELP.update( 57 | { 58 | "adzan": ".adzan \ 59 | \nUsage: Gets the prayer time for moslem." 60 | } 61 | ) 62 | -------------------------------------------------------------------------------- /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 From UniBorg to UserBot by keselekpermen69 7 | 8 | import io 9 | import re 10 | 11 | import userbot.modules.sql_helper.blacklist_sql as sql 12 | from userbot import CMD_HELP 13 | from userbot.events import register 14 | 15 | 16 | @register(incoming=True, disable_edited=True, disable_errors=True) 17 | async def on_new_message(event): 18 | # TODO: exempt admins from locks 19 | name = event.raw_text 20 | snips = sql.get_chat_blacklist(event.chat_id) 21 | for snip in snips: 22 | pattern = r"( |^|[^\w])" + re.escape(snip) + r"( |$|[^\w])" 23 | if re.search(pattern, name, flags=re.IGNORECASE): 24 | try: 25 | await event.delete() 26 | except Exception: 27 | await event.reply("I do not have DELETE permission in this chat") 28 | sql.rm_from_blacklist(event.chat_id, snip.lower()) 29 | break 30 | 31 | 32 | @register(outgoing=True, pattern="^.addbl(?: |$)(.*)") 33 | async def on_add_black_list(addbl): 34 | text = addbl.pattern_match.group(1) 35 | to_blacklist = list( 36 | set(trigger.strip() for trigger in text.split("\n") if trigger.strip()) 37 | ) 38 | for trigger in to_blacklist: 39 | sql.add_to_blacklist(addbl.chat_id, trigger.lower()) 40 | await addbl.edit( 41 | "Added {} triggers to the blacklist in the current chat".format( 42 | len(to_blacklist) 43 | ) 44 | ) 45 | 46 | 47 | @register(outgoing=True, pattern="^.listbl(?: |$)(.*)") 48 | async def on_view_blacklist(listbl): 49 | all_blacklisted = sql.get_chat_blacklist(listbl.chat_id) 50 | OUT_STR = "Blacklists in the Current Chat:\n" 51 | if len(all_blacklisted) > 0: 52 | for trigger in all_blacklisted: 53 | OUT_STR += f"`{trigger}`\n" 54 | else: 55 | OUT_STR = "No BlackLists. Start Saving using `.addbl`" 56 | if len(OUT_STR) > 4096: 57 | with io.BytesIO(str.encode(OUT_STR)) as out_file: 58 | out_file.name = "blacklist.text" 59 | await listbl.client.send_file( 60 | listbl.chat_id, 61 | out_file, 62 | force_document=True, 63 | allow_cache=False, 64 | caption="BlackLists in the Current Chat", 65 | reply_to=listbl, 66 | ) 67 | await listbl.delete() 68 | else: 69 | await listbl.edit(OUT_STR) 70 | 71 | 72 | @register(outgoing=True, pattern="^.rmbl(?: |$)(.*)") 73 | async def on_delete_blacklist(rmbl): 74 | text = rmbl.pattern_match.group(1) 75 | to_unblacklist = list( 76 | set(trigger.strip() for trigger in text.split("\n") if trigger.strip()) 77 | ) 78 | successful = 0 79 | for trigger in to_unblacklist: 80 | if sql.rm_from_blacklist(rmbl.chat_id, trigger.lower()): 81 | successful += 1 82 | await rmbl.edit(f"Removed {successful} / {len(to_unblacklist)} from the blacklist") 83 | 84 | 85 | CMD_HELP.update( 86 | { 87 | "blacklist": ".listbl\ 88 | \nUsage: Lists all active userbot blacklist in a chat.\ 89 | \n\n.addbl \ 90 | \nUsage: Saves the message to the 'blacklist keyword'.\ 91 | \nThe bot will delete to the message whenever 'blacklist keyword' is mentioned.\ 92 | \n\n.rmbl \ 93 | \nUsage: Stops the specified blacklist.\ 94 | \n btw you need permissions **Delete Messages** of admin." 95 | } 96 | ) 97 | -------------------------------------------------------------------------------- /userbot/modules/chat.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 module containing userid, chatid and log commands""" 7 | 8 | from asyncio import sleep 9 | 10 | from userbot import BOTLOG, BOTLOG_CHATID, CMD_HELP, bot 11 | from userbot.events import register 12 | from userbot.modules.admin import get_user_from_event 13 | 14 | 15 | @register(outgoing=True, pattern="^.userid$") 16 | async def useridgetter(target): 17 | """ For .userid command, returns the ID of the target user. """ 18 | message = await target.get_reply_message() 19 | if message: 20 | if not message.forward: 21 | user_id = message.sender.id 22 | if message.sender.username: 23 | name = "@" + message.sender.username 24 | else: 25 | name = "**" + message.sender.first_name + "**" 26 | else: 27 | user_id = message.forward.sender.id 28 | if message.forward.sender.username: 29 | name = "@" + message.forward.sender.username 30 | else: 31 | name = "*" + message.forward.sender.first_name + "*" 32 | await target.edit("**Name:** {} \n**User ID:** `{}`".format(name, user_id)) 33 | 34 | 35 | @register(outgoing=True, pattern="^.link(?: |$)(.*)") 36 | async def permalink(mention): 37 | """ For .link command, generates a link to the user's PM with a custom text. """ 38 | user, custom = await get_user_from_event(mention) 39 | if not user: 40 | return 41 | if custom: 42 | await mention.edit(f"[{custom}](tg://user?id={user.id})") 43 | else: 44 | tag = ( 45 | user.first_name.replace("\u2060", "") if user.first_name else user.username 46 | ) 47 | await mention.edit(f"[{tag}](tg://user?id={user.id})") 48 | 49 | 50 | @register(outgoing=True, pattern="^.chatid$") 51 | async def chatidgetter(chat): 52 | """ For .chatid, returns the ID of the chat you are in at that moment. """ 53 | await chat.edit("Chat ID: `" + str(chat.chat_id) + "`") 54 | 55 | 56 | @register(outgoing=True, pattern=r"^.log(?: |$)([\s\S]*)") 57 | async def log(log_text): 58 | """ For .log command, forwards a message or the command argument to the bot logs group """ 59 | if BOTLOG: 60 | if log_text.reply_to_msg_id: 61 | reply_msg = await log_text.get_reply_message() 62 | await reply_msg.forward_to(BOTLOG_CHATID) 63 | elif log_text.pattern_match.group(1): 64 | user = f"#LOG / Chat ID: {log_text.chat_id}\n\n" 65 | textx = user + log_text.pattern_match.group(1) 66 | await bot.send_message(BOTLOG_CHATID, textx) 67 | else: 68 | await log_text.edit("`What am I supposed to log?`") 69 | return 70 | await log_text.edit("`Logged Successfully`") 71 | else: 72 | await log_text.edit("`This feature requires Logging to be enabled!`") 73 | await sleep(2) 74 | await log_text.delete() 75 | 76 | 77 | @register(outgoing=True, pattern="^.kickme$") 78 | async def kickme(leave): 79 | """ Basically it's .kickme command """ 80 | await leave.edit("Nope, no, no, I go away") 81 | await leave.client.kick_participant(leave.chat_id, "me") 82 | 83 | 84 | @register(outgoing=True, pattern="^.unmutechat$") 85 | async def unmute_chat(unm_e): 86 | """ For .unmutechat command, unmute a muted chat. """ 87 | try: 88 | from userbot.modules.sql_helper.keep_read_sql import unkread 89 | except AttributeError: 90 | await unm_e.edit("`Running on Non-SQL Mode!`") 91 | return 92 | unkread(str(unm_e.chat_id)) 93 | await unm_e.edit("```Unmuted this chat Successfully```") 94 | await sleep(2) 95 | await unm_e.delete() 96 | 97 | 98 | @register(outgoing=True, pattern="^.mutechat$") 99 | async def mute_chat(mute_e): 100 | """ For .mutechat command, mute any chat. """ 101 | try: 102 | from userbot.modules.sql_helper.keep_read_sql import kread 103 | except AttributeError: 104 | await mute_e.edit("`Running on Non-SQL mode!`") 105 | return 106 | await mute_e.edit(str(mute_e.chat_id)) 107 | kread(str(mute_e.chat_id)) 108 | await mute_e.edit("`Shush! This chat will be silenced!`") 109 | await sleep(2) 110 | await mute_e.delete() 111 | if BOTLOG: 112 | await mute_e.client.send_message( 113 | BOTLOG_CHATID, str(mute_e.chat_id) + " was silenced." 114 | ) 115 | 116 | 117 | @register(incoming=True, disable_errors=True) 118 | async def keep_read(message): 119 | """ The mute logic. """ 120 | try: 121 | from userbot.modules.sql_helper.keep_read_sql import is_kread 122 | except AttributeError: 123 | return 124 | kread = is_kread() 125 | if kread: 126 | for i in kread: 127 | if i.groupid == str(message.chat_id): 128 | await message.client.send_read_acknowledge(message.chat_id) 129 | 130 | 131 | # Regex-Ninja module by @Kandnub 132 | regexNinja = False 133 | 134 | 135 | @register(outgoing=True, pattern="^s/") 136 | async def sedNinja(event): 137 | """For regex-ninja module, auto delete command starting with s/""" 138 | if regexNinja: 139 | await sleep(0.5) 140 | await event.delete() 141 | 142 | 143 | @register(outgoing=True, pattern="^.regexninja (on|off)$") 144 | async def sedNinjaToggle(event): 145 | """ Enables or disables the regex ninja module. """ 146 | global regexNinja 147 | if event.pattern_match.group(1) == "on": 148 | regexNinja = True 149 | await event.edit("`Successfully enabled ninja mode for Regexbot.`") 150 | await sleep(1) 151 | await event.delete() 152 | elif event.pattern_match.group(1) == "off": 153 | regexNinja = False 154 | await event.edit("`Successfully disabled ninja mode for Regexbot.`") 155 | await sleep(1) 156 | await event.delete() 157 | 158 | 159 | CMD_HELP.update( 160 | { 161 | "chat": ".chatid\ 162 | \nUsage: Fetches the current chat's ID\ 163 | \n\n.userid\ 164 | \nUsage: Fetches the ID of the user in reply, if its a forwarded message, finds the ID for the source.\ 165 | \n\n.log\ 166 | \nUsage: Forwards the message you've replied to in your bot logs group.\ 167 | \n\n.kickme\ 168 | \nUsage: Leave from a targeted group.\ 169 | \n\n.unmutechat\ 170 | \nUsage: Unmutes a muted chat.\ 171 | \n\n.mutechat\ 172 | \nUsage: Allows you to mute any chat.\ 173 | \n\n.link : (or) reply to someone's message with .link \ 174 | \nUsage: Generate a permanent link to the user's profile with optional custom text.\ 175 | \n\n.regexninja on/off\ 176 | \nUsage: Globally enable/disables the regex ninja module.\ 177 | \nRegex Ninja module helps to delete the regex bot's triggering messages." 178 | } 179 | ) 180 | -------------------------------------------------------------------------------- /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 | 10 | from userbot import CMD_HELP 11 | from userbot.events import register 12 | 13 | 14 | @register(outgoing=True, pattern="^.covid (.*)") 15 | async def corona(event): 16 | await event.edit("`Processing...`") 17 | country = event.pattern_match.group(1) 18 | covid = Covid(source="worldometers") 19 | try: 20 | country_data = covid.get_status_by_country_name(country) 21 | output_text = ( 22 | f"`Confirmed : {format_integer(country_data['confirmed'])}`\n" 23 | + f"`Active : {format_integer(country_data['active'])}`\n" 24 | + f"`Deaths : {format_integer(country_data['deaths'])}`\n" 25 | + f"`Recovered : {format_integer(country_data['recovered'])}`\n\n" 26 | + f"`New Cases : {format_integer(country_data['new_cases'])}`\n" 27 | + f"`New Deaths : {format_integer(country_data['new_deaths'])}`\n" 28 | + f"`Critical : {format_integer(country_data['critical'])}`\n" 29 | + f"`Total Tests : {format_integer(country_data['total_tests'])}`\n\n" 30 | + f"Data provided by [Worldometer](https://www.worldometers.info/coronavirus/country/{country})" 31 | ) 32 | await event.edit(f"Corona Virus Info in {country}:\n\n{output_text}") 33 | except ValueError: 34 | await event.edit( 35 | f"No information found for: {country}!\nCheck your spelling and try again." 36 | ) 37 | 38 | 39 | def format_integer(number, thousand_separator="."): 40 | def reverse(string): 41 | string = "".join(reversed(string)) 42 | return string 43 | 44 | s = reverse(str(number)) 45 | count = 0 46 | result = "" 47 | for char in s: 48 | count = count + 1 49 | if count % 3 == 0: 50 | if len(s) == count: 51 | result = char + result 52 | else: 53 | result = thousand_separator + char + result 54 | else: 55 | result = char + result 56 | return result 57 | 58 | 59 | CMD_HELP.update( 60 | { 61 | "covid": ".covid " 62 | "\nUsage: Get an information about data covid-19 in your country.\n" 63 | } 64 | ) 65 | -------------------------------------------------------------------------------- /userbot/modules/create.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 | # (c) Spechide - UniBorg 7 | # Port From UniBorg to UserBot by @afdulfauzan 8 | 9 | from telethon.tl import functions 10 | 11 | from userbot import CMD_HELP 12 | from userbot.events import register 13 | 14 | 15 | @register(outgoing=True, pattern="^.create (b|g|c)(?: |$)(.*)") 16 | async def telegraphs(grop): 17 | """ For .create command, Creating New Group & Channel """ 18 | if not grop.text[0].isalpha() and grop.text[0] not in ("/", "#", "@", "!"): 19 | if grop.fwd_from: 20 | return 21 | type_of_group = grop.pattern_match.group(1) 22 | group_name = grop.pattern_match.group(2) 23 | if type_of_group == "b": 24 | try: 25 | result = await grop.client( 26 | functions.messages.CreateChatRequest( # pylint:disable=E0602 27 | users=["@userbotindobot"], 28 | # Not enough users (to create a chat, for example) 29 | # Telegram, no longer allows creating a chat with 30 | # ourselves 31 | title=group_name, 32 | ) 33 | ) 34 | created_chat_id = result.chats[0].id 35 | result = await grop.client( 36 | functions.messages.ExportChatInviteRequest( 37 | peer=created_chat_id, 38 | ) 39 | ) 40 | await grop.edit( 41 | "Your {} Group Created Successfully. Click [{}]({}) to join".format( 42 | group_name, group_name, result.link 43 | ) 44 | ) 45 | except Exception as e: # pylint:disable=C0103,W0703 46 | await grop.edit(str(e)) 47 | elif type_of_group == "g" or type_of_group == "c": 48 | try: 49 | r = await grop.client( 50 | functions.channels.CreateChannelRequest( # pylint:disable=E0602 51 | title=group_name, 52 | about="Welcome to this Channel", 53 | megagroup=False if type_of_group == "c" else True, 54 | ) 55 | ) 56 | created_chat_id = r.chats[0].id 57 | result = await grop.client( 58 | functions.messages.ExportChatInviteRequest( 59 | peer=created_chat_id, 60 | ) 61 | ) 62 | await grop.edit( 63 | "Your {} Group/Channel Created Successfully. Click [{}]({}) to join".format( 64 | group_name, group_name, result.link 65 | ) 66 | ) 67 | except Exception as e: # pylint:disable=C0103,W0703 68 | await grop.edit(str(e)) 69 | 70 | 71 | CMD_HELP.update( 72 | { 73 | "create": "\ 74 | Create\ 75 | \nUsage: Create Channel, Group & Group With Bot.\ 76 | \n\n.create g \ 77 | \nUsage: Create a Private Group.\ 78 | \n\n.create b \ 79 | \nUsage: Create a Group with Bot.\ 80 | \n\n.create c \ 81 | \nUsage: Create a Channel.\ 82 | " 83 | } 84 | ) 85 | -------------------------------------------------------------------------------- /userbot/modules/deezload.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 The Authors UniBorg (telegram userbot) 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 | # requires: deezloader hachoir Pillow 7 | # Ported from UniBorg by AnggaR96s 8 | 9 | import os 10 | import shutil 11 | import time 12 | 13 | import deezloader 14 | from hachoir.metadata import extractMetadata 15 | from hachoir.parser import createParser 16 | from telethon.tl.types import DocumentAttributeAudio 17 | 18 | from userbot import CMD_HELP, DEEZER_ARL_TOKEN, TEMP_DOWNLOAD_DIRECTORY 19 | from userbot.events import register 20 | 21 | 22 | @register(outgoing=True, pattern=r"^\.deez (.+?|) (FLAC|MP3\_320|MP3\_256|MP3\_128)") 23 | async def _(event): 24 | """DeezLoader by @An0nimia 25 | Ported for UniBorg by @SpEcHlDe""" 26 | if event.fwd_from: 27 | return 28 | 29 | strings = { 30 | "name": "DeezLoad", 31 | "arl_token_cfg_doc": "ARL Token for Deezer", 32 | "invalid_arl_token": "please set the required variables for this module", 33 | "wrong_cmd_syntax": "bruh, now i think how far should we go. please terminate my Session!", 34 | "server_error": "We're experiencing technical difficulties.", 35 | "processing": "`Downloading...`", 36 | "uploading": "`Uploading...`", 37 | } 38 | 39 | ARL_TOKEN = DEEZER_ARL_TOKEN 40 | 41 | if ARL_TOKEN is None: 42 | await event.edit(strings["invalid_arl_token"]) 43 | return 44 | 45 | try: 46 | loader = deezloader.Login(ARL_TOKEN) 47 | except Exception as er: 48 | await event.edit(str(er)) 49 | return 50 | 51 | temp_dl_path = os.path.join(TEMP_DOWNLOAD_DIRECTORY, str(time.time())) 52 | if not os.path.exists(temp_dl_path): 53 | os.makedirs(temp_dl_path) 54 | 55 | required_link = event.pattern_match.group(1) 56 | required_qty = event.pattern_match.group(2) 57 | 58 | await event.edit(strings["processing"]) 59 | 60 | if "spotify" in required_link: 61 | if "track" in required_link: 62 | required_track = loader.download_trackspo( 63 | required_link, 64 | output=temp_dl_path, 65 | quality=required_qty, 66 | recursive_quality=True, 67 | recursive_download=True, 68 | not_interface=True, 69 | ) 70 | await event.edit(strings["uploading"]) 71 | await upload_track(required_track, event) 72 | shutil.rmtree(temp_dl_path) 73 | await event.delete() 74 | 75 | elif "album" in required_link: 76 | reqd_albums = loader.download_albumspo( 77 | required_link, 78 | output=temp_dl_path, 79 | quality=required_qty, 80 | recursive_quality=True, 81 | recursive_download=True, 82 | not_interface=True, 83 | zips=False, 84 | ) 85 | await event.edit(strings["uploading"]) 86 | for required_track in reqd_albums: 87 | await upload_track(required_track, event) 88 | shutil.rmtree(temp_dl_path) 89 | await event.delete() 90 | 91 | elif "deezer" in required_link: 92 | if "track" in required_link: 93 | required_track = loader.download_trackdee( 94 | required_link, 95 | output=temp_dl_path, 96 | quality=required_qty, 97 | recursive_quality=True, 98 | recursive_download=True, 99 | not_interface=True, 100 | ) 101 | await event.edit(strings["uploading"]) 102 | await upload_track(required_track, event) 103 | shutil.rmtree(temp_dl_path) 104 | await event.delete() 105 | 106 | elif "album" in required_link: 107 | reqd_albums = loader.download_albumdee( 108 | required_link, 109 | output=temp_dl_path, 110 | quality=required_qty, 111 | recursive_quality=True, 112 | recursive_download=True, 113 | not_interface=True, 114 | zips=False, 115 | ) 116 | await event.edit(strings["uploading"]) 117 | for required_track in reqd_albums: 118 | await upload_track(required_track, event) 119 | shutil.rmtree(temp_dl_path) 120 | await event.delete() 121 | 122 | else: 123 | await event.edit(strings["wrong_cmd_syntax"]) 124 | 125 | 126 | async def upload_track(track_location, message): 127 | metadata = extractMetadata(createParser(track_location)) 128 | duration = 0 129 | title = "" 130 | performer = "" 131 | if metadata.has("duration"): 132 | duration = metadata.get("duration").seconds 133 | if metadata.has("title"): 134 | title = metadata.get("title") 135 | if metadata.has("artist"): 136 | performer = metadata.get("artist") 137 | document_attributes = [ 138 | DocumentAttributeAudio( 139 | duration=duration, 140 | voice=False, 141 | title=title, 142 | performer=performer, 143 | waveform=None, 144 | ) 145 | ] 146 | supports_streaming = True 147 | force_document = False 148 | caption_rts = os.path.basename(track_location) 149 | await message.client.send_file( 150 | message.chat_id, 151 | track_location, 152 | caption=caption_rts, 153 | force_document=force_document, 154 | supports_streaming=supports_streaming, 155 | allow_cache=False, 156 | attributes=document_attributes, 157 | ) 158 | os.remove(track_location) 159 | 160 | 161 | CMD_HELP.update( 162 | { 163 | "deezload": ".deez " 164 | "\nUsage: Download music from deezer." 165 | "\n\n *Format= `FLAC`, `MP3_320`, `MP3_256`, `MP3_128`." 166 | } 167 | ) 168 | -------------------------------------------------------------------------------- /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 | # Port to UserBot by @MoveAngel 7 | 8 | import pyfiglet 9 | 10 | from userbot import CMD_HELP 11 | from userbot.events import register 12 | 13 | 14 | @register(outgoing=True, pattern=r"^\.figlet(?: |$)(.*)") 15 | async def figlet(fg): 16 | if fg.fwd_from: 17 | return 18 | CMD_FIG = { 19 | "slant": "slant", 20 | "3D": "3-d", 21 | "5line": "5lineoblique", 22 | "alpha": "alphabet", 23 | "banner": "banner3-D", 24 | "doh": "doh", 25 | "iso": "isometric1", 26 | "letter": "letters", 27 | "allig": "alligator", 28 | "dotm": "dotmatrix", 29 | "bubble": "bubble", 30 | "bulb": "bulbhead", 31 | "digi": "digital", 32 | } 33 | input_str = fg.pattern_match.group(1) 34 | if "." in input_str: 35 | text, cmd = input_str.split(".", maxsplit=1) 36 | elif input_str is not None: 37 | cmd = None 38 | text = input_str 39 | else: 40 | await fg.edit("`Please add some text to figlet`") 41 | return 42 | if cmd is not None: 43 | try: 44 | font = CMD_FIG[cmd] 45 | except KeyError: 46 | await fg.edit("`Invalid selected font.`") 47 | return 48 | result = pyfiglet.figlet_format(text, font=font) 49 | else: 50 | result = pyfiglet.figlet_format(text) 51 | await fg.respond("‌‌‎`{}`".format(result)) 52 | await fg.delete() 53 | 54 | 55 | CMD_HELP.update( 56 | { 57 | "figlet": ".figlet" 58 | "\nUsage: Enhance ur text to strip line with anvil." 59 | "\n\nExample: `.figlet `" 60 | "\nSTYLE LIST: `slant`, `3D`, `5line`, `alpha`, `banner`, `doh`, `iso`, `letter`, `allig`, `dotm`, `bubble`, `bulb`, `digi`" 61 | } 62 | ) 63 | -------------------------------------------------------------------------------- /userbot/modules/filemanager.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 | 7 | import io 8 | import os 9 | import os.path 10 | import time 11 | from os.path import exists, isdir 12 | 13 | from userbot import CMD_HELP 14 | from userbot.events import register 15 | from userbot.utils import humanbytes 16 | 17 | MAX_MESSAGE_SIZE_LIMIT = 4095 18 | 19 | 20 | @register(outgoing=True, pattern=r"^\.ls ?(.*)") 21 | async def lst(event): 22 | if event.fwd_from: 23 | return 24 | cat = event.pattern_match.group(1) 25 | if cat: 26 | path = cat 27 | else: 28 | path = os.getcwd() 29 | if not exists(path): 30 | await event.edit( 31 | f"There is no such directory or file with the name `{cat}` check again!" 32 | ) 33 | return 34 | if isdir(path): 35 | if cat: 36 | msg = "Folders and Files in `{}` :\n\n".format(path) 37 | lists = os.listdir(path) 38 | else: 39 | msg = "Folders and Files in Current Directory :\n\n" 40 | lists = os.listdir(path) 41 | files = "" 42 | folders = "" 43 | for contents in sorted(lists): 44 | catpath = path + "/" + contents 45 | if not isdir(catpath): 46 | size = os.stat(catpath).st_size 47 | if contents.endswith((".mp3", ".flac", ".wav", ".m4a")): 48 | files += "🎵 " + f"`{contents}`\n" 49 | if contents.endswith((".opus")): 50 | files += "🎙 " + f"`{contents}`\n" 51 | elif contents.endswith( 52 | (".mkv", ".mp4", ".webm", ".avi", ".mov", ".flv") 53 | ): 54 | files += "🎞 " + f"`{contents}`\n" 55 | elif contents.endswith( 56 | (".zip", ".tar", ".tar.gz", ".rar", ".7z", ".xz") 57 | ): 58 | files += "🗜 " + f"`{contents}`\n" 59 | elif contents.endswith( 60 | (".jpg", ".jpeg", ".png", ".gif", ".bmp", ".ico", ". webp") 61 | ): 62 | files += "🖼 " + f"`{contents}`\n" 63 | elif contents.endswith((".exe", ".deb")): 64 | files += "⚙️ " + f"`{contents}`\n" 65 | elif contents.endswith((".iso", ".img")): 66 | files += "💿 " + f"`{contents}`\n" 67 | elif contents.endswith((".apk", ".xapk")): 68 | files += "📱 " + f"`{contents}`\n" 69 | elif contents.endswith((".py")): 70 | files += "🐍 " + f"`{contents}`\n" 71 | else: 72 | files += "📄 " + f"`{contents}`\n" 73 | else: 74 | folders += f"📁 `{contents}`\n" 75 | if files or folders: 76 | msg = msg + folders + files 77 | else: 78 | msg = msg + "__empty path__" 79 | else: 80 | size = os.stat(path).st_size 81 | msg = "The details of given file :\n\n" 82 | if path.endswith((".mp3", ".flac", ".wav", ".m4a")): 83 | mode = "🎵 " 84 | if path.endswith((".opus")): 85 | mode = "🎙 " 86 | elif path.endswith((".mkv", ".mp4", ".webm", ".avi", ".mov", ".flv")): 87 | mode = "🎞 " 88 | elif path.endswith((".zip", ".tar", ".tar.gz", ".rar", ".7z", ".xz")): 89 | mode = "🗜 " 90 | elif path.endswith((".jpg", ".jpeg", ".png", ".gif", ".bmp", ".ico", ". webp")): 91 | mode = "🖼 " 92 | elif path.endswith((".exe", ".deb")): 93 | mode = "⚙️ " 94 | elif path.endswith((".iso", ".img")): 95 | mode = "💿 " 96 | elif path.endswith((".apk", ".xapk")): 97 | mode = "📱 " 98 | elif path.endswith((".py")): 99 | mode = "🐍 " 100 | else: 101 | mode = "📄 " 102 | time.ctime(os.path.getctime(path)) 103 | time2 = time.ctime(os.path.getmtime(path)) 104 | time3 = time.ctime(os.path.getatime(path)) 105 | msg += f"**Location :** `{path}`\n" 106 | msg += f"**Icon :** `{mode}`\n" 107 | msg += f"**Size :** `{humanbytes(size)}`\n" 108 | msg += f"**Last Modified Time:** `{time2}`\n" 109 | msg += f"**Last Accessed Time:** `{time3}`" 110 | 111 | if len(msg) > MAX_MESSAGE_SIZE_LIMIT: 112 | with io.BytesIO(str.encode(msg)) as out_file: 113 | out_file.name = "ls.txt" 114 | await event.client.send_file( 115 | event.chat_id, 116 | out_file, 117 | force_document=True, 118 | allow_cache=False, 119 | caption=path, 120 | ) 121 | await event.delete() 122 | else: 123 | await event.edit(msg) 124 | 125 | 126 | CMD_HELP.update( 127 | { 128 | "file": ".ls " 129 | "\nUsage: Get an information about data covid-19 in your country." 130 | } 131 | ) 132 | -------------------------------------------------------------------------------- /userbot/modules/filter.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 module for filter commands """ 7 | 8 | from asyncio import sleep 9 | from re import IGNORECASE, escape, search 10 | 11 | from userbot import BOTLOG, BOTLOG_CHATID, CMD_HELP 12 | from userbot.events import register 13 | 14 | 15 | @register(incoming=True, disable_edited=True, disable_errors=True) 16 | async def filter_incoming_handler(handler): 17 | """ Checks if the incoming message contains handler of a filter """ 18 | try: 19 | if not (await handler.get_sender()).bot: 20 | try: 21 | from userbot.modules.sql_helper.filter_sql import get_filters 22 | except AttributeError: 23 | await handler.edit("`Running on Non-SQL mode!`") 24 | return 25 | name = handler.raw_text 26 | filters = get_filters(handler.chat_id) 27 | if not filters: 28 | return 29 | for trigger in filters: 30 | pattern = r"( |^|[^\w])" + escape(trigger.keyword) + r"( |$|[^\w])" 31 | pro = search(pattern, name, flags=IGNORECASE) 32 | if pro and trigger.f_mesg_id: 33 | msg_o = await handler.client.get_messages( 34 | entity=BOTLOG_CHATID, ids=int(trigger.f_mesg_id) 35 | ) 36 | await handler.reply(msg_o.message, file=msg_o.media) 37 | elif pro and trigger.reply: 38 | await handler.reply(trigger.reply) 39 | except AttributeError: 40 | pass 41 | 42 | 43 | @register(outgoing=True, pattern=r"^.filter (.*)") 44 | async def add_new_filter(new_handler): 45 | """ For .filter command, allows adding new filters in a chat """ 46 | try: 47 | from userbot.modules.sql_helper.filter_sql import add_filter 48 | except AttributeError: 49 | await new_handler.edit("`Running on Non-SQL mode!`") 50 | return 51 | value = new_handler.pattern_match.group(1).split(None, 1) 52 | """ - The first words after .filter(space) is the keyword - """ 53 | keyword = value[0] 54 | try: 55 | string = value[1] 56 | except IndexError: 57 | string = None 58 | msg = await new_handler.get_reply_message() 59 | msg_id = None 60 | if msg and msg.media and not string: 61 | if BOTLOG_CHATID: 62 | await new_handler.client.send_message( 63 | BOTLOG_CHATID, 64 | f"#FILTER\nCHAT ID: {new_handler.chat_id}\nTRIGGER: {keyword}" 65 | "\n\nThe following message is saved as the filter's reply data for the chat, please do NOT delete it !!", 66 | ) 67 | msg_o = await new_handler.client.forward_messages( 68 | entity=BOTLOG_CHATID, 69 | messages=msg, 70 | from_peer=new_handler.chat_id, 71 | silent=True, 72 | ) 73 | msg_id = msg_o.id 74 | else: 75 | return await new_handler.edit( 76 | "`Saving media as reply to the filter requires the BOTLOG_CHATID to be set.`" 77 | ) 78 | elif new_handler.reply_to_msg_id and not string: 79 | rep_msg = await new_handler.get_reply_message() 80 | string = rep_msg.text 81 | success = "`Filter` **{}** `{} successfully`." 82 | if add_filter(str(new_handler.chat_id), keyword, string, msg_id) is True: 83 | await new_handler.edit(success.format(keyword, "added")) 84 | else: 85 | await new_handler.edit(success.format(keyword, "updated")) 86 | 87 | 88 | @register(outgoing=True, pattern=r"^.stop (.*)") 89 | async def remove_a_filter(r_handler): 90 | """ For .stop command, allows you to remove a filter from a chat. """ 91 | try: 92 | from userbot.modules.sql_helper.filter_sql import remove_filter 93 | except AttributeError: 94 | return await r_handler.edit("`Running on Non-SQL mode!`") 95 | filt = r_handler.pattern_match.group(1) 96 | if not remove_filter(r_handler.chat_id, filt): 97 | await r_handler.edit("`Filter` **{}** `doesn't exist`.".format(filt)) 98 | else: 99 | await r_handler.edit( 100 | "`Filter` **{}** `was deleted successfully`.".format(filt) 101 | ) 102 | 103 | 104 | @register(outgoing=True, pattern="^.rmbotfilters (.*)") 105 | async def kick_marie_filter(event): 106 | """ For .rmfilters command, allows you to kick all \ 107 | Marie(or her clones) filters from a chat. """ 108 | event.text[0] 109 | bot_type = event.pattern_match.group(1).lower() 110 | if bot_type not in ["marie", "rose"]: 111 | return await event.edit("`That bot is not yet supported!`") 112 | await event.edit("```Will be kicking away all Filters!```") 113 | await sleep(3) 114 | resp = await event.get_reply_message() 115 | filters = resp.text.split("-")[1:] 116 | for i in filters: 117 | if bot_type.lower() == "marie": 118 | await event.reply("/stop %s" % (i.strip())) 119 | if bot_type.lower() == "rose": 120 | i = i.replace("`", "") 121 | await event.reply("/stop %s" % (i.strip())) 122 | await sleep(0.3) 123 | await event.respond("```Successfully purged bots filters yaay!```\n Gimme cookies!") 124 | if BOTLOG: 125 | await event.client.send_message( 126 | BOTLOG_CHATID, "I cleaned all filters at " + str(event.chat_id) 127 | ) 128 | 129 | 130 | @register(outgoing=True, pattern="^.filters$") 131 | async def filters_active(event): 132 | """ For .filters command, lists all of the active filters in a chat. """ 133 | try: 134 | from userbot.modules.sql_helper.filter_sql import get_filters 135 | except AttributeError: 136 | return await event.edit("`Running on Non-SQL mode!`") 137 | transact = "`There are no filters in this chat.`" 138 | filters = get_filters(event.chat_id) 139 | for filt in filters: 140 | if transact == "`There are no filters in this chat.`": 141 | transact = "Active filters in this chat:\n" 142 | transact += "`{}`\n".format(filt.keyword) 143 | else: 144 | transact += "`{}`\n".format(filt.keyword) 145 | 146 | await event.edit(transact) 147 | 148 | 149 | CMD_HELP.update( 150 | { 151 | "filter": ".filters\ 152 | \nUsage: Lists all active userbot filters in a chat.\ 153 | \n\n.filter or reply to a message with .filter \ 154 | \nUsage: Saves the replied message as a reply to the 'keyword'.\ 155 | \nThe bot will reply to the message whenever 'keyword' is mentioned.\ 156 | \nWorks with everything from files to stickers.\ 157 | \n\n.stop \ 158 | \nUsage: Stops the specified filter.\ 159 | \n\n.rmbotfilters \ 160 | \nUsage: Removes all filters of admin bots (Currently supported: Marie, Rose and their clones.) in the chat." 161 | } 162 | ) 163 | -------------------------------------------------------------------------------- /userbot/modules/fonts.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 | # This module is maked by Project TESLA 6 | 7 | from userbot import CMD_HELP 8 | from userbot.events import register 9 | 10 | normiefont = [ 11 | "a", 12 | "b", 13 | "c", 14 | "d", 15 | "e", 16 | "f", 17 | "g", 18 | "h", 19 | "i", 20 | "j", 21 | "k", 22 | "l", 23 | "m", 24 | "n", 25 | "o", 26 | "p", 27 | "q", 28 | "r", 29 | "s", 30 | "t", 31 | "u", 32 | "v", 33 | "w", 34 | "x", 35 | "y", 36 | "z", 37 | ] 38 | weebyfont = [ 39 | "卂", 40 | "乃", 41 | "匚", 42 | "刀", 43 | "乇", 44 | "下", 45 | "厶", 46 | "卄", 47 | "工", 48 | "丁", 49 | "长", 50 | "乚", 51 | "从", 52 | "𠘨", 53 | "口", 54 | "尸", 55 | "㔿", 56 | "尺", 57 | "丂", 58 | "丅", 59 | "凵", 60 | "リ", 61 | "山", 62 | "乂", 63 | "丫", 64 | "乙", 65 | ] 66 | circlyfont = [ 67 | "🅐", 68 | "🅑", 69 | "🅒", 70 | "🅓", 71 | "🅔", 72 | "🅕", 73 | "🅖", 74 | "🅗", 75 | "🅘", 76 | "🅙", 77 | "🅚", 78 | "🅛", 79 | "🅜", 80 | "🅝", 81 | "🅞", 82 | "🅟", 83 | "🅠", 84 | "🅡", 85 | "🅢", 86 | "🅣", 87 | "🅤", 88 | "🅥", 89 | "🅦", 90 | "🅧", 91 | "🅨", 92 | "🅩", 93 | ] 94 | oldengfont = [ 95 | "𝔄", 96 | "𝔅", 97 | "ℭ", 98 | "𝔇", 99 | "𝔈", 100 | "𝔉", 101 | "𝔊", 102 | "ℌ", 103 | "ℑ", 104 | "𝔍", 105 | "𝔎", 106 | "𝔏", 107 | "𝔐", 108 | "𝔑", 109 | "𝔒", 110 | "𝔓", 111 | "𝔔", 112 | "ℜ", 113 | "𝔖", 114 | "𝔗", 115 | "𝔘", 116 | "𝔙", 117 | "𝔚", 118 | "𝔛", 119 | "𝔜", 120 | "ℨ", 121 | ] 122 | 123 | 124 | @register(outgoing=True, pattern="^.weebify(?: |$)(.*)") 125 | async def weebify(event): 126 | 127 | args = event.pattern_match.group(1) 128 | if not args: 129 | get = await event.get_reply_message() 130 | args = get.text 131 | if not args: 132 | await event.edit("`What I am Supposed to Weebify U Dumb`") 133 | return 134 | string = " ".join(args).lower() 135 | for normiecharacter in string: 136 | if normiecharacter in normiefont: 137 | weebycharacter = weebyfont[normiefont.index(normiecharacter)] 138 | string = string.replace(normiecharacter, weebycharacter) 139 | await event.edit(string) 140 | 141 | 142 | @register(outgoing=True, pattern="^.circlify(?: |$)(.*)") 143 | async def circly(event): 144 | 145 | args = event.pattern_match.group(1) 146 | if not args: 147 | get = await event.get_reply_message() 148 | args = get.text 149 | if not args: 150 | await event.edit("`What I am Supposed to circlyfy U Dumb`") 151 | return 152 | string = " ".join(args).lower() 153 | for normiecharacter in string: 154 | if normiecharacter in normiefont: 155 | circlycharacter = circlyfont[normiefont.index(normiecharacter)] 156 | string = string.replace(normiecharacter, circlycharacter) 157 | await event.edit(string) 158 | 159 | 160 | @register(outgoing=True, pattern="^.oldeng(?: |$)(.*)") 161 | async def oldy(event): 162 | 163 | args = event.pattern_match.group(1) 164 | if not args: 165 | get = await event.get_reply_message() 166 | args = get.text 167 | if not args: 168 | await event.edit("`What, I am Supposed To Work with text only`") 169 | return 170 | string = " ".join(args).lower() 171 | for normiecharacter in string: 172 | if normiecharacter in normiefont: 173 | oldycharacter = oldengfont[normiefont.index(normiecharacter)] 174 | string = string.replace(normiecharacter, oldycharacter) 175 | await event.edit(string) 176 | 177 | 178 | CMD_HELP.update( 179 | { 180 | "fonts": ".weebify :- weebifys your text \ 181 | \n.circlify :- circlifies text \ 182 | \n.oldeng :- old eng font" 183 | } 184 | ) 185 | -------------------------------------------------------------------------------- /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 os 8 | import time 9 | from datetime import datetime 10 | 11 | import aiohttp 12 | from github import Github 13 | 14 | from userbot import CMD_HELP, GIT_REPO_NAME, GITHUB_ACCESS_TOKEN, bot 15 | from userbot.events import register 16 | 17 | GIT_TEMP_DIR = "/One4uBot/temp/" 18 | 19 | 20 | @register(outgoing=True, pattern=r".git (.*)") 21 | async def github(event): 22 | username = event.pattern_match.group(1) 23 | URL = f"https://api.github.com/users/{username}" 24 | await event.get_chat() 25 | async with aiohttp.ClientSession() as session: 26 | async with session.get(URL) as request: 27 | if request.status == 404: 28 | return await event.reply(f"`{username} not found`") 29 | 30 | result = await request.json() 31 | 32 | url = result.get("html_url", None) 33 | name = result.get("name", None) 34 | company = result.get("company", None) 35 | bio = result.get("bio", None) 36 | created_at = result.get("created_at", "Not Found") 37 | 38 | REPLY = ( 39 | f"GitHub Info for `{username}`\n" 40 | f"Username: `{name}`\n" 41 | f"Bio: `{bio}`\n" 42 | f"URL: {url}\n" 43 | f"Company: `{company}`\n" 44 | f"Created at: `{created_at}`\n" 45 | f"More info : [Here](https://api.github.com/users/{username}/events/public)" 46 | ) 47 | 48 | if not result.get("repos_url", None): 49 | return await event.edit(REPLY) 50 | async with session.get(result.get("repos_url", None)) as request: 51 | result = request.json 52 | if request.status == 404: 53 | return await event.edit(REPLY) 54 | 55 | result = await request.json() 56 | 57 | REPLY += "\nRepos:\n" 58 | 59 | for nr in range(len(result)): 60 | REPLY += f"[{result[nr].get('name', None)}]({result[nr].get('html_url', None)})\n" 61 | 62 | await event.edit(REPLY) 63 | 64 | 65 | @register(outgoing=True, pattern="^.commit(?: |$)(.*)") 66 | async def download(event): 67 | if event.fwd_from: 68 | return 69 | if GITHUB_ACCESS_TOKEN is None: 70 | await event.edit("`Please ADD Proper Access Token from github.com`") 71 | return 72 | if GIT_REPO_NAME is None: 73 | await event.edit("`Please ADD Proper Github Repo Name of your userbot`") 74 | return 75 | mone = await event.reply("Processing ...") 76 | if not os.path.isdir(GIT_TEMP_DIR): 77 | os.makedirs(GIT_TEMP_DIR) 78 | start = datetime.now() 79 | reply_message = await event.get_reply_message() 80 | try: 81 | time.time() 82 | print("Downloading to TEMP directory") 83 | downloaded_file_name = await bot.download_media( 84 | reply_message.media, GIT_TEMP_DIR 85 | ) 86 | except Exception as e: 87 | await mone.edit(str(e)) 88 | else: 89 | end = datetime.now() 90 | ms = (end - start).seconds 91 | await event.delete() 92 | await mone.edit( 93 | "Downloaded to `{}` in {} seconds.".format(downloaded_file_name, ms) 94 | ) 95 | await mone.edit("Committing to Github....") 96 | await git_commit(downloaded_file_name, mone) 97 | 98 | 99 | async def git_commit(file_name, mone): 100 | content_list = [] 101 | access_token = GITHUB_ACCESS_TOKEN 102 | g = Github(access_token) 103 | file = open(file_name, "r", encoding="utf-8") 104 | commit_data = file.read() 105 | repo = g.get_repo(GIT_REPO_NAME) 106 | print(repo.name) 107 | create_file = True 108 | contents = repo.get_contents("") 109 | for content_file in contents: 110 | content_list.append(str(content_file)) 111 | print(content_file) 112 | for i in content_list: 113 | create_file = True 114 | if i == 'ContentFile(path="' + file_name + '")': 115 | return await mone.edit("`File Already Exists`") 116 | create_file = False 117 | file_name = "userbot/modules/" + file_name 118 | if create_file: 119 | file_name = file_name.replace(GIT_TEMP_DIR, "") 120 | print(file_name) 121 | try: 122 | repo.create_file( 123 | file_name, "Uploaded New Plugin", commit_data, branch="sql-extended" 124 | ) 125 | print("Committed File") 126 | ccess = GIT_REPO_NAME 127 | ccess = ccess.strip() 128 | await mone.edit( 129 | f"`Commited On Your Github Repo`\n\n[Your Modules](https://github.com/{ccess}/tree/sql-extended/userbot/modules/)" 130 | ) 131 | except BaseException: 132 | print("Cannot Create Plugin") 133 | await mone.edit("Cannot Upload Plugin") 134 | else: 135 | return await mone.edit("`Committed Suicide`") 136 | 137 | 138 | CMD_HELP.update( 139 | { 140 | "github": ".git " 141 | "\nUsage: Like .whois but for GitHub usernames." 142 | "\n\n.commit " 143 | "\nUsage: GITHUB File Uploader Plugin for userbot. Heroku Automation should be Enabled." 144 | } 145 | ) 146 | -------------------------------------------------------------------------------- /userbot/modules/hash.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 module containing hash and encode/decode commands. """ 7 | 8 | from subprocess import PIPE 9 | from subprocess import run as runapp 10 | 11 | import pybase64 12 | 13 | from userbot import CMD_HELP 14 | from userbot.events import register 15 | 16 | 17 | @register(outgoing=True, pattern="^.hash (.*)") 18 | async def gethash(hash_q): 19 | """ For .hash command, find the md5, sha1, sha256, sha512 of the string. """ 20 | hashtxt_ = hash_q.pattern_match.group(1) 21 | hashtxt = open("hashdis.txt", "w+") 22 | hashtxt.write(hashtxt_) 23 | hashtxt.close() 24 | md5 = runapp(["md5sum", "hashdis.txt"], stdout=PIPE) 25 | md5 = md5.stdout.decode() 26 | sha1 = runapp(["sha1sum", "hashdis.txt"], stdout=PIPE) 27 | sha1 = sha1.stdout.decode() 28 | sha256 = runapp(["sha256sum", "hashdis.txt"], stdout=PIPE) 29 | sha256 = sha256.stdout.decode() 30 | sha512 = runapp(["sha512sum", "hashdis.txt"], stdout=PIPE) 31 | runapp(["rm", "hashdis.txt"], stdout=PIPE) 32 | sha512 = sha512.stdout.decode() 33 | ans = ( 34 | "Text: `" 35 | + hashtxt_ 36 | + "`\nMD5: `" 37 | + md5 38 | + "`SHA1: `" 39 | + sha1 40 | + "`SHA256: `" 41 | + sha256 42 | + "`SHA512: `" 43 | + sha512[:-1] 44 | + "`" 45 | ) 46 | if len(ans) > 4096: 47 | hashfile = open("hashes.txt", "w+") 48 | hashfile.write(ans) 49 | hashfile.close() 50 | await hash_q.client.send_file( 51 | hash_q.chat_id, 52 | "hashes.txt", 53 | reply_to=hash_q.id, 54 | caption="`It's too big, sending a text file instead. `", 55 | ) 56 | runapp(["rm", "hashes.txt"], stdout=PIPE) 57 | else: 58 | await hash_q.reply(ans) 59 | 60 | 61 | @register(outgoing=True, pattern="^.base64 (en|de) (.*)") 62 | async def endecrypt(query): 63 | """ For .base64 command, find the base64 encoding of the given string. """ 64 | if query.pattern_match.group(1) == "en": 65 | lething = str(pybase64.b64encode(bytes(query.pattern_match.group(2), "utf-8")))[ 66 | 2: 67 | ] 68 | await query.reply("Encoded: `" + lething[:-1] + "`") 69 | else: 70 | lething = str( 71 | pybase64.b64decode( 72 | bytes(query.pattern_match.group(2), "utf-8"), validate=True 73 | ) 74 | )[2:] 75 | await query.reply("Decoded: `" + lething[:-1] + "`") 76 | 77 | 78 | CMD_HELP.update({"base64": "Find the base64 encoding of the given string"}) 79 | 80 | CMD_HELP.update( 81 | { 82 | "hash": "Find the md5, sha1, sha256, sha512 of the string when written into a txt file." 83 | } 84 | ) 85 | -------------------------------------------------------------------------------- /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 | if args: 17 | if args in CMD_HELP: 18 | await event.edit(str(CMD_HELP[args])) 19 | else: 20 | await event.edit("Please specify a valid module name.") 21 | else: 22 | string = "" 23 | for i in CMD_HELP: 24 | string += "`" + str(i) 25 | string += "`\t\t\t||\t\t\t " 26 | await event.edit( 27 | f"{string}" 28 | "\n\nSpecify which module do you want help for !!\ 29 | \n**Usage:** `.help` " 30 | ) 31 | -------------------------------------------------------------------------------- /userbot/modules/invite.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 From UniBorg to UserBot by @afdulfauzan 7 | 8 | from asyncio import sleep 9 | 10 | from telethon import functions 11 | 12 | from userbot import CMD_HELP 13 | from userbot.events import register 14 | 15 | 16 | @register(outgoing=True, pattern="^.invite(?: |$)(.*)") 17 | async def _(event): 18 | if event.fwd_from: 19 | return 20 | to_add_users = event.pattern_match.group(1) 21 | if event.is_private: 22 | await event.edit("`.invite` users to a chat, not to a Private Message") 23 | else: 24 | if not event.is_channel and event.is_group: 25 | # https://lonamiwebs.github.io/Telethon/methods/messages/add_chat_user.html 26 | for user_id in to_add_users.split(" "): 27 | try: 28 | await event.client( 29 | functions.messages.AddChatUserRequest( 30 | chat_id=event.chat_id, user_id=user_id, fwd_limit=1000000 31 | ) 32 | ) 33 | except Exception as e: 34 | await event.edit(str(e)) 35 | return 36 | await event.edit("`Invited Successfully`") 37 | await sleep(2) 38 | await event.delete() 39 | else: 40 | # https://lonamiwebs.github.io/Telethon/methods/channels/invite_to_channel.html 41 | for user_id in to_add_users.split(" "): 42 | try: 43 | await event.client( 44 | functions.channels.InviteToChannelRequest( 45 | channel=event.chat_id, users=[user_id] 46 | ) 47 | ) 48 | except Exception as e: 49 | await event.edit(str(e)) 50 | return 51 | await event.edit("`Invited Successfully`") 52 | await sleep(2) 53 | await event.delete() 54 | 55 | 56 | CMD_HELP.update( 57 | { 58 | "invite": ".invite \ 59 | \nUsage: Invite some user or bots if u want." 60 | } 61 | ) 62 | -------------------------------------------------------------------------------- /userbot/modules/locks.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 | from telethon.tl.functions.messages import EditChatDefaultBannedRightsRequest 8 | from telethon.tl.types import ChatBannedRights 9 | 10 | from userbot import CMD_HELP 11 | from userbot.events import register 12 | 13 | 14 | @register(outgoing=True, pattern=r"^.lock ?(.*)") 15 | async def locks(event): 16 | input_str = event.pattern_match.group(1).lower() 17 | peer_id = event.chat_id 18 | msg = None 19 | media = None 20 | sticker = None 21 | gif = None 22 | gamee = None 23 | ainline = None 24 | gpoll = None 25 | adduser = None 26 | cpin = None 27 | changeinfo = None 28 | if input_str == "msg": 29 | msg = True 30 | what = "messages" 31 | elif input_str == "media": 32 | media = True 33 | what = "media" 34 | elif input_str == "sticker": 35 | sticker = True 36 | what = "stickers" 37 | elif input_str == "gif": 38 | gif = True 39 | what = "GIFs" 40 | elif input_str == "game": 41 | gamee = True 42 | what = "games" 43 | elif input_str == "inline": 44 | ainline = True 45 | what = "inline bots" 46 | elif input_str == "poll": 47 | gpoll = True 48 | what = "polls" 49 | elif input_str == "invite": 50 | adduser = True 51 | what = "invites" 52 | elif input_str == "pin": 53 | cpin = True 54 | what = "pins" 55 | elif input_str == "info": 56 | changeinfo = True 57 | what = "chat info" 58 | elif input_str == "all": 59 | msg = True 60 | media = True 61 | sticker = True 62 | gif = True 63 | gamee = True 64 | ainline = True 65 | gpoll = True 66 | adduser = True 67 | cpin = True 68 | changeinfo = True 69 | what = "everything" 70 | else: 71 | if not input_str: 72 | await event.edit("`I can't lock nothing !!`") 73 | return 74 | else: 75 | await event.edit(f"`Invalid lock type:` {input_str}") 76 | return 77 | 78 | lock_rights = ChatBannedRights( 79 | until_date=None, 80 | send_messages=msg, 81 | send_media=media, 82 | send_stickers=sticker, 83 | send_gifs=gif, 84 | send_games=gamee, 85 | send_inline=ainline, 86 | send_polls=gpoll, 87 | invite_users=adduser, 88 | pin_messages=cpin, 89 | change_info=changeinfo, 90 | ) 91 | try: 92 | await event.client( 93 | EditChatDefaultBannedRightsRequest(peer=peer_id, banned_rights=lock_rights) 94 | ) 95 | await event.edit(f"`Locked {what} for this chat !!`") 96 | except BaseException as e: 97 | await event.edit(f"`Do I have proper rights for that ??`\n**Error:** {str(e)}") 98 | return 99 | 100 | 101 | @register(outgoing=True, pattern=r"^.unlock ?(.*)") 102 | async def rem_locks(event): 103 | input_str = event.pattern_match.group(1).lower() 104 | peer_id = event.chat_id 105 | msg = None 106 | media = None 107 | sticker = None 108 | gif = None 109 | gamee = None 110 | ainline = None 111 | gpoll = None 112 | adduser = None 113 | cpin = None 114 | changeinfo = None 115 | if input_str == "msg": 116 | msg = False 117 | what = "messages" 118 | elif input_str == "media": 119 | media = False 120 | what = "media" 121 | elif input_str == "sticker": 122 | sticker = False 123 | what = "stickers" 124 | elif input_str == "gif": 125 | gif = False 126 | what = "GIFs" 127 | elif input_str == "game": 128 | gamee = False 129 | what = "games" 130 | elif input_str == "inline": 131 | ainline = False 132 | what = "inline bots" 133 | elif input_str == "poll": 134 | gpoll = False 135 | what = "polls" 136 | elif input_str == "invite": 137 | adduser = False 138 | what = "invites" 139 | elif input_str == "pin": 140 | cpin = False 141 | what = "pins" 142 | elif input_str == "info": 143 | changeinfo = False 144 | what = "chat info" 145 | elif input_str == "all": 146 | msg = False 147 | media = False 148 | sticker = False 149 | gif = False 150 | gamee = False 151 | ainline = False 152 | gpoll = False 153 | adduser = False 154 | cpin = False 155 | changeinfo = False 156 | what = "everything" 157 | else: 158 | if not input_str: 159 | await event.edit("`I can't unlock nothing !!`") 160 | return 161 | else: 162 | await event.edit(f"`Invalid unlock type:` {input_str}") 163 | return 164 | 165 | unlock_rights = ChatBannedRights( 166 | until_date=None, 167 | send_messages=msg, 168 | send_media=media, 169 | send_stickers=sticker, 170 | send_gifs=gif, 171 | send_games=gamee, 172 | send_inline=ainline, 173 | send_polls=gpoll, 174 | invite_users=adduser, 175 | pin_messages=cpin, 176 | change_info=changeinfo, 177 | ) 178 | try: 179 | await event.client( 180 | EditChatDefaultBannedRightsRequest( 181 | peer=peer_id, banned_rights=unlock_rights 182 | ) 183 | ) 184 | await event.edit(f"`Unlocked {what} for this chat !!`") 185 | except BaseException as e: 186 | await event.edit(f"`Do I have proper rights for that ??`\n**Error:** {str(e)}") 187 | return 188 | 189 | 190 | CMD_HELP.update( 191 | { 192 | "locks": ".lock or .unlock \ 193 | \nUsage: Allows you to lock/unlock some common message types in the chat.\ 194 | [NOTE: Requires proper admin rights in the chat !!]\ 195 | \n\nAvailable message types to lock/unlock are: \ 196 | \n`all, msg, media, sticker, gif, game, inline, poll, invite, pin, info`" 197 | } 198 | ) 199 | -------------------------------------------------------------------------------- /userbot/modules/lyrics.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 os 8 | 9 | import lyricsgenius 10 | from pylast import User 11 | 12 | from userbot import CMD_HELP, GENIUS, LASTFM_USERNAME, lastfm 13 | from userbot.events import register 14 | 15 | if GENIUS is not None: 16 | genius = lyricsgenius.Genius(GENIUS) 17 | 18 | 19 | @register(outgoing=True, pattern="^.lyrics (?:(now)|(.*) - (.*))") 20 | async def lyrics(lyric): 21 | await lyric.edit("`Getting information...`") 22 | if GENIUS is None: 23 | await lyric.edit("`Provide genius access token to Heroku ConfigVars...`") 24 | return False 25 | if lyric.pattern_match.group(1) == "now": 26 | playing = User(LASTFM_USERNAME, lastfm).get_now_playing() 27 | if playing is None: 28 | await lyric.edit("`No information current lastfm scrobbling...`") 29 | return False 30 | artist = playing.get_artist() 31 | song = playing.get_title() 32 | else: 33 | artist = lyric.pattern_match.group(2) 34 | song = lyric.pattern_match.group(3) 35 | await lyric.edit(f"`Searching lyrics for {artist} - {song}...`") 36 | songs = genius.search_song(song, artist) 37 | if songs is None: 38 | await lyric.edit(f"`Song` **{artist} - {song}** `not found...`") 39 | return False 40 | if len(songs.lyrics) > 4096: 41 | await lyric.edit("`Lyrics is too big, view the file to see it.`") 42 | with open("lyrics.txt", "w+") as f: 43 | f.write(f"Search query: \n{artist} - {song}\n\n{songs.lyrics}") 44 | await lyric.client.send_file( 45 | lyric.chat_id, 46 | "lyrics.txt", 47 | reply_to=lyric.id, 48 | ) 49 | os.remove("lyrics.txt") 50 | return True 51 | else: 52 | await lyric.edit( 53 | f"**Search query**:\n`{artist}` - `{song}`" f"\n\n```{songs.lyrics}```" 54 | ) 55 | return True 56 | 57 | 58 | CMD_HELP.update( 59 | { 60 | "lyrics": ".lyrics ** - **" 61 | "\nUsage: Get lyrics matched artist and song." 62 | "\n\n.lyrics now" 63 | "\nUsage: Get lyrics artist and song from current lastfm scrobbling." 64 | } 65 | ) 66 | -------------------------------------------------------------------------------- /userbot/modules/misc.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 | # You can find misc modules, which dont fit in anything xD 7 | """ Userbot module for other small commands. """ 8 | 9 | import io 10 | import sys 11 | from os import execl 12 | from random import randint 13 | from time import sleep 14 | 15 | from userbot import BOTLOG, BOTLOG_CHATID, CMD_HELP, bot 16 | from userbot.events import register 17 | from userbot.utils import time_formatter 18 | 19 | 20 | @register(outgoing=True, pattern="^.random") 21 | async def randomise(items): 22 | """ For .random command, get a random item from the list of items. """ 23 | itemo = (items.text[8:]).split() 24 | if len(itemo) < 2: 25 | await items.edit( 26 | "`2 or more items are required! Check .help random for more info.`" 27 | ) 28 | return 29 | index = randint(1, len(itemo) - 1) 30 | await items.edit( 31 | "**Query: **\n`" + items.text[8:] + "`\n**Output: **\n`" + itemo[index] + "`" 32 | ) 33 | 34 | 35 | @register(outgoing=True, pattern="^.sleep ([0-9]+)$") 36 | async def sleepybot(time): 37 | """ For .sleep command, let the userbot snooze for a few second. """ 38 | counter = int(time.pattern_match.group(1)) 39 | await time.edit("`I am sulking and snoozing...`") 40 | if BOTLOG: 41 | str_counter = time_formatter(counter) 42 | await time.client.send_message( 43 | BOTLOG_CHATID, 44 | f"You put the bot to sleep for {str_counter}.", 45 | ) 46 | sleep(counter) 47 | await time.edit("`OK, I'm awake now.`") 48 | 49 | 50 | @register(outgoing=True, pattern="^.shutdown$") 51 | async def killbot(shut): 52 | """For .shutdown command, shut the bot down.""" 53 | await shut.edit("`Goodbye *Windows XP shutdown sound*....`") 54 | if BOTLOG: 55 | await shut.client.send_message(BOTLOG_CHATID, "#SHUTDOWN \n" "Bot shut down") 56 | await bot.disconnect() 57 | 58 | 59 | @register(outgoing=True, pattern="^.restart$") 60 | async def killdabot(reboot): 61 | await reboot.edit("`*i would be back in a moment*`") 62 | if BOTLOG: 63 | await reboot.client.send_message(BOTLOG_CHATID, "#RESTART \n" "Bot Restarted") 64 | await bot.disconnect() 65 | # Spin a new instance of bot 66 | execl(sys.executable, sys.executable, *sys.argv) 67 | # Shut the existing one down 68 | exit() 69 | 70 | 71 | @register(outgoing=True, pattern="^.readme$") 72 | async def reedme(event): 73 | await event.edit( 74 | "Here's something for you to read:\n" 75 | "\n[One4uBot's README.md file](https://github.com/MoveAngel/One4uBot/blob/sql-extended/README.md)" 76 | "\n[Setup Guide - Basic](https://telegra.ph/How-to-host-a-Telegram-Userbot-07-01-2)" 77 | "\n[Setup Guide - Google Drive](https://telegra.ph/How-To-Setup-Google-Drive-04-03)" 78 | "\n[Setup Guide - LastFM Module](https://telegra.ph/How-to-set-up-LastFM-module-for-Paperplane-userbot-11-02)" 79 | "\n[Setup Guide - From MiHub with Pict](https://www.mihub.my.id/2020/05/jadiuserbot.html)" 80 | "\n[Setup Guide - In Indonesian Language](https://telegra.ph/UserIndoBot-05-21-3)" 81 | "\n[Instant Setup - Generate String Session](https://repl.it/@MoveAngel/UserbotSession?lite=1&outputonly=1)" 82 | "\n*For Instant Setup, click the green button called 'run' before use" 83 | ) 84 | 85 | 86 | # Copyright (c) Gegham Zakaryan | 2019 87 | @register(outgoing=True, pattern="^.repeat (.*)") 88 | async def repeat(rep): 89 | cnt, txt = rep.pattern_match.group(1).split(" ", 1) 90 | replyCount = int(cnt) 91 | toBeRepeated = txt 92 | 93 | replyText = toBeRepeated + "\n" 94 | 95 | for i in range(0, replyCount - 1): 96 | replyText += toBeRepeated + "\n" 97 | 98 | await rep.edit(replyText) 99 | 100 | 101 | @register(outgoing=True, pattern="^.repo$") 102 | async def repo_is_here(wannasee): 103 | """ For .repo command, just returns the repo URL. """ 104 | await wannasee.edit( 105 | "[Click here](https://github.com/MoveAngel/One4uBot) to open One4uBot's GitHub page." 106 | ) 107 | 108 | 109 | @register(outgoing=True, pattern="^.raw$") 110 | async def raw(rawtext): 111 | the_real_message = None 112 | reply_to_id = None 113 | if rawtext.reply_to_msg_id: 114 | previous_message = await rawtext.get_reply_message() 115 | the_real_message = previous_message.stringify() 116 | reply_to_id = rawtext.reply_to_msg_id 117 | else: 118 | the_real_message = rawtext.stringify() 119 | reply_to_id = rawtext.message.id 120 | with io.BytesIO(str.encode(the_real_message)) as out_file: 121 | out_file.name = "raw_message_data.txt" 122 | await rawtext.edit("`Check the userbot log for the decoded message data !!`") 123 | await rawtext.client.send_file( 124 | BOTLOG_CHATID, 125 | out_file, 126 | force_document=True, 127 | allow_cache=False, 128 | reply_to=reply_to_id, 129 | caption="`Here's the decoded message data !!`", 130 | ) 131 | 132 | 133 | CMD_HELP.update( 134 | { 135 | "random": ".random ... \ 136 | \nUsage: Get a random item from the list of items." 137 | } 138 | ) 139 | 140 | CMD_HELP.update( 141 | { 142 | "sleep": ".sleep \ 143 | \nUsage: Userbots get tired too. Let yours snooze for a few seconds." 144 | } 145 | ) 146 | 147 | CMD_HELP.update( 148 | { 149 | "shutdown": ".shutdown\ 150 | \nUsage: Sometimes you need to shut down your bot. Sometimes you just hope to\ 151 | hear Windows XP shutdown sound... but you don't." 152 | } 153 | ) 154 | 155 | CMD_HELP.update( 156 | { 157 | "repo": ".repo\ 158 | \nUsage: If you are curious what makes the userbot work, this is what you need." 159 | } 160 | ) 161 | 162 | CMD_HELP.update( 163 | { 164 | "readme": ".readme\ 165 | \nUsage: Provide links to setup the userbot and it's modules." 166 | } 167 | ) 168 | 169 | CMD_HELP.update( 170 | { 171 | "repeat": ".repeat \ 172 | \nUsage: Repeats the text for a number of times. Don't confuse this with spam tho." 173 | } 174 | ) 175 | 176 | CMD_HELP.update( 177 | { 178 | "restart": ".restart\ 179 | \nUsage: Restarts the bot !!" 180 | } 181 | ) 182 | 183 | CMD_HELP.update( 184 | { 185 | "raw": ".raw\ 186 | \nUsage: Get detailed JSON-like formatted data about replied message." 187 | } 188 | ) 189 | -------------------------------------------------------------------------------- /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 | from telethon import events 8 | from telethon.errors.rpcerrorlist import YouBlockedUserError 9 | 10 | from userbot import CMD_HELP, bot 11 | from userbot.events import register 12 | 13 | 14 | @register(outgoing=True, pattern="^.nhentai(?: |$)(.*)") 15 | async def _(hentai): 16 | if hentai.fwd_from: 17 | return 18 | link = hentai.pattern_match.group(1) 19 | if not link: 20 | return await hentai.edit("`I can't search nothing`") 21 | chat = "@nHentaiBot" 22 | await hentai.edit("```Processing```") 23 | async with bot.conversation(chat) as conv: 24 | try: 25 | response = conv.wait_event( 26 | events.NewMessage(incoming=True, from_users=424466890) 27 | ) 28 | msg = await bot.send_message(chat, link) 29 | response = await response 30 | """ - don't spam notif - """ 31 | await bot.send_read_acknowledge(conv.chat_id) 32 | except YouBlockedUserError: 33 | await hentai.reply("```Please unblock @nHentaiBot and try again```") 34 | return 35 | if response.text.startswith("**Sorry I couldn't get manga from**"): 36 | await hentai.edit("```I think this is not the right link```") 37 | else: 38 | await hentai.delete() 39 | await bot.send_message(hentai.chat_id, response.message) 40 | await bot.send_read_acknowledge(hentai.chat_id) 41 | """ - cleanup chat after completed - """ 42 | await hentai.client.delete_messages(conv.chat_id, [msg.id, response.id]) 43 | 44 | 45 | CMD_HELP.update( 46 | { 47 | "nhentai": ".nhentai \ 48 | \nUsage: view nhentai in telegra.ph\n" 49 | } 50 | ) 51 | -------------------------------------------------------------------------------- /userbot/modules/notes.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 module containing commands for keeping notes. """ 7 | 8 | from asyncio import sleep 9 | 10 | from userbot import BOTLOG, BOTLOG_CHATID, CMD_HELP 11 | from userbot.events import register 12 | 13 | 14 | @register(outgoing=True, pattern="^.notes$") 15 | async def notes_active(svd): 16 | """ For .notes command, list all of the notes saved in a chat. """ 17 | try: 18 | from userbot.modules.sql_helper.notes_sql import get_notes 19 | except AttributeError: 20 | await svd.edit("`Running on Non-SQL mode!`") 21 | return 22 | message = "`There are no saved notes in this chat`" 23 | notes = get_notes(svd.chat_id) 24 | for note in notes: 25 | if message == "`There are no saved notes in this chat`": 26 | message = "Notes saved in this chat:\n" 27 | message += "`#{}`\n".format(note.keyword) 28 | else: 29 | message += "`#{}`\n".format(note.keyword) 30 | await svd.edit(message) 31 | 32 | 33 | @register(outgoing=True, pattern=r"^.clear (\w*)") 34 | async def remove_notes(clr): 35 | """ For .clear command, clear note with the given name.""" 36 | try: 37 | from userbot.modules.sql_helper.notes_sql import rm_note 38 | except AttributeError: 39 | await clr.edit("`Running on Non-SQL mode!`") 40 | return 41 | notename = clr.pattern_match.group(1) 42 | if rm_note(clr.chat_id, notename) is False: 43 | return await clr.edit("`Couldn't find note:` **{}**".format(notename)) 44 | else: 45 | return await clr.edit("`Successfully deleted note:` **{}**".format(notename)) 46 | 47 | 48 | @register(outgoing=True, pattern=r"^.save (\w*)") 49 | async def add_note(fltr): 50 | """ For .save command, saves notes in a chat. """ 51 | try: 52 | from userbot.modules.sql_helper.notes_sql import add_note 53 | except AttributeError: 54 | await fltr.edit("`Running on Non-SQL mode!`") 55 | return 56 | keyword = fltr.pattern_match.group(1) 57 | string = fltr.text.partition(keyword)[2] 58 | msg = await fltr.get_reply_message() 59 | msg_id = None 60 | if msg and msg.media and not string: 61 | if BOTLOG_CHATID: 62 | await fltr.client.send_message( 63 | BOTLOG_CHATID, 64 | f"#NOTE\ 65 | \nCHAT ID: {fltr.chat_id}\ 66 | \nKEYWORD: {keyword}\ 67 | \n\nThe following message is saved as the note's reply data for the chat, please do NOT delete it !!", 68 | ) 69 | msg_o = await fltr.client.forward_messages( 70 | entity=BOTLOG_CHATID, messages=msg, from_peer=fltr.chat_id, silent=True 71 | ) 72 | msg_id = msg_o.id 73 | else: 74 | await fltr.edit( 75 | "`Saving media as data for the note requires the BOTLOG_CHATID to be set.`" 76 | ) 77 | return 78 | elif fltr.reply_to_msg_id and not string: 79 | rep_msg = await fltr.get_reply_message() 80 | string = rep_msg.text 81 | success = "`Note {} successfully. Use` #{} `to get it`" 82 | if add_note(str(fltr.chat_id), keyword, string, msg_id) is False: 83 | return await fltr.edit(success.format("updated", keyword)) 84 | else: 85 | return await fltr.edit(success.format("added", keyword)) 86 | 87 | 88 | @register(pattern=r"#\w*", disable_edited=True, disable_errors=True, ignore_unsafe=True) 89 | async def incom_note(getnt): 90 | """ Notes logic. """ 91 | try: 92 | if not (await getnt.get_sender()).bot: 93 | try: 94 | from userbot.modules.sql_helper.notes_sql import get_note 95 | except AttributeError: 96 | return 97 | notename = getnt.text[1:] 98 | note = get_note(getnt.chat_id, notename) 99 | message_id_to_reply = getnt.message.reply_to_msg_id 100 | if not message_id_to_reply: 101 | message_id_to_reply = None 102 | if note and note.f_mesg_id: 103 | msg_o = await getnt.client.get_messages( 104 | entity=BOTLOG_CHATID, ids=int(note.f_mesg_id) 105 | ) 106 | await getnt.client.send_message( 107 | getnt.chat_id, 108 | msg_o.mesage, 109 | reply_to=message_id_to_reply, 110 | file=msg_o.media, 111 | ) 112 | elif note and note.reply: 113 | await getnt.client.send_message( 114 | getnt.chat_id, note.reply, reply_to=message_id_to_reply 115 | ) 116 | except AttributeError: 117 | pass 118 | 119 | 120 | @register(outgoing=True, pattern="^.rmbotnotes (.*)") 121 | async def kick_marie_notes(kick): 122 | """ For .rmbotnotes command, allows you to kick all \ 123 | Marie(or her clones) notes from a chat. """ 124 | bot_type = kick.pattern_match.group(1).lower() 125 | if bot_type not in ["marie", "rose"]: 126 | await kick.edit("`That bot is not yet supported!`") 127 | return 128 | await kick.edit("```Will be kicking away all Notes!```") 129 | await sleep(3) 130 | resp = await kick.get_reply_message() 131 | filters = resp.text.split("-")[1:] 132 | for i in filters: 133 | if bot_type == "marie": 134 | await kick.reply("/clear %s" % (i.strip())) 135 | if bot_type == "rose": 136 | i = i.replace("`", "") 137 | await kick.reply("/clear %s" % (i.strip())) 138 | await sleep(0.3) 139 | await kick.respond("```Successfully purged bots notes yaay!```\n Gimme cookies!") 140 | if BOTLOG: 141 | await kick.client.send_message( 142 | BOTLOG_CHATID, "I cleaned all Notes at " + str(kick.chat_id) 143 | ) 144 | 145 | 146 | CMD_HELP.update( 147 | { 148 | "notes": "\ 149 | #\ 150 | \nUsage: Gets the specified note.\ 151 | \n\n.save or reply to a message with .save \ 152 | \nUsage: Saves the replied message as a note with the notename. (Works with pics, docs, and stickers too!)\ 153 | \n\n.notes\ 154 | \nUsage: Gets all saved notes in a chat.\ 155 | \n\n.clear \ 156 | \nUsage: Deletes the specified note.\ 157 | \n\n.rmbotnotes \ 158 | \nUsage: Removes all notes of admin bots (Currently supported: Marie, Rose and their clones.) in the chat." 159 | } 160 | ) 161 | -------------------------------------------------------------------------------- /userbot/modules/ocr.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 os 8 | 9 | import requests 10 | 11 | from userbot import CMD_HELP, OCR_SPACE_API_KEY, TEMP_DOWNLOAD_DIRECTORY, bot 12 | from userbot.events import register 13 | 14 | 15 | async def ocr_space_file( 16 | filename, overlay=False, api_key=OCR_SPACE_API_KEY, language="eng" 17 | ): 18 | """OCR.space API request with local file. 19 | Python3.5 - not tested on 2.7 20 | :param filename: Your file path & name. 21 | :param overlay: Is OCR.space overlay required in your response. 22 | Defaults to False. 23 | :param api_key: OCR.space API key. 24 | Defaults to 'helloworld'. 25 | :param language: Language code to be used in OCR. 26 | List of available language codes can be found on https://ocr.space/OCRAPI 27 | Defaults to 'en'. 28 | :return: Result in JSON format. 29 | """ 30 | 31 | payload = { 32 | "isOverlayRequired": overlay, 33 | "apikey": api_key, 34 | "language": language, 35 | } 36 | with open(filename, "rb") as f: 37 | r = requests.post( 38 | "https://api.ocr.space/parse/image", 39 | files={filename: f}, 40 | data=payload, 41 | ) 42 | return r.json() 43 | 44 | 45 | @register(pattern=r".ocr (.*)", outgoing=True) 46 | async def ocr(event): 47 | if not OCR_SPACE_API_KEY: 48 | return await event.edit( 49 | "`Error: OCR.Space API key is missing! Add it to environment variables or config.env.`" 50 | ) 51 | await event.edit("`Reading...`") 52 | if not os.path.isdir(TEMP_DOWNLOAD_DIRECTORY): 53 | os.makedirs(TEMP_DOWNLOAD_DIRECTORY) 54 | lang_code = event.pattern_match.group(1) 55 | downloaded_file_name = await bot.download_media( 56 | await event.get_reply_message(), TEMP_DOWNLOAD_DIRECTORY 57 | ) 58 | test_file = await ocr_space_file(filename=downloaded_file_name, language=lang_code) 59 | try: 60 | ParsedText = test_file["ParsedResults"][0]["ParsedText"] 61 | except BaseException: 62 | await event.edit("`Couldn't read it.`\n`I guess I need new glasses.`") 63 | else: 64 | await event.edit(f"`Here's what I could read from it:`\n\n{ParsedText}") 65 | os.remove(downloaded_file_name) 66 | 67 | 68 | CMD_HELP.update( 69 | { 70 | "ocr": ".ocr \ 71 | \nUsage: Reply to an image or sticker to extract text from it. \ 72 | \n\nGet language codes from [here](https://ocr.space/OCRAPI#PostParameters)." 73 | } 74 | ) 75 | -------------------------------------------------------------------------------- /userbot/modules/pics.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 | # Copyright (C) 2020-2069 The authorship 7 | 8 | from asyncio import sleep 9 | from io import BytesIO 10 | 11 | from telethon import types 12 | from telethon.errors import PhotoInvalidDimensionsError 13 | from telethon.tl.functions.messages import SendMediaRequest 14 | 15 | from userbot import CMD_HELP 16 | from userbot.events import register 17 | 18 | 19 | @register(outgoing=True, pattern=r"^\.pic(?: |$)(.*)") 20 | async def on_file_to_photo(pics): 21 | await pics.edit("Converting Document image to Full Size Image\nPlease wait...") 22 | await sleep(1.5) 23 | await pics.delete() 24 | target = await pics.get_reply_message() 25 | try: 26 | image = target.media.document 27 | except AttributeError: 28 | return 29 | if not image.mime_type.startswith("image/"): 30 | return # This isn't an image 31 | if image.mime_type == "image/webp": 32 | return # Telegram doesn't let you directly send stickers as photos 33 | if image.size > 10 * 2560 * 1440: 34 | return # We'd get PhotoSaveFileInvalidError otherwise 35 | 36 | file = await pics.client.download_media(target, file=BytesIO()) 37 | file.seek(0) 38 | img = await pics.client.upload_file(file) 39 | img.name = "image.png" 40 | 41 | try: 42 | await pics.client( 43 | SendMediaRequest( 44 | peer=await pics.get_input_chat(), 45 | media=types.InputMediaUploadedPhoto(img), 46 | message=target.message, 47 | entities=target.entities, 48 | reply_to_msg_id=target.id, 49 | ) 50 | ) 51 | except PhotoInvalidDimensionsError: 52 | return 53 | 54 | 55 | CMD_HELP.update( 56 | { 57 | "pics": ".pic \ 58 | \nUsage: Convert any Document Image to Full Size Image." 59 | } 60 | ) 61 | -------------------------------------------------------------------------------- /userbot/modules/purge.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 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 = 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 = i + 1 63 | await message.delete() 64 | 65 | smsg = await delme.client.send_message( 66 | delme.chat_id, 67 | "`Purge complete!` Purged " + str(count) + " messages.", 68 | ) 69 | if BOTLOG: 70 | await delme.client.send_message( 71 | BOTLOG_CHATID, "Purge of " + str(count) + " messages done successfully." 72 | ) 73 | await sleep(2) 74 | i = 1 75 | await smsg.delete() 76 | 77 | 78 | @register(outgoing=True, pattern="^.del$") 79 | async def delete_it(delme): 80 | """ For .del command, delete the replied message. """ 81 | msg_src = await delme.get_reply_message() 82 | if delme.reply_to_msg_id: 83 | try: 84 | await msg_src.delete() 85 | await delme.delete() 86 | if BOTLOG: 87 | await delme.client.send_message( 88 | BOTLOG_CHATID, "Deletion of message was successful" 89 | ) 90 | except rpcbaseerrors.BadRequestError: 91 | if BOTLOG: 92 | await delme.client.send_message( 93 | BOTLOG_CHATID, "Well, I can't delete a message" 94 | ) 95 | 96 | 97 | @register(outgoing=True, pattern="^.edit") 98 | async def editer(edit): 99 | """ For .editme command, edit your last message. """ 100 | message = edit.text 101 | chat = await edit.get_input_chat() 102 | self_id = await edit.client.get_peer_id("me") 103 | string = str(message[6:]) 104 | i = 1 105 | async for message in edit.client.iter_messages(chat, self_id): 106 | if i == 2: 107 | await message.edit(string) 108 | await edit.delete() 109 | break 110 | i = i + 1 111 | if BOTLOG: 112 | await edit.client.send_message( 113 | BOTLOG_CHATID, "Edit query was executed successfully" 114 | ) 115 | 116 | 117 | @register(outgoing=True, pattern="^.sd") 118 | async def selfdestruct(destroy): 119 | """ For .sd command, make seflf-destructable messages. """ 120 | message = destroy.text 121 | counter = int(message[4:6]) 122 | text = str(destroy.text[6:]) 123 | await destroy.delete() 124 | smsg = await destroy.client.send_message(destroy.chat_id, text) 125 | await sleep(counter) 126 | await smsg.delete() 127 | if BOTLOG: 128 | await destroy.client.send_message(BOTLOG_CHATID, "sd query done successfully") 129 | 130 | 131 | CMD_HELP.update( 132 | { 133 | "purge": ".purge\ 134 | \nUsage: Purges all messages starting from the reply." 135 | } 136 | ) 137 | 138 | CMD_HELP.update( 139 | { 140 | "purgeme": ".purgeme \ 141 | \nUsage: Deletes x amount of your latest messages." 142 | } 143 | ) 144 | 145 | CMD_HELP.update( 146 | { 147 | "del": ".del\ 148 | \nUsage: Deletes the message you replied to." 149 | } 150 | ) 151 | 152 | CMD_HELP.update( 153 | { 154 | "edit": ".edit \ 155 | \nUsage: Replace your last message with ." 156 | } 157 | ) 158 | 159 | CMD_HELP.update( 160 | { 161 | "sd": ".sd \ 162 | \nUsage: Creates a message that selfdestructs in x seconds.\ 163 | \nKeep the seconds under 100 since it puts your bot to sleep." 164 | } 165 | ) 166 | -------------------------------------------------------------------------------- /userbot/modules/qrcode.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 | # 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 asyncio 11 | import os 12 | 13 | import barcode 14 | import qrcode 15 | from barcode.writer import ImageWriter 16 | from bs4 import BeautifulSoup 17 | 18 | from userbot import CMD_HELP, LOGS 19 | from userbot.events import register 20 | 21 | 22 | @register(pattern=r"^.decode$", outgoing=True) 23 | async def parseqr(qr_e): 24 | """ For .decode command, get QR Code/BarCode content from the replied photo. """ 25 | downloaded_file_name = await qr_e.client.download_media( 26 | await qr_e.get_reply_message() 27 | ) 28 | # parse the Official ZXing webpage to decode the QRCode 29 | command_to_exec = [ 30 | "curl", 31 | "-X", 32 | "POST", 33 | "-F", 34 | "f=@" + downloaded_file_name + "", 35 | "https://zxing.org/w/decode", 36 | ] 37 | process = await asyncio.create_subprocess_exec( 38 | *command_to_exec, 39 | # stdout must a pipe to be accessible as process.stdout 40 | stdout=asyncio.subprocess.PIPE, 41 | stderr=asyncio.subprocess.PIPE, 42 | ) 43 | # Wait for the subprocess to finish 44 | stdout, stderr = await process.communicate() 45 | e_response = stderr.decode().strip() 46 | t_response = stdout.decode().strip() 47 | os.remove(downloaded_file_name) 48 | if not t_response: 49 | LOGS.info(e_response) 50 | LOGS.info(t_response) 51 | return await qr_e.edit("Failed to decode.") 52 | soup = BeautifulSoup(t_response, "html.parser") 53 | qr_contents = soup.find_all("pre")[0].text 54 | await qr_e.edit(qr_contents) 55 | 56 | 57 | @register(pattern=r".barcode(?: |$)([\s\S]*)", outgoing=True) 58 | async def bq(event): 59 | """ For .barcode command, genrate a barcode containing the given content. """ 60 | await event.edit("`Processing..`") 61 | input_str = event.pattern_match.group(1) 62 | message = "SYNTAX: `.barcode `" 63 | reply_msg_id = event.message.id 64 | if input_str: 65 | message = input_str 66 | elif event.reply_to_msg_id: 67 | previous_message = await event.get_reply_message() 68 | reply_msg_id = previous_message.id 69 | if previous_message.media: 70 | downloaded_file_name = await event.client.download_media(previous_message) 71 | m_list = None 72 | with open(downloaded_file_name, "rb") as fd: 73 | m_list = fd.readlines() 74 | message = "" 75 | for m in m_list: 76 | message += m.decode("UTF-8") + "\r\n" 77 | os.remove(downloaded_file_name) 78 | else: 79 | message = previous_message.message 80 | else: 81 | return event.edit("SYNTAX: `.barcode `") 82 | 83 | bar_code_type = "code128" 84 | try: 85 | bar_code_mode_f = barcode.get(bar_code_type, message, writer=ImageWriter()) 86 | filename = bar_code_mode_f.save(bar_code_type) 87 | await event.client.send_file(event.chat_id, filename, reply_to=reply_msg_id) 88 | os.remove(filename) 89 | except Exception as e: 90 | return await event.edit(str(e)) 91 | await event.delete() 92 | 93 | 94 | @register(pattern=r".makeqr(?: |$)([\s\S]*)", outgoing=True) 95 | async def make_qr(makeqr): 96 | """ For .makeqr command, make a QR Code containing the given content. """ 97 | input_str = makeqr.pattern_match.group(1) 98 | message = "SYNTAX: `.makeqr `" 99 | reply_msg_id = None 100 | if input_str: 101 | message = input_str 102 | elif makeqr.reply_to_msg_id: 103 | previous_message = await makeqr.get_reply_message() 104 | reply_msg_id = previous_message.id 105 | if previous_message.media: 106 | downloaded_file_name = await makeqr.client.download_media(previous_message) 107 | m_list = None 108 | with open(downloaded_file_name, "rb") as file: 109 | m_list = file.readlines() 110 | message = "" 111 | for media in m_list: 112 | message += media.decode("UTF-8") + "\r\n" 113 | os.remove(downloaded_file_name) 114 | else: 115 | message = previous_message.message 116 | 117 | qr = qrcode.QRCode( 118 | version=1, 119 | error_correction=qrcode.constants.ERROR_CORRECT_L, 120 | box_size=10, 121 | border=4, 122 | ) 123 | qr.add_data(message) 124 | qr.make(fit=True) 125 | img = qr.make_image(fill_color="black", back_color="white") 126 | img.save("img_file.webp", "PNG") 127 | await makeqr.client.send_file( 128 | makeqr.chat_id, "img_file.webp", reply_to=reply_msg_id 129 | ) 130 | os.remove("img_file.webp") 131 | await makeqr.delete() 132 | 133 | 134 | CMD_HELP.update( 135 | { 136 | "qr": ".makeqr \ 137 | \nUsage: Make a QR Code from the given content.\ 138 | \nExample: .makeqr www.google.com\ 139 | \nNote: use .decode to get decoded content." 140 | } 141 | ) 142 | 143 | CMD_HELP.update( 144 | { 145 | "barcode": ".barcode \ 146 | \nUsage: Make a BarCode from the given content.\ 147 | \nExample: .barcode www.google.com\ 148 | \nNote: use .decode to get decoded content." 149 | } 150 | ) 151 | -------------------------------------------------------------------------------- /userbot/modules/remove_bg.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 | # (c) Shrimadhav U K - UniBorg 8 | # Thanks to Prakasaka for porting. 9 | 10 | import io 11 | import os 12 | 13 | import requests 14 | from telethon.tl.types import MessageMediaPhoto 15 | 16 | from userbot import CMD_HELP, REM_BG_API_KEY, TEMP_DOWNLOAD_DIRECTORY 17 | from userbot.events import register 18 | 19 | 20 | @register(outgoing=True, pattern="^.rbg(?: |$)(.*)") 21 | async def kbg(remob): 22 | """ For .rbg command, Remove Image Background. """ 23 | if REM_BG_API_KEY is None: 24 | await remob.edit( 25 | "`Error: Remove.BG API key missing! Add it to environment vars or config.env.`" 26 | ) 27 | return 28 | input_str = remob.pattern_match.group(1) 29 | message_id = remob.message.id 30 | if remob.reply_to_msg_id: 31 | message_id = remob.reply_to_msg_id 32 | reply_message = await remob.get_reply_message() 33 | await remob.edit("`Processing..`") 34 | try: 35 | if isinstance( 36 | reply_message.media, MessageMediaPhoto 37 | ) or "image" in reply_message.media.document.mime_type.split("/"): 38 | downloaded_file_name = await remob.client.download_media( 39 | reply_message, TEMP_DOWNLOAD_DIRECTORY 40 | ) 41 | await remob.edit("`Removing background from this image..`") 42 | output_file_name = await ReTrieveFile(downloaded_file_name) 43 | os.remove(downloaded_file_name) 44 | else: 45 | await remob.edit("`How do I remove the background from this ?`") 46 | except Exception as e: 47 | await remob.edit(str(e)) 48 | return 49 | elif input_str: 50 | await remob.edit( 51 | f"`Removing background from online image hosted at`\n{input_str}" 52 | ) 53 | output_file_name = await ReTrieveURL(input_str) 54 | else: 55 | await remob.edit("`I need something to remove the background from.`") 56 | return 57 | contentType = output_file_name.headers.get("content-type") 58 | if "image" in contentType: 59 | with io.BytesIO(output_file_name.content) as remove_bg_image: 60 | remove_bg_image.name = "removed_bg.png" 61 | await remob.client.send_file( 62 | remob.chat_id, 63 | remove_bg_image, 64 | caption="Background removed using remove.bg", 65 | force_document=True, 66 | reply_to=message_id, 67 | ) 68 | await remob.delete() 69 | else: 70 | await remob.edit( 71 | "**Error (Invalid API key, I guess ?)**\n`{}`".format( 72 | output_file_name.content.decode("UTF-8") 73 | ) 74 | ) 75 | 76 | 77 | # this method will call the API, and return in the appropriate format 78 | # with the name provided. 79 | async def ReTrieveFile(input_file_name): 80 | headers = { 81 | "X-API-Key": REM_BG_API_KEY, 82 | } 83 | files = { 84 | "image_file": (input_file_name, open(input_file_name, "rb")), 85 | } 86 | r = requests.post( 87 | "https://api.remove.bg/v1.0/removebg", 88 | headers=headers, 89 | files=files, 90 | allow_redirects=True, 91 | stream=True, 92 | ) 93 | return r 94 | 95 | 96 | async def ReTrieveURL(input_url): 97 | headers = { 98 | "X-API-Key": REM_BG_API_KEY, 99 | } 100 | data = {"image_url": input_url} 101 | r = requests.post( 102 | "https://api.remove.bg/v1.0/removebg", 103 | headers=headers, 104 | data=data, 105 | allow_redirects=True, 106 | stream=True, 107 | ) 108 | return r 109 | 110 | 111 | CMD_HELP.update( 112 | { 113 | "rbg": ".rbg or reply to any image (Warning: does not work on stickers.)\ 114 | \nUsage: Removes the background of images, using remove.bg API" 115 | } 116 | ) 117 | -------------------------------------------------------------------------------- /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.d (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 re 13 | import urllib 14 | 15 | import requests 16 | from bs4 import BeautifulSoup 17 | from PIL import Image 18 | 19 | from userbot import CMD_HELP, bot 20 | from userbot.events import register 21 | 22 | opener = urllib.request.build_opener() 23 | 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" 24 | opener.addheaders = [("User-agent", useragent)] 25 | 26 | 27 | @register(outgoing=True, pattern=r"^.reverse(?: |$)(\d*)") 28 | async def okgoogle(img): 29 | """ For .reverse command, Google search images and stickers. """ 30 | if os.path.isfile("okgoogle.png"): 31 | os.remove("okgoogle.png") 32 | 33 | message = await img.get_reply_message() 34 | if message and message.media: 35 | photo = io.BytesIO() 36 | await bot.download_media(message, photo) 37 | else: 38 | await img.edit("`Reply to photo or sticker nigger.`") 39 | return 40 | 41 | if photo: 42 | await img.edit("`Processing...`") 43 | try: 44 | image = Image.open(photo) 45 | except OSError: 46 | await img.edit("`Unsupported sexuality, most likely.`") 47 | return 48 | name = "okgoogle.png" 49 | image.save(name, "PNG") 50 | image.close() 51 | # https://stackoverflow.com/questions/23270175/google-reverse-image-search-using-post-request#28792943 52 | searchUrl = "https://www.google.com/searchbyimage/upload" 53 | multipart = {"encoded_image": (name, open(name, "rb")), "image_content": ""} 54 | response = requests.post(searchUrl, files=multipart, allow_redirects=False) 55 | fetchUrl = response.headers["Location"] 56 | 57 | if response != 400: 58 | await img.edit( 59 | "`Image successfully uploaded to Google. Maybe.`" 60 | "\n`Parsing source now. Maybe.`" 61 | ) 62 | else: 63 | await img.edit("`Google told me to fuck off.`") 64 | return 65 | 66 | os.remove(name) 67 | match = await ParseSauce(fetchUrl + "&preferences?hl=en&fg=1#languages") 68 | guess = match["best_guess"] 69 | imgspage = match["similar_images"] 70 | 71 | if guess and imgspage: 72 | await img.edit(f"[{guess}]({fetchUrl})\n\n`Looking for images...`") 73 | else: 74 | await img.edit("`Couldn't find anything for your uglyass.`") 75 | return 76 | 77 | if img.pattern_match.group(1): 78 | lim = img.pattern_match.group(1) 79 | else: 80 | lim = 3 81 | images = await scam(match, lim) 82 | yeet = [] 83 | for i in images: 84 | k = requests.get(i) 85 | yeet.append(k.content) 86 | try: 87 | await img.client.send_file( 88 | entity=await img.client.get_input_entity(img.chat_id), 89 | file=yeet, 90 | reply_to=img, 91 | ) 92 | except TypeError: 93 | pass 94 | await img.edit( 95 | f"[{guess}]({fetchUrl})\n\n[Visually similar images]({imgspage})" 96 | ) 97 | 98 | 99 | async def ParseSauce(googleurl): 100 | """Parse/Scrape the HTML code for the info we want.""" 101 | 102 | source = opener.open(googleurl).read() 103 | soup = BeautifulSoup(source, "html.parser") 104 | 105 | results = {"similar_images": "", "best_guess": ""} 106 | 107 | try: 108 | for similar_image in soup.findAll("input", {"class": "gLFyf"}): 109 | url = "https://www.google.com/search?tbm=isch&q=" + urllib.parse.quote_plus( 110 | similar_image.get("value") 111 | ) 112 | results["similar_images"] = url 113 | except BaseException: 114 | pass 115 | 116 | for best_guess in soup.findAll("div", attrs={"class": "r5a77d"}): 117 | results["best_guess"] = best_guess.get_text() 118 | 119 | return results 120 | 121 | 122 | async def scam(results, lim): 123 | 124 | single = opener.open(results["similar_images"]).read() 125 | decoded = single.decode("utf-8") 126 | 127 | imglinks = [] 128 | counter = 0 129 | 130 | pattern = r"^,\[\"(.*[.png|.jpg|.jpeg])\",[0-9]+,[0-9]+\]$" 131 | oboi = re.findall(pattern, decoded, re.I | re.M) 132 | 133 | for imglink in oboi: 134 | counter += 1 135 | if not counter >= int(lim): 136 | imglinks.append(imglink) 137 | else: 138 | break 139 | 140 | return imglinks 141 | 142 | 143 | CMD_HELP.update( 144 | { 145 | "reverse": ".reverse\ 146 | \nUsage: Reply to a pic/sticker to revers-search it on Google Images !!" 147 | } 148 | ) 149 | -------------------------------------------------------------------------------- /userbot/modules/screencapture.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 | # The entire source code is OSSRPL except 'screencapture' which is MPL 7 | # License: MPL and OSSRPL 8 | 9 | import io 10 | from asyncio import sleep 11 | from re import match 12 | 13 | from userbot import CMD_HELP 14 | from userbot.events import register 15 | from userbot.utils import chrome, options 16 | 17 | 18 | @register(pattern="^.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 | await url.delete() 70 | 71 | 72 | CMD_HELP.update( 73 | { 74 | "ss": ".ss \ 75 | \nUsage: Takes a screenshot of a website and sends the screenshot.\ 76 | \nExample of a valid URL : `https://www.google.com`" 77 | } 78 | ) 79 | -------------------------------------------------------------------------------- /userbot/modules/sed.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 | # 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 | 13 | from userbot import CMD_HELP 14 | from userbot.events import register 15 | 16 | DELIMITERS = ("/", ":", "|", "_") 17 | 18 | 19 | async def separate_sed(sed_string): 20 | """ Separate sed arguments. """ 21 | 22 | if len(sed_string) < 2: 23 | return 24 | 25 | if ( 26 | len(sed_string) >= 2 27 | and sed_string[2] in DELIMITERS 28 | and sed_string.count(sed_string[2]) >= 2 29 | ): 30 | delim = sed_string[2] 31 | start = counter = 3 32 | while counter < len(sed_string): 33 | if sed_string[counter] == "\\": 34 | counter += 1 35 | 36 | elif sed_string[counter] == delim: 37 | replace = sed_string[start:counter] 38 | counter += 1 39 | start = counter 40 | break 41 | 42 | counter += 1 43 | 44 | else: 45 | return None 46 | 47 | while counter < len(sed_string): 48 | if ( 49 | sed_string[counter] == "\\" 50 | and counter + 1 < len(sed_string) 51 | and sed_string[counter + 1] == delim 52 | ): 53 | sed_string = sed_string[:counter] + sed_string[counter + 1 :] 54 | 55 | elif sed_string[counter] == delim: 56 | replace_with = sed_string[start:counter] 57 | counter += 1 58 | break 59 | 60 | counter += 1 61 | else: 62 | return replace, sed_string[start:], "" 63 | 64 | flags = "" 65 | if counter < len(sed_string): 66 | flags = sed_string[counter:] 67 | return replace, replace_with, flags.lower() 68 | return None 69 | 70 | 71 | @register(outgoing=True, pattern="^.s") 72 | async def sed(command): 73 | """ For sed command, use sed on Telegram. """ 74 | sed_result = await separate_sed(command.text) 75 | textx = await command.get_reply_message() 76 | if sed_result: 77 | if textx: 78 | to_fix = textx.text 79 | else: 80 | await command.edit( 81 | "`Master, I don't have brains. Well you too don't I guess.`" 82 | ) 83 | return 84 | 85 | repl, repl_with, flags = sed_result 86 | 87 | if not repl: 88 | await command.edit( 89 | "`Master, I don't have brains. Well you too don't I guess.`" 90 | ) 91 | return 92 | 93 | try: 94 | check = re.match(repl, to_fix, flags=re.IGNORECASE) 95 | if check and check.group(0).lower() == to_fix.lower(): 96 | await command.edit("`Boi!, that's a reply. Don't use sed`") 97 | return 98 | 99 | if "i" in flags and "g" in flags: 100 | text = re.sub(repl, repl_with, to_fix, flags=re.I).strip() 101 | elif "i" in flags: 102 | text = re.sub(repl, repl_with, to_fix, count=1, flags=re.I).strip() 103 | elif "g" in flags: 104 | text = re.sub(repl, repl_with, to_fix).strip() 105 | else: 106 | text = re.sub(repl, repl_with, to_fix, count=1).strip() 107 | except sre_err: 108 | await command.edit("B O I! [Learn Regex](https://regexone.com)") 109 | return 110 | if text: 111 | await command.edit(f"Did you mean? \n\n{text}") 112 | 113 | 114 | CMD_HELP.update( 115 | { 116 | "sed": ".s\ 117 | \nUsage: Replaces a word or words using sed.\ 118 | \nDelimiters: `/, :, |, _`" 119 | } 120 | ) 121 | -------------------------------------------------------------------------------- /userbot/modules/snips.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 module containing commands for keeping global notes. """ 7 | 8 | from userbot import BOTLOG_CHATID, CMD_HELP 9 | from userbot.events import register 10 | 11 | 12 | @register(outgoing=True, pattern=r"\$\w*", ignore_unsafe=True, disable_errors=True) 13 | async def on_snip(event): 14 | """ Snips logic. """ 15 | try: 16 | from userbot.modules.sql_helper.snips_sql import get_snip 17 | except AttributeError: 18 | return 19 | name = event.text[1:] 20 | snip = get_snip(name) 21 | message_id_to_reply = event.message.reply_to_msg_id 22 | if not message_id_to_reply: 23 | message_id_to_reply = None 24 | if snip and snip.f_mesg_id: 25 | msg_o = await event.client.get_messages( 26 | entity=BOTLOG_CHATID, ids=int(snip.f_mesg_id) 27 | ) 28 | await event.client.send_message( 29 | event.chat_id, msg_o.message, reply_to=message_id_to_reply, file=msg_o.media 30 | ) 31 | elif snip and snip.reply: 32 | await event.client.send_message( 33 | event.chat_id, snip.reply, reply_to=message_id_to_reply 34 | ) 35 | 36 | 37 | @register(outgoing=True, pattern=r"^.snip (\w*)") 38 | async def on_snip_save(event): 39 | """ For .snip command, saves snips for future use. """ 40 | try: 41 | from userbot.modules.sql_helper.snips_sql import add_snip 42 | except AtrributeError: 43 | await event.edit("`Running on Non-SQL mode!`") 44 | return 45 | keyword = event.pattern_match.group(1) 46 | string = event.text.partition(keyword)[2] 47 | msg = await event.get_reply_message() 48 | msg_id = None 49 | if msg and msg.media and not string: 50 | if BOTLOG_CHATID: 51 | await event.client.send_message( 52 | BOTLOG_CHATID, 53 | f"#SNIP\ 54 | \nKEYWORD: {keyword}\ 55 | \n\nThe following message is saved as the data for the snip, please do NOT delete it !!", 56 | ) 57 | msg_o = await event.client.forward_messages( 58 | entity=BOTLOG_CHATID, messages=msg, from_peer=event.chat_id, silent=True 59 | ) 60 | msg_id = msg_o.id 61 | else: 62 | await event.edit( 63 | "`Saving snips with media requires the BOTLOG_CHATID to be set.`" 64 | ) 65 | return 66 | elif event.reply_to_msg_id and not string: 67 | rep_msg = await event.get_reply_message() 68 | string = rep_msg.text 69 | success = "`Snip {} successfully. Use` **${}** `anywhere to get it`" 70 | if add_snip(keyword, string, msg_id) is False: 71 | await event.edit(success.format("updated", keyword)) 72 | else: 73 | await event.edit(success.format("saved", keyword)) 74 | 75 | 76 | @register(outgoing=True, pattern="^.snips$") 77 | async def on_snip_list(event): 78 | """ For .snips command, lists snips saved by you. """ 79 | try: 80 | from userbot.modules.sql_helper.snips_sql import get_snips 81 | except AttributeError: 82 | await event.edit("`Running on Non-SQL mode!`") 83 | return 84 | 85 | message = "`No snips available right now.`" 86 | all_snips = get_snips() 87 | for a_snip in all_snips: 88 | if message == "`No snips available right now.`": 89 | message = "Available snips:\n" 90 | message += f"`${a_snip.snip}`\n" 91 | else: 92 | message += f"`${a_snip.snip}`\n" 93 | 94 | await event.edit(message) 95 | 96 | 97 | @register(outgoing=True, pattern=r"^.remsnip (\w*)") 98 | async def on_snip_delete(event): 99 | """ For .remsnip command, deletes a snip. """ 100 | try: 101 | from userbot.modules.sql_helper.snips_sql import remove_snip 102 | except AttributeError: 103 | await event.edit("`Running on Non-SQL mode!`") 104 | return 105 | name = event.pattern_match.group(1) 106 | if remove_snip(name) is True: 107 | await event.edit(f"`Successfully deleted snip:` **{name}**") 108 | else: 109 | await event.edit(f"`Couldn't find snip:` **{name}**") 110 | 111 | 112 | CMD_HELP.update( 113 | { 114 | "snips": "\ 115 | $\ 116 | \nUsage: Gets the specified snip, anywhere.\ 117 | \n\n.snip or reply to a message with .snip \ 118 | \nUsage: Saves the message as a snip (global note) with the name. (Works with pics, docs, and stickers too!)\ 119 | \n\n.snips\ 120 | \nUsage: Gets all saved snips.\ 121 | \n\n.remsnip \ 122 | \nUsage: Deletes the specified snip.\ 123 | " 124 | } 125 | ) 126 | -------------------------------------------------------------------------------- /userbot/modules/spam.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 asyncio 8 | from asyncio import sleep 9 | 10 | from userbot import BOTLOG, BOTLOG_CHATID, CMD_HELP 11 | from userbot.events import register 12 | 13 | 14 | @register(outgoing=True, pattern="^.cspam (.*)") 15 | async def leter_spam(cspammer): 16 | cspam = str(cspammer.pattern_match.group(1)) 17 | message = cspam.replace(" ", "") 18 | await cspammer.delete() 19 | for letter in message: 20 | await cspammer.respond(letter) 21 | if BOTLOG: 22 | await cspammer.client.send_message( 23 | BOTLOG_CHATID, "#CSPAM\n" "TSpam was executed successfully" 24 | ) 25 | 26 | 27 | @register(outgoing=True, pattern="^.wspam (.*)") 28 | async def word_spam(wspammer): 29 | wspam = str(wspammer.pattern_match.group(1)) 30 | message = wspam.split() 31 | await wspammer.delete() 32 | for word in message: 33 | await wspammer.respond(word) 34 | if BOTLOG: 35 | await wspammer.client.send_message( 36 | BOTLOG_CHATID, "#WSPAM\n" "WSpam was executed successfully" 37 | ) 38 | 39 | 40 | @register(outgoing=True, pattern="^.spam (.*)") 41 | async def spammer(spamm): 42 | counter = int(spamm.pattern_match.group(1).split(" ", 1)[0]) 43 | spam_message = str(spamm.pattern_match.group(1).split(" ", 1)[1]) 44 | await spamm.delete() 45 | await asyncio.wait([spamm.respond(spam_message) for i in range(counter)]) 46 | if BOTLOG: 47 | await spamm.client.send_message( 48 | BOTLOG_CHATID, "#SPAM\n" "Spam was executed successfully" 49 | ) 50 | 51 | 52 | @register(outgoing=True, pattern="^.picspam") 53 | async def tiny_pic_spam(pspam): 54 | message = pspam.text 55 | text = message.split() 56 | counter = int(text[1]) 57 | link = str(text[2]) 58 | await pspam.delete() 59 | for _ in range(1, counter): 60 | await pspam.client.send_file(pspam.chat_id, link) 61 | if BOTLOG: 62 | await pspam.client.send_message( 63 | BOTLOG_CHATID, "#PICSPAM\n" "PicSpam was executed successfully" 64 | ) 65 | 66 | 67 | @register(outgoing=True, pattern="^.delayspam (.*)") 68 | async def dspammer(dspam): 69 | spamDelay = float(dspam.pattern_match.group(1).split(" ", 2)[0]) 70 | counter = int(dspam.pattern_match.group(1).split(" ", 2)[1]) 71 | spam_message = str(dspam.pattern_match.group(1).split(" ", 2)[2]) 72 | await dspam.delete() 73 | for _ in range(1, counter): 74 | await dspam.respond(spam_message) 75 | await sleep(spamDelay) 76 | if BOTLOG: 77 | await dspam.client.send_message( 78 | BOTLOG_CHATID, "#DelaySPAM\n" "DelaySpam was executed successfully" 79 | ) 80 | 81 | 82 | CMD_HELP.update( 83 | { 84 | "spam": ".cspam \ 85 | \nUsage: Spam the text letter by letter.\ 86 | \n\n.spam \ 87 | \nUsage: Floods text in the chat !!\ 88 | \n\n.wspam \ 89 | \nUsage: Spam the text word by word.\ 90 | \n\n.picspam \ 91 | \nUsage: As if text spam was not enough !!\ 92 | \n\n.delayspam \ 93 | \nUsage: .bigspam but with custom delay.\ 94 | \n\n\nNOTE : Spam at your own risk !!" 95 | } 96 | ) 97 | -------------------------------------------------------------------------------- /userbot/modules/sql_helper/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MoveAngel/One4uBot/e153f632feb419bbc93909198e809c513cd0e988/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 | SESSION = start() 17 | -------------------------------------------------------------------------------- /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, String, UnicodeText 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(isinstance(other, BlackListFilters) 23 | and self.chat_id == other.chat_id 24 | and self.trigger == other.trigger) 25 | 26 | 27 | BlackListFilters.__table__.create(checkfirst=True) 28 | 29 | BLACKLIST_FILTER_INSERTION_LOCK = threading.RLock() 30 | 31 | CHAT_BLACKLISTS = {} 32 | 33 | 34 | def add_to_blacklist(chat_id, trigger): 35 | with BLACKLIST_FILTER_INSERTION_LOCK: 36 | blacklist_filt = BlackListFilters(str(chat_id), trigger) 37 | 38 | SESSION.merge(blacklist_filt) # merge to avoid duplicate key issues 39 | SESSION.commit() 40 | CHAT_BLACKLISTS.setdefault(str(chat_id), set()).add(trigger) 41 | 42 | 43 | def rm_from_blacklist(chat_id, trigger): 44 | with BLACKLIST_FILTER_INSERTION_LOCK: 45 | blacklist_filt = SESSION.query( 46 | BlackListFilters).get((str(chat_id), trigger)) 47 | if blacklist_filt: 48 | if trigger in CHAT_BLACKLISTS.get( 49 | 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 SESSION.query(BlackListFilters.chat_id).filter( 74 | BlackListFilters.chat_id == str(chat_id)).count() 75 | finally: 76 | SESSION.close() 77 | 78 | 79 | def num_blacklist_filter_chats(): 80 | try: 81 | return SESSION.query( 82 | func.count( 83 | distinct( 84 | 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 | 41 | 42 | def del_flist_all(): 43 | SESSION.execute("""TRUNCATE TABLE fban""") 44 | SESSION.commit() 45 | -------------------------------------------------------------------------------- /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) and self.chat_id == other.chat_id 24 | and self.keyword == other.keyword) 25 | 26 | 27 | Filters.__table__.create(checkfirst=True) 28 | 29 | 30 | def get_filter(chat_id, keyword): 31 | try: 32 | return SESSION.query(Filters).get((str(chat_id), keyword)) 33 | finally: 34 | SESSION.close() 35 | 36 | 37 | def get_filters(chat_id): 38 | try: 39 | return SESSION.query(Filters).filter( 40 | Filters.chat_id == str(chat_id)).all() 41 | finally: 42 | SESSION.close() 43 | 44 | 45 | def add_filter(chat_id, keyword, reply, f_mesg_id): 46 | to_check = get_filter(chat_id, keyword) 47 | if not to_check: 48 | adder = Filters(str(chat_id), keyword, reply, f_mesg_id) 49 | SESSION.add(adder) 50 | SESSION.commit() 51 | return True 52 | else: 53 | rem = SESSION.query(Filters).get((str(chat_id), keyword)) 54 | SESSION.delete(rem) 55 | SESSION.commit() 56 | adder = Filters(str(chat_id), keyword, reply, f_mesg_id) 57 | SESSION.add(adder) 58 | SESSION.commit() 59 | return False 60 | 61 | 62 | def remove_filter(chat_id, keyword): 63 | to_check = get_filter(chat_id, keyword) 64 | if not to_check: 65 | return False 66 | else: 67 | rem = SESSION.query(Filters).get((str(chat_id), keyword)) 68 | SESSION.delete(rem) 69 | SESSION.commit() 70 | return True 71 | -------------------------------------------------------------------------------- /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 SESSION.query(Globals).filter( 25 | Globals.variable == str(variable)).first().value 26 | except BaseException: 27 | return None 28 | finally: 29 | SESSION.close() 30 | 31 | 32 | def addgvar(variable, value): 33 | if SESSION.query(Globals).filter( 34 | Globals.variable == str(variable)).one_or_none(): 35 | delgvar(variable) 36 | adder = Globals(str(variable), value) 37 | SESSION.add(adder) 38 | SESSION.commit() 39 | 40 | 41 | def delgvar(variable): 42 | rem = SESSION.query(Globals).filter(Globals.variable == str(variable))\ 43 | .delete(synchronize_session="fetch") 44 | if rem: 45 | SESSION.commit() 46 | -------------------------------------------------------------------------------- /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 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, Numeric, UnicodeText 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__( 13 | self, 14 | user_id, 15 | chat_id, 16 | session_id, 17 | session_expires 18 | ): 19 | self.user_id = user_id 20 | self.chat_id = chat_id 21 | self.session_id = session_id 22 | self.session_expires = session_expires 23 | 24 | 25 | LydiaAI.__table__.create(checkfirst=True) 26 | 27 | 28 | def get_s(user_id, chat_id): 29 | try: 30 | return SESSION.query(LydiaAI).get((user_id, chat_id)) 31 | except BaseException: 32 | return None 33 | finally: 34 | SESSION.close() 35 | 36 | 37 | def get_all_s(): 38 | try: 39 | return SESSION.query(LydiaAI).all() 40 | except BaseException: 41 | return None 42 | finally: 43 | SESSION.close() 44 | 45 | 46 | def add_s( 47 | user_id, 48 | chat_id, 49 | session_id, 50 | session_expires 51 | ): 52 | adder = SESSION.query(LydiaAI).get((user_id, chat_id)) 53 | if adder: 54 | adder.session_id = session_id 55 | adder.session_expires = session_expires 56 | else: 57 | adder = LydiaAI( 58 | user_id, 59 | chat_id, 60 | session_id, 61 | session_expires 62 | ) 63 | SESSION.add(adder) 64 | SESSION.commit() 65 | 66 | 67 | def remove_s( 68 | user_id, 69 | chat_id 70 | ): 71 | note = SESSION.query(LydiaAI).get((user_id, chat_id)) 72 | if note: 73 | SESSION.delete(note) 74 | SESSION.commit() 75 | -------------------------------------------------------------------------------- /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 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( 22 | PMPermit.chat_id == str(chat_id)).one() 23 | except BaseException: 24 | return None 25 | finally: 26 | SESSION.close() 27 | 28 | 29 | def approve(chat_id): 30 | adder = PMPermit(str(chat_id)) 31 | SESSION.add(adder) 32 | SESSION.commit() 33 | 34 | 35 | def dissprove(chat_id): 36 | rem = SESSION.query(PMPermit).get(str(chat_id)) 37 | if rem: 38 | SESSION.delete(rem) 39 | SESSION.commit() 40 | -------------------------------------------------------------------------------- /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, Numeric, UnicodeText 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( 36 | Welcome.chat_id == str(chat_id)).one() 37 | except BaseException: 38 | return None 39 | finally: 40 | SESSION.close() 41 | 42 | 43 | def add_welcome_setting(chat_id, previous_welcome, reply, f_mesg_id): 44 | to_check = get_welcome(chat_id) 45 | if not to_check: 46 | adder = Welcome(chat_id, previous_welcome, reply, f_mesg_id) 47 | SESSION.add(adder) 48 | SESSION.commit() 49 | return True 50 | else: 51 | rem = SESSION.query(Welcome).get(str(chat_id)) 52 | SESSION.delete(rem) 53 | SESSION.commit() 54 | adder = Welcome(chat_id, previous_welcome, reply, f_mesg_id) 55 | SESSION.commit() 56 | return False 57 | 58 | 59 | def rm_welcome_setting(chat_id): 60 | try: 61 | rem = SESSION.query(Welcome).get(str(chat_id)) 62 | if rem: 63 | SESSION.delete(rem) 64 | SESSION.commit() 65 | return True 66 | except BaseException: 67 | return False 68 | 69 | 70 | def update_previous_welcome(chat_id, previous_welcome): 71 | row = SESSION.query(Welcome).get(str(chat_id)) 72 | row.previous_welcome = previous_welcome 73 | SESSION.commit() 74 | -------------------------------------------------------------------------------- /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/telegraph.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 From UniBorg to UserBot by @afdulfauzan 7 | 8 | import os 9 | from datetime import datetime 10 | 11 | from PIL import Image 12 | from telegraph import Telegraph, exceptions, upload_file 13 | 14 | from userbot import CMD_HELP, TEMP_DOWNLOAD_DIRECTORY, bot 15 | from userbot.events import register 16 | 17 | telegraph = Telegraph() 18 | r = telegraph.create_account(short_name="telegraph") 19 | auth_url = r["auth_url"] 20 | 21 | 22 | @register(outgoing=True, pattern="^.tg (m|t)$") 23 | async def telegraphs(graph): 24 | """For .telegraph command, upload media & text to telegraph site.""" 25 | await graph.edit("`Processing...`") 26 | if not graph.text[0].isalpha() and graph.text[0] not in ("/", "#", "@", "!"): 27 | if graph.fwd_from: 28 | return 29 | if not os.path.isdir(TEMP_DOWNLOAD_DIRECTORY): 30 | os.makedirs(TEMP_DOWNLOAD_DIRECTORY) 31 | if graph.reply_to_msg_id: 32 | start = datetime.now() 33 | r_message = await graph.get_reply_message() 34 | input_str = graph.pattern_match.group(1) 35 | if input_str == "m": 36 | downloaded_file_name = await bot.download_media( 37 | r_message, TEMP_DOWNLOAD_DIRECTORY 38 | ) 39 | end = datetime.now() 40 | ms = (end - start).seconds 41 | await graph.edit( 42 | "Downloaded to {} in {} seconds.".format(downloaded_file_name, ms) 43 | ) 44 | try: 45 | if downloaded_file_name.endswith((".webp")): 46 | resize_image(downloaded_file_name) 47 | except AttributeError: 48 | return await graph.edit("`No media provided`") 49 | try: 50 | media_urls = upload_file(downloaded_file_name) 51 | except exceptions.TelegraphException as exc: 52 | await graph.edit("ERROR: " + str(exc)) 53 | os.remove(downloaded_file_name) 54 | else: 55 | os.remove(downloaded_file_name) 56 | await graph.edit( 57 | "Successfully Uploaded to [telegra.ph](https://telegra.ph{}).".format( 58 | media_urls[0] 59 | ), 60 | link_preview=True, 61 | ) 62 | elif input_str == "t": 63 | user_object = await bot.get_entity(r_message.from_id) 64 | title_of_page = user_object.first_name # + " " + user_object.last_name 65 | # apparently, all Users do not have last_name field 66 | page_content = r_message.message 67 | if r_message.media: 68 | if page_content != "": 69 | title_of_page = page_content 70 | downloaded_file_name = await bot.download_media( 71 | r_message, TEMP_DOWNLOAD_DIRECTORY 72 | ) 73 | m_list = None 74 | with open(downloaded_file_name, "rb") as fd: 75 | m_list = fd.readlines() 76 | for m in m_list: 77 | page_content += m.decode("UTF-8") + "\n" 78 | os.remove(downloaded_file_name) 79 | page_content = page_content.replace("\n", "
") 80 | response = telegraph.create_page( 81 | title_of_page, html_content=page_content 82 | ) 83 | await graph.edit( 84 | "Successfully uploaded to [telegra.ph](https://telegra.ph/{}).".format( 85 | response["path"] 86 | ), 87 | link_preview=True, 88 | ) 89 | else: 90 | await graph.edit("`Reply to a message to get a permanent telegra.ph link.`") 91 | 92 | 93 | def resize_image(image): 94 | im = Image.open(image) 95 | im.save(image, "PNG") 96 | 97 | 98 | CMD_HELP.update( 99 | { 100 | "telegraph": ".tg \ 101 | \nUsage: Upload t(text) or m(media) on Telegraph." 102 | } 103 | ) 104 | -------------------------------------------------------------------------------- /userbot/modules/time.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 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 | # 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 codecs 8 | import json 9 | import os 10 | 11 | import requests 12 | from bs4 import BeautifulSoup as bs 13 | 14 | from userbot import CMD_HELP, TEMP_DOWNLOAD_DIRECTORY 15 | from userbot.events import register 16 | 17 | 18 | @register(outgoing=True, pattern=r"^\.ts (.*)") 19 | async def gengkapak(e): 20 | await e.edit("`Please wait, fetching results...`") 21 | query = e.pattern_match.group(1) 22 | response = requests.get( 23 | f"https://sjprojectsapi.herokuapp.com/torrent/?query={query}" 24 | ) 25 | ts = json.loads(response.text) 26 | if not ts == response.json(): 27 | await e.edit("**Some error occured**\n`Try Again Later`") 28 | return 29 | listdata = "" 30 | run = 0 31 | while True: 32 | try: 33 | run += 1 34 | r1 = ts[run] 35 | list1 = "<-----{}----->\nName: {}\nSeeders: {}\nSize: {}\nAge: {}\n<--Magnet Below-->\n{}\n\n\n".format( 36 | run, r1["name"], r1["seeder"], r1["size"], r1["age"], r1["magnet"] 37 | ) 38 | listdata = listdata + list1 39 | except BaseException: 40 | break 41 | 42 | if not listdata: 43 | return await e.edit("`Error: No results found`") 44 | 45 | tsfileloc = f"{TEMP_DOWNLOAD_DIRECTORY}/{query}.txt" 46 | with open(tsfileloc, "w+", encoding="utf8") as out_file: 47 | out_file.write(str(listdata)) 48 | fd = codecs.open(tsfileloc, "r", encoding="utf-8") 49 | data = fd.read() 50 | key = ( 51 | requests.post("https://nekobin.com/api/documents", json={"content": data}) 52 | .json() 53 | .get("result") 54 | .get("key") 55 | ) 56 | url = f"https://nekobin.com/raw/{key}" 57 | caption = ( 58 | f"`Here the results for the query: {query}`\n\nPasted to: [Nekobin]({url})" 59 | ) 60 | os.remove(tsfileloc) 61 | await e.edit(caption, link_preview=False) 62 | 63 | 64 | def dogbin(magnets): 65 | counter = 0 66 | urls = [] 67 | while counter != len(magnets): 68 | message = magnets[counter] 69 | url = "https://del.dog/documents" 70 | r = requests.post(url, data=message.encode("UTF-8")).json() 71 | url = f"https://del.dog/raw/{r['key']}" 72 | urls.append(url) 73 | counter = counter + 1 74 | return urls 75 | 76 | 77 | @register(outgoing=True, pattern=r"^.tos(?: |$)(.*)") 78 | async def tor_search(event): 79 | if event.fwd_from: 80 | return 81 | headers = { 82 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36" 83 | } 84 | 85 | search_str = event.pattern_match.group(1) 86 | 87 | print(search_str) 88 | await event.edit("Searching for " + search_str + ".....") 89 | if " " in search_str: 90 | search_str = search_str.replace(" ", "+") 91 | print(search_str) 92 | res = requests.get( 93 | "https://www.torrentdownloads.me/search/?new=1&s_cat=0&search=" 94 | + search_str, 95 | headers, 96 | ) 97 | 98 | else: 99 | res = requests.get( 100 | "https://www.torrentdownloads.me/search/?search=" + search_str, headers 101 | ) 102 | 103 | source = bs(res.text, "lxml") 104 | urls = [] 105 | magnets = [] 106 | titles = [] 107 | counter = 0 108 | for div in source.find_all("div", {"class": "grey_bar3 back_none"}): 109 | # print("https://www.torrentdownloads.me"+a['href']) 110 | try: 111 | title = div.p.a["title"] 112 | title = title[20:] 113 | titles.append(title) 114 | urls.append("https://www.torrentdownloads.me" + div.p.a["href"]) 115 | except KeyError: 116 | pass 117 | except TypeError: 118 | pass 119 | except AttributeError: 120 | pass 121 | if counter == 11: 122 | break 123 | counter = counter + 1 124 | if not urls: 125 | await event.edit("Either the Keyword was restricted or not found..") 126 | return 127 | 128 | print("Found URLS...") 129 | for url in urls: 130 | res = requests.get(url, headers) 131 | # print("URl: "+url) 132 | source = bs(res.text, "lxml") 133 | for div in source.find_all("div", {"class": "grey_bar1 back_none"}): 134 | try: 135 | mg = div.p.a["href"] 136 | magnets.append(mg) 137 | except Exception: 138 | pass 139 | print("Found Magnets...") 140 | shorted_links = dogbin(magnets) 141 | print("Dogged Magnets to del.dog...") 142 | msg = "" 143 | try: 144 | search_str = search_str.replace("+", " ") 145 | except BaseException: 146 | pass 147 | msg = "**Torrent Search Query**\n`{}`".format(search_str) + "\n**Results**\n" 148 | counter = 0 149 | while counter != len(titles): 150 | msg = ( 151 | msg 152 | + "⁍ [{}]".format(titles[counter]) 153 | + "({})".format(shorted_links[counter]) 154 | + "\n\n" 155 | ) 156 | counter = counter + 1 157 | await event.edit(msg, link_preview=False) 158 | 159 | 160 | CMD_HELP.update( 161 | { 162 | "torrent": ".ts Search query.\ 163 | \nUsage: Search for torrent query and post to dogbin.\ 164 | \n\n.tos Search query.\ 165 | \nUsage: Search for torrent magnet from query." 166 | } 167 | ) 168 | -------------------------------------------------------------------------------- /userbot/modules/whois.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 | # The entire source code is OSSRPL except 'whois' which is MPL 7 | # License: MPL and OSSRPL 8 | """ Userbot module for getiing info about any user on Telegram(including you!). """ 9 | 10 | import os 11 | 12 | from telethon.tl.functions.photos import GetUserPhotosRequest 13 | from telethon.tl.functions.users import GetFullUserRequest 14 | from telethon.tl.types import MessageEntityMentionName 15 | from telethon.utils import get_input_location 16 | 17 | from userbot import CMD_HELP, TEMP_DOWNLOAD_DIRECTORY 18 | from userbot.events import register 19 | 20 | 21 | @register(pattern=".whois(?: |$)(.*)", outgoing=True) 22 | async def who(event): 23 | 24 | await event.edit( 25 | "`Sit tight while I steal some data from *Global Network Zone*...`" 26 | ) 27 | 28 | if not os.path.isdir(TEMP_DOWNLOAD_DIRECTORY): 29 | os.makedirs(TEMP_DOWNLOAD_DIRECTORY) 30 | 31 | replied_user = await get_user(event) 32 | if replied_user is None: 33 | await event.edit("`This is anonymous admin in this group.\nCan't fetch the info`") 34 | return 35 | 36 | try: 37 | photo, caption = await fetch_info(replied_user, event) 38 | except AttributeError: 39 | await event.edit("`Could not fetch info of that user.`") 40 | return 41 | 42 | message_id_to_reply = event.message.reply_to_msg_id 43 | 44 | if not message_id_to_reply: 45 | message_id_to_reply = None 46 | 47 | try: 48 | await event.client.send_file( 49 | event.chat_id, 50 | photo, 51 | caption=caption, 52 | link_preview=False, 53 | force_document=False, 54 | reply_to=message_id_to_reply, 55 | parse_mode="html", 56 | ) 57 | 58 | if not photo.startswith("http"): 59 | os.remove(photo) 60 | await event.delete() 61 | 62 | except TypeError: 63 | await event.edit(caption, parse_mode="html") 64 | 65 | 66 | async def get_user(event): 67 | """ Get the user from argument or replied message. """ 68 | if event.reply_to_msg_id and not event.pattern_match.group(1): 69 | previous_message = await event.get_reply_message() 70 | if previous_message.from_id is None: # Anonymous admin seems don't have id attr 71 | return None 72 | replied_user = await event.client( 73 | GetFullUserRequest(previous_message.from_id)) 74 | else: 75 | user = event.pattern_match.group(1) 76 | 77 | if user.isnumeric(): 78 | user = int(user) 79 | 80 | if not user: 81 | self_user = await event.client.get_me() 82 | user = self_user.id 83 | 84 | if event.message.entities is not None: 85 | probable_user_mention_entity = event.message.entities[0] 86 | 87 | if isinstance(probable_user_mention_entity, MessageEntityMentionName): 88 | user_id = probable_user_mention_entity.user_id 89 | replied_user = await event.client(GetFullUserRequest(user_id)) 90 | return replied_user 91 | try: 92 | user_object = await event.client.get_entity(user) 93 | replied_user = await event.client(GetFullUserRequest(user_object.id)) 94 | except (TypeError, ValueError) as err: 95 | await event.edit(str(err)) 96 | return None 97 | 98 | return replied_user 99 | 100 | 101 | async def fetch_info(replied_user, event): 102 | """ Get details from the User object. """ 103 | replied_user_profile_photos = await event.client( 104 | GetUserPhotosRequest( 105 | user_id=replied_user.user.id, offset=42, max_id=0, limit=80 106 | ) 107 | ) 108 | replied_user_profile_photos_count = ( 109 | "Person needs help with uploading profile picture." 110 | ) 111 | try: 112 | replied_user_profile_photos_count = replied_user_profile_photos.count 113 | except AttributeError: 114 | pass 115 | user_id = replied_user.user.id 116 | first_name = replied_user.user.first_name 117 | last_name = replied_user.user.last_name 118 | try: 119 | dc_id, location = get_input_location(replied_user.profile_photo) 120 | except Exception as e: 121 | dc_id = "Couldn't fetch DC ID!" 122 | str(e) 123 | common_chat = replied_user.common_chats_count 124 | username = replied_user.user.username 125 | user_bio = replied_user.about 126 | is_bot = replied_user.user.bot 127 | restricted = replied_user.user.restricted 128 | verified = replied_user.user.verified 129 | photo = await event.client.download_profile_photo( 130 | user_id, TEMP_DOWNLOAD_DIRECTORY + str(user_id) + ".jpg", download_big=True 131 | ) 132 | first_name = ( 133 | first_name.replace("\u2060", "") 134 | if first_name 135 | else ("This User has no First Name") 136 | ) 137 | last_name = ( 138 | last_name.replace("\u2060", "") if last_name else ("This User has no Last Name") 139 | ) 140 | username = "@{}".format(username) if username else ("This User has no Username") 141 | user_bio = "This User has no About" if not user_bio else user_bio 142 | 143 | caption = "USER INFO:\n\n" 144 | caption += f"First Name: {first_name}\n" 145 | caption += f"Last Name: {last_name}\n" 146 | caption += f"Username: {username}\n" 147 | caption += f"Data Centre ID: {dc_id}\n" 148 | caption += f"Number of Profile Pics: {replied_user_profile_photos_count}\n" 149 | caption += f"Is Bot: {is_bot}\n" 150 | caption += f"Is Restricted: {restricted}\n" 151 | caption += f"Is Verified by Telegram: {verified}\n" 152 | caption += f"ID: {user_id}\n\n" 153 | caption += f"Bio: \n{user_bio}\n\n" 154 | caption += f"Common Chats with this user: {common_chat}\n" 155 | caption += f"Permanent Link To Profile: " 156 | caption += f'{first_name}' 157 | 158 | return photo, caption 159 | 160 | 161 | CMD_HELP.update( 162 | { 163 | "whois": ".whois or reply to someones text with .whois\ 164 | \nUsage: Gets info of an user." 165 | } 166 | ) 167 | -------------------------------------------------------------------------------- /userbot/modules/www.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 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 | 14 | from userbot import CMD_HELP 15 | from userbot.events import register 16 | 17 | 18 | @register(outgoing=True, pattern="^.speed$") 19 | async def speedtst(spd): 20 | """ For .speed command, use SpeedTest to check server speeds. """ 21 | await spd.edit("`Running speed test . . .`") 22 | test = Speedtest() 23 | 24 | test.get_best_server() 25 | test.download() 26 | test.upload() 27 | test.results.share() 28 | result = test.results.dict() 29 | 30 | await spd.edit( 31 | "`" 32 | "Started at " 33 | f"{result['timestamp']} \n\n" 34 | "Download " 35 | f"{speed_convert(result['download'])} \n" 36 | "Upload " 37 | f"{speed_convert(result['upload'])} \n" 38 | "Ping " 39 | f"{result['ping']} \n" 40 | "ISP " 41 | f"{result['client']['isp']}" 42 | "`" 43 | ) 44 | 45 | 46 | def speed_convert(size): 47 | """ 48 | Hi human, you can't read bytes? 49 | """ 50 | power = 2 ** 10 51 | zero = 0 52 | units = {0: "", 1: "Kb/s", 2: "Mb/s", 3: "Gb/s", 4: "Tb/s"} 53 | while size > power: 54 | size /= power 55 | zero += 1 56 | return f"{round(size, 2)} {units[zero]}" 57 | 58 | 59 | @register(outgoing=True, pattern="^.dc$") 60 | async def neardc(event): 61 | """ For .dc command, get the nearest datacenter information. """ 62 | result = await event.client(functions.help.GetNearestDcRequest()) 63 | await event.edit( 64 | f"Country : `{result.country}`\n" 65 | f"Nearest Datacenter : `{result.nearest_dc}`\n" 66 | f"This Datacenter : `{result.this_dc}`" 67 | ) 68 | 69 | 70 | @register(outgoing=True, pattern="^.ping$") 71 | async def pingme(pong): 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 | "speed": ".speed\ 83 | \nUsage: Does a speedtest and shows the results." 84 | } 85 | ) 86 | CMD_HELP.update( 87 | { 88 | "dc": ".dc\ 89 | \nUsage: Finds the nearest datacenter from your server." 90 | } 91 | ) 92 | CMD_HELP.update( 93 | { 94 | "ping": ".ping\ 95 | \nUsage: Shows how long it takes to ping your bot." 96 | } 97 | ) 98 | -------------------------------------------------------------------------------- /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 to Userbot by yincen17 7 | 8 | import asyncio 9 | import os 10 | import time 11 | import zipfile 12 | from datetime import date 13 | 14 | from userbot import CMD_HELP, TEMP_DOWNLOAD_DIRECTORY, ZIP_DOWNLOAD_DIRECTORY, bot 15 | from userbot.events import register 16 | from userbot.utils import progress 17 | 18 | # ==================== 19 | today = date.today() 20 | # ==================== 21 | 22 | 23 | @register(outgoing=True, pattern=r"^\.compress(?: |$)(.*)") 24 | async def _(event): 25 | # Prevent Channel Bug to use update 26 | if event.is_channel and not event.is_group: 27 | await event.edit("`Compress Command isn't permitted on channels`") 28 | return 29 | if event.fwd_from: 30 | return 31 | if not event.is_reply: 32 | await event.edit("`Reply to a file to compress it.`") 33 | return 34 | mone = await event.edit("`Processing...`") 35 | if not os.path.isdir(TEMP_DOWNLOAD_DIRECTORY): 36 | os.makedirs(TEMP_DOWNLOAD_DIRECTORY) 37 | if event.reply_to_msg_id: 38 | reply_message = await event.get_reply_message() 39 | try: 40 | c_time = time.time() 41 | downloaded_file_name = await bot.download_media( 42 | reply_message, 43 | TEMP_DOWNLOAD_DIRECTORY, 44 | progress_callback=lambda d, t: asyncio.get_event_loop().create_task( 45 | progress(d, t, mone, c_time, "[DOWNLOADING]") 46 | ), 47 | ) 48 | directory_name = downloaded_file_name 49 | await event.edit( 50 | f"Downloaded to `{directory_name}`" "`\ncompressing file...`" 51 | ) 52 | except Exception as e: # pylint:disable=C0103,W0703 53 | await mone.edit(str(e)) 54 | zipfile.ZipFile(directory_name + ".zip", "w", zipfile.ZIP_DEFLATED).write( 55 | directory_name 56 | ) 57 | c_time = time.time() 58 | await bot.send_file( 59 | event.chat_id, 60 | directory_name + ".zip", 61 | force_document=True, 62 | allow_cache=False, 63 | reply_to=event.message.id, 64 | progress_callback=lambda d, t: asyncio.get_event_loop().create_task( 65 | progress(d, t, mone, c_time, "[UPLOADING]") 66 | ), 67 | ) 68 | await event.edit("`Done!!`") 69 | await asyncio.sleep(7) 70 | await event.delete() 71 | 72 | 73 | @register(outgoing=True, pattern=r"^\.addzip(?: |$)(.*)") 74 | async def addzip(add): 75 | """ Copyright (c) 2020 azrim @github""" 76 | # Prevent Channel Bug to use update 77 | if add.is_channel and not add.is_group: 78 | await add.edit("`Command isn't permitted on channels`") 79 | return 80 | if add.fwd_from: 81 | return 82 | if not add.is_reply: 83 | await add.edit("`Reply to a file to compress it.`") 84 | return 85 | mone = await add.edit("`Processing...`") 86 | if not os.path.isdir(ZIP_DOWNLOAD_DIRECTORY): 87 | os.makedirs(ZIP_DOWNLOAD_DIRECTORY) 88 | if add.reply_to_msg_id: 89 | reply_message = await add.get_reply_message() 90 | try: 91 | c_time = time.time() 92 | downloaded_file_name = await bot.download_media( 93 | reply_message, 94 | ZIP_DOWNLOAD_DIRECTORY, 95 | progress_callback=lambda d, t: asyncio.get_event_loop().create_task( 96 | progress(d, t, mone, c_time, "[DOWNLOADING]") 97 | ), 98 | ) 99 | success = str(downloaded_file_name).replace("./zips/", "") 100 | await add.edit(f"`{success} Successfully added to list`") 101 | except Exception as e: # pylint:disable=C0103,W0703 102 | await mone.edit(str(e)) 103 | return 104 | 105 | 106 | @register(outgoing=True, pattern=r"^\.upzip(?: |$)(.*)") 107 | async def upload_zip(up): 108 | if not os.path.isdir(ZIP_DOWNLOAD_DIRECTORY): 109 | await up.edit("`Files not found`") 110 | return 111 | mone = await up.edit("`Zipping File...`") 112 | input_str = up.pattern_match.group(1) 113 | curdate = today.strftime("%m%d%y") 114 | title = str(input_str) if input_str else "zipfile" + f"{curdate}" 115 | zipf = zipfile.ZipFile(title + ".zip", "w", zipfile.ZIP_DEFLATED) 116 | zipdir(ZIP_DOWNLOAD_DIRECTORY, zipf) 117 | zipf.close() 118 | c_time = time.time() 119 | await bot.send_file( 120 | up.chat_id, 121 | title + ".zip", 122 | force_document=True, 123 | allow_cache=False, 124 | reply_to=up.message.id, 125 | progress_callback=lambda d, t: asyncio.get_event_loop().create_task( 126 | progress(d, t, mone, c_time, "[UPLOADING]", input_str) 127 | ), 128 | ) 129 | os.rmdir(ZIP_DOWNLOAD_DIRECTORY) 130 | await up.delete() 131 | 132 | 133 | @register(outgoing=True, pattern=r"^\.rmzip(?: |$)(.*)") 134 | async def remove_dir(rm): 135 | if not os.path.isdir(ZIP_DOWNLOAD_DIRECTORY): 136 | await rm.edit("`Directory not found`") 137 | return 138 | os.rmdir(ZIP_DOWNLOAD_DIRECTORY) 139 | await rm.edit("`Zip list removed`") 140 | 141 | 142 | def zipdir(path, ziph): 143 | # ziph is zipfile handle 144 | for root, dirs, files in os.walk(path): 145 | for file in files: 146 | ziph.write(os.path.join(root, file)) 147 | os.remove(os.path.join(root, file)) 148 | 149 | 150 | CMD_HELP.update( 151 | { 152 | "zipfile": ".compress **[optional: ]**\ 153 | \nUsage: make files to zip.\ 154 | \n.addzip ****\ 155 | \nUsage: add files to zip list.\ 156 | \n.upzip **[optional: ]**\ 157 | \nUsage: upload zip list.\ 158 | \n.rmzip **[optional: ]**\ 159 | \nUsage: clear zip list." 160 | } 161 | ) 162 | -------------------------------------------------------------------------------- /userbot/utils/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 Adek Maulana 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 | from .chrome import chrome, options 8 | from .progress import progress 9 | from .google_images_download import googleimagesdownload 10 | 11 | from .tools import ( 12 | humanbytes, 13 | time_formatter, 14 | human_to_bytes, 15 | md5, 16 | check_media 17 | ) 18 | -------------------------------------------------------------------------------- /userbot/utils/chrome.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Adek Maulana 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 os 8 | 9 | from selenium import webdriver 10 | from selenium.webdriver.chrome.options import Options 11 | 12 | from userbot import TEMP_DOWNLOAD_DIRECTORY, GOOGLE_CHROME_BIN, CHROME_DRIVER 13 | 14 | 15 | async def chrome(chrome_options=None): 16 | if chrome_options is None: 17 | chrome_options = await options() 18 | if not os.path.isdir(TEMP_DOWNLOAD_DIRECTORY): 19 | os.mkdir(TEMP_DOWNLOAD_DIRECTORY) 20 | prefs = {'download.default_directory': TEMP_DOWNLOAD_DIRECTORY} 21 | chrome_options.add_experimental_option('prefs', prefs) 22 | driver = webdriver.Chrome(executable_path=CHROME_DRIVER, 23 | options=chrome_options) 24 | return driver 25 | 26 | 27 | async def options(): 28 | chrome_options = Options() 29 | chrome_options.binary_location = GOOGLE_CHROME_BIN 30 | chrome_options.add_argument("--headless") 31 | chrome_options.add_argument("--window-size=1920x1080") 32 | chrome_options.add_argument("--disable-dev-shm-usage") 33 | chrome_options.add_argument("--no-sandbox") 34 | chrome_options.add_argument("--disable-gpu") 35 | return chrome_options 36 | -------------------------------------------------------------------------------- /userbot/utils/exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Adek Maulana 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 | class CancelProcess(Exception): 8 | """ 9 | Cancel Process 10 | """ 11 | -------------------------------------------------------------------------------- /userbot/utils/progress.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Adek Maulana 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 time 8 | import math 9 | 10 | from .tools import humanbytes, time_formatter 11 | from .exceptions import CancelProcess 12 | 13 | 14 | async def progress( 15 | current, total, gdrive, start, prog_type, 16 | file_name=None, is_cancelled=False 17 | ): 18 | now = time.time() 19 | diff = now - start 20 | if is_cancelled is True: 21 | raise CancelProcess 22 | 23 | if round(diff % 10.00) == 0 or current == total: 24 | percentage = current * 100 / total 25 | speed = current / diff 26 | elapsed_time = round(diff) 27 | eta = round((total - current) / speed) 28 | if 'upload' in prog_type.lower(): 29 | status = 'Uploading' 30 | elif 'download' in prog_type.lower(): 31 | status = 'Downloading' 32 | else: 33 | status = 'Unknown' 34 | progress_str = "`{0}` | [{1}{2}] `{3}%`".format( 35 | status, 36 | ''.join(["■" for i in range( 37 | math.floor(percentage / 10))]), 38 | ''.join(["▨" for i in range( 39 | 10 - math.floor(percentage / 10))]), 40 | round(percentage, 2)) 41 | tmp = ( 42 | f"{progress_str}\n" 43 | f"`{humanbytes(current)} of {humanbytes(total)}" 44 | f" @ {humanbytes(speed)}`\n" 45 | f"`ETA` -> {time_formatter(eta)}\n" 46 | f"`Duration` -> {time_formatter(elapsed_time)}" 47 | ) 48 | await gdrive.edit(f"`{prog_type}`\n\n" 49 | f"`Status`\n{tmp}") 50 | -------------------------------------------------------------------------------- /userbot/utils/tools.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 Adek Maulana 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 re 8 | import hashlib 9 | 10 | from telethon.tl.types import DocumentAttributeFilename 11 | 12 | 13 | async def md5(fname: str) -> str: 14 | hash_md5 = hashlib.md5() 15 | with open(fname, "rb") as f: 16 | for chunk in iter(lambda: f.read(4096), b""): 17 | hash_md5.update(chunk) 18 | return hash_md5.hexdigest() 19 | 20 | 21 | def humanbytes(size: int) -> str: 22 | if size is None or isinstance(size, str): 23 | return "" 24 | 25 | power = 2**10 26 | raised_to_pow = 0 27 | dict_power_n = {0: "", 1: "Ki", 2: "Mi", 3: "Gi", 4: "Ti"} 28 | while size > power: 29 | size /= power 30 | raised_to_pow += 1 31 | return str(round(size, 2)) + " " + dict_power_n[raised_to_pow] + "B" 32 | 33 | 34 | def time_formatter(seconds: int) -> str: 35 | minutes, seconds = divmod(seconds, 60) 36 | hours, minutes = divmod(minutes, 60) 37 | days, hours = divmod(hours, 24) 38 | tmp = ( 39 | ((str(days) + " day(s), ") if days else "") + 40 | ((str(hours) + " hour(s), ") if hours else "") + 41 | ((str(minutes) + " minute(s), ") if minutes else "") + 42 | ((str(seconds) + " second(s), ") if seconds else "") 43 | ) 44 | return tmp[:-2] 45 | 46 | 47 | def human_to_bytes(size: str) -> int: 48 | units = { 49 | "M": 2**20, "MB": 2**20, 50 | "G": 2**30, "GB": 2**30, 51 | "T": 2**40, "TB": 2**40 52 | } 53 | 54 | size = size.upper() 55 | if not re.match(r' ', size): 56 | size = re.sub(r'([KMGT])', r' \1', size) 57 | number, unit = [string.strip() for string in size.split()] 58 | return int(float(number) * units[unit]) 59 | 60 | 61 | async def check_media(reply_message): 62 | if reply_message and reply_message.media: 63 | if reply_message.photo: 64 | data = reply_message.photo 65 | elif reply_message.document: 66 | if ( 67 | DocumentAttributeFilename(file_name="AnimatedSticker.tgs") 68 | in reply_message.media.document.attributes 69 | ): 70 | return False 71 | if ( 72 | reply_message.gif 73 | or reply_message.video 74 | or reply_message.audio 75 | or reply_message.voice 76 | ): 77 | return False 78 | data = reply_message.media.document 79 | else: 80 | return False 81 | else: 82 | return False 83 | 84 | if not data or data is None: 85 | return False 86 | else: 87 | return data 88 | -------------------------------------------------------------------------------- /windows_startup_script.py: -------------------------------------------------------------------------------- 1 | from telethon import TelegramClient 2 | API_KEY = "Type that here" 3 | API_HASH = "Type that here" 4 | # get it from my.telegram.org 5 | bot = TelegramClient('userbot', API_KEY, API_HASH) 6 | bot.start() 7 | 8 | # This script wont run your bot, it just generates a session. 9 | --------------------------------------------------------------------------------