├── .dockerignore ├── .env.example ├── .gitattributes ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── README.md ├── VERSION ├── config.py ├── core ├── __init__.py ├── commands │ ├── __init__.py │ ├── admin │ │ ├── __init__.py │ │ ├── badword.py │ │ ├── ban.py │ │ ├── check_permission.py │ │ ├── dashboard.py │ │ ├── delete_message.py │ │ ├── filters.py │ │ ├── greport.py │ │ ├── info_group.py │ │ ├── mute.py │ │ ├── pin.py │ │ ├── promote.py │ │ ├── say.py │ │ ├── set_custom_handler.py │ │ ├── set_lang.py │ │ ├── set_rules.py │ │ ├── set_welcome.py │ │ ├── settings.py │ │ ├── shield.py │ │ ├── top.py │ │ ├── unban.py │ │ ├── user_info.py │ │ └── warn.py │ ├── index.py │ ├── owner │ │ ├── __init__.py │ │ ├── add_antispam.py │ │ ├── add_community.py │ │ ├── add_owner.py │ │ ├── broadcast.py │ │ ├── exit.py │ │ ├── export_invite_link.py │ │ ├── list_community.py │ │ ├── server_info.py │ │ ├── superban.py │ │ ├── test.py │ │ └── whitelist.py │ └── public │ │ ├── __init__.py │ │ ├── eggs.py │ │ ├── help.py │ │ ├── io.py │ │ ├── kickme.py │ │ ├── report.py │ │ ├── rules.py │ │ ├── source.py │ │ ├── staff.py │ │ ├── start.py │ │ └── user_search.py ├── database │ ├── __init__.py │ ├── db_connect.py │ ├── migrations.py │ ├── redis_connect.py │ └── repository │ │ ├── __init__.py │ │ ├── community.py │ │ ├── dashboard.py │ │ ├── group.py │ │ ├── group_language.py │ │ ├── superban.py │ │ └── user.py ├── decorators │ ├── __init__.py │ ├── admin.py │ ├── bot.py │ ├── delete.py │ ├── owner.py │ ├── private.py │ └── public.py ├── handlers │ ├── __init__.py │ ├── check_status_chat.py │ ├── check_status_user.py │ ├── custom_handler.py │ ├── errors.py │ ├── filters_chat.py │ ├── flood_wait.py │ ├── handler_errors.py │ ├── handlers_index.py │ ├── logs.py │ └── welcome.py ├── jobs │ ├── __init__.py │ ├── night_mode.py │ ├── query_repeat.py │ ├── send_db_backup.py │ └── send_debug.py └── utilities │ ├── __init__.py │ ├── constants.py │ ├── functions.py │ ├── menu.py │ ├── message.py │ ├── monads.py │ ├── regex.py │ └── strings.py ├── docker-compose.yml ├── languages ├── EN.py ├── IT.py ├── __init__.py └── getLang.py ├── main.py ├── plugins ├── __init__.py ├── distrowatch.py ├── inspire.py ├── plugin_index.py ├── search.py ├── weather.py └── wikipedia.py ├── poetry.lock ├── pyproject.toml ├── requirements.txt └── runtime.txt /.dockerignore: -------------------------------------------------------------------------------- 1 | .git* 2 | .dockerignore 3 | .circleci 4 | .vscode 5 | Dockerfile 6 | env 7 | venv 8 | docker/ 9 | docker-compose.yml 10 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # BOT SETTINGS 2 | TOKEN = 'YOUR_TOKEN' 3 | # DATABASE SETTINGS 4 | MYSQL_HOST = 'localhost' 5 | MYSQL_PORT = 3306 6 | MYSQL_USER = 'root' 7 | MYSQL_PASSWORD = '' 8 | MYSQL_DBNAME = 'nebula' 9 | #REDIS SETTINGS 10 | REDIS_HOST = 'localhost' 11 | REDIS_PORT = 6379 12 | REDIS_PASSWORD = '' 13 | REDIS_DB = 0 14 | # TELEGRAM SETTINGS 15 | TG_DEFAULT_WELCOME = 'Welcome {} to the {} group' 16 | TG_DEFAULT_RULES = 'https://github.com/Squirrel-Network/GroupRules' 17 | TG_DEFAULT_LOG_CHANNEL = -100123456789 18 | TG_DEFAULT_STAFF_GROUP = -100123456789 19 | # PROJECT SETTINGS 20 | DEV_CHAT_ID = -100123456789 21 | OPENWEATHER_TOKEN = 'YOUR_TOKEN' -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.* linguist-language=python -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | .idea/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # celery beat schedule file 95 | celerybeat-schedule 96 | 97 | # SageMath parsed files 98 | *.sage.py 99 | 100 | # Environments 101 | .env 102 | .venv 103 | env/ 104 | venv/ 105 | ENV/ 106 | env.bak/ 107 | venv.bak/ 108 | 109 | # Spyder project settings 110 | .spyderproject 111 | .spyproject 112 | 113 | # Rope project settings 114 | .ropeproject 115 | 116 | # mkdocs documentation 117 | /site 118 | 119 | # mypy 120 | .mypy_cache/ 121 | .dmypy.json 122 | dmypy.json 123 | 124 | # Pyre type checker 125 | .pyre/ 126 | 127 | # app 128 | .vsls.json 129 | .vscode 130 | .vs -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at officialsquirrelnetwork@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | Please note we have a code of conduct, please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a 11 | build. 12 | 2. Update the README.md with details of changes to the interface, this includes new environment 13 | variables, exposed ports, useful file locations and container parameters. 14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this 15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). 16 | 4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you 17 | do not have permission to do that, you may request the second reviewer to merge it for you. 18 | 19 | ## Code of Conduct 20 | 21 | ### Our Pledge 22 | 23 | In the interest of fostering an open and welcoming environment, we as 24 | contributors and maintainers pledge to making participation in our project and 25 | our community a harassment-free experience for everyone, regardless of age, body 26 | size, disability, ethnicity, gender identity and expression, level of experience, 27 | nationality, personal appearance, race, religion, or sexual identity and 28 | orientation. 29 | 30 | ### Our Standards 31 | 32 | Examples of behavior that contributes to creating a positive environment 33 | include: 34 | 35 | * Using welcoming and inclusive language 36 | * Being respectful of differing viewpoints and experiences 37 | * Gracefully accepting constructive criticism 38 | * Focusing on what is best for the community 39 | * Showing empathy towards other community members 40 | 41 | Examples of unacceptable behavior by participants include: 42 | 43 | * The use of sexualized language or imagery and unwelcome sexual attention or 44 | advances 45 | * Trolling, insulting/derogatory comments, and personal or political attacks 46 | * Public or private harassment 47 | * Publishing others' private information, such as a physical or electronic 48 | address, without explicit permission 49 | * Other conduct which could reasonably be considered inappropriate in a 50 | professional setting 51 | 52 | ### Our Responsibilities 53 | 54 | Project maintainers are responsible for clarifying the standards of acceptable 55 | behavior and are expected to take appropriate and fair corrective action in 56 | response to any instances of unacceptable behavior. 57 | 58 | Project maintainers have the right and responsibility to remove, edit, or 59 | reject comments, commits, code, wiki edits, issues, and other contributions 60 | that are not aligned to this Code of Conduct, or to ban temporarily or 61 | permanently any contributor for other behaviors that they deem inappropriate, 62 | threatening, offensive, or harmful. 63 | 64 | ### Scope 65 | 66 | This Code of Conduct applies both within project spaces and in public spaces 67 | when an individual is representing the project or its community. Examples of 68 | representing a project or community include using an official project e-mail 69 | address, posting via an official social media account, or acting as an appointed 70 | representative at an online or offline event. Representation of a project may be 71 | further defined and clarified by project maintainers. 72 | 73 | ### Enforcement 74 | 75 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 76 | reported by contacting the project team at [INSERT EMAIL ADDRESS]. All 77 | complaints will be reviewed and investigated and will result in a response that 78 | is deemed necessary and appropriate to the circumstances. The project team is 79 | obligated to maintain confidentiality with regard to the reporter of an incident. 80 | Further details of specific enforcement policies may be posted separately. 81 | 82 | Project maintainers who do not follow or enforce the Code of Conduct in good 83 | faith may face temporary or permanent repercussions as determined by other 84 | members of the project's leadership. 85 | 86 | ### Attribution 87 | 88 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 89 | available at [http://contributor-covenant.org/version/1/4][version] 90 | 91 | [homepage]: http://contributor-covenant.org 92 | [version]: http://contributor-covenant.org/version/1/4/ -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # first stage 2 | FROM python:3.9 AS builder 3 | COPY requirements.txt . 4 | 5 | # install dependencies to the local user directory (eg. /root/.local) 6 | RUN pip install --user -r requirements.txt 7 | 8 | # second unnamed stage 9 | FROM python:3.9-slim 10 | WORKDIR /app 11 | 12 | # copy only the dependencies installation from the 1st stage image 13 | COPY --from=builder /root/.local /root/.local 14 | COPY . /app 15 | 16 | # update PATH environment variable 17 | ENV PATH=/root/.local:$PATH 18 | 19 | CMD [ "python", "./main.py" ] 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![forthebadge](https://forthebadge.com/images/badges/made-with-python.svg)](https://www.python.org/) [![forthebadge](https://forthebadge.com/images/badges/open-source.svg)](https://en.wikipedia.org/wiki/Open_source) 2 | 3 | [![Codacy Badge](https://app.codacy.com/project/badge/Grade/5c5d758521f6442f83c11af5f063cbfc)](https://www.codacy.com/gh/Squirrel-Network/nebula8/dashboard?utm_source=github.com&utm_medium=referral&utm_content=Squirrel-Network/nebula8&utm_campaign=Badge_Grade) [![Squirrel-Network](https://circleci.com/gh/Squirrel-Network/nebula.svg?style=shield)](https://app.circleci.com/pipelines/github/Squirrel-Network/nebula8) [![Group](https://img.shields.io/badge/Group-SquirrelNetwork-blue)](https://t.me/squirrelnetwork) 4 | # NEBULA BOT 5 | 6 | ❗❗️️❗️ The new Version compatible with the python-telegram-bot 20.X library is under development❗️❗️❗️ 7 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 8.6.2 -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | import os 6 | from dotenv import load_dotenv 7 | 8 | load_dotenv() 9 | 10 | class Config(object): 11 | ########################### 12 | ## DATABASE SETTINGS ## 13 | ########################## 14 | HOST = os.environ.get('MYSQL_HOST', 'localhost') 15 | PORT = int(os.environ.get('MYSQL_PORT', '3306')) 16 | USER = os.environ.get('MYSQL_USER', 'root') 17 | PASSWORD = os.environ.get('MYSQL_PASSWORD') 18 | DBNAME = os.environ.get('MYSQL_DBNAME') 19 | ########################## 20 | ## REDIS SETTINGS ## 21 | ########################## 22 | RD_HOST = os.environ.get('REDIS_HOST', 'localhost') 23 | RD_PORT = os.environ.get('REDIS_PORT', '6379') 24 | RD_PASSWORD = os.environ.get('REDIS_PASSWORD') 25 | RD_DB = os.environ.get('REDIS_DB', 0) 26 | ########################### 27 | ## TELEGRAM SETTINGS ## 28 | ########################## 29 | BOT_TOKEN = os.environ.get('TOKEN') 30 | DEFAULT_WELCOME = os.environ.get('TG_DEFAULT_WELCOME', 'Welcome {} to the {} group') 31 | DEFAULT_RULES = os.environ.get('TG_DEFAULT_RULES', 'https://github.com/Squirrel-Network/GroupRules') 32 | DEFAULT_LOG_CHANNEL = os.environ.get('TG_DEFAULT_LOG_CHANNEL') 33 | DEFAULT_STAFF_GROUP = os.environ.get('TG_DEFAULT_STAFF_GROUP') 34 | ########################## 35 | ## PROJECT SETTINGS ## 36 | ########################## 37 | OPENWEATHER_API = os.environ.get('OPENWEATHER_TOKEN') 38 | ENABLE_PLUGINS = True 39 | DEFAULT_LANGUAGE = "EN" 40 | VERSION = '8.6.2' 41 | VERSION_NAME = 'Hatterene' 42 | REPO = 'https://github.com/Squirrel-Network/nebula8' 43 | DEVELOPER_CHAT_ID = os.environ.get('DEV_CHAT_ID') 44 | DEBUG = False 45 | if BOT_TOKEN is None: 46 | print("The environment variable TOKEN was not set correctly!") 47 | quit(1) 48 | if RD_PASSWORD is None: 49 | print("The environment variable REDIS_PASSWORD was not set correctly!") 50 | quit(1) 51 | if DEFAULT_LOG_CHANNEL is None: 52 | print("The environment variable TG_DEFAULT_LOG_CHANNEL was not set correctly!") 53 | quit(1) 54 | if DEFAULT_STAFF_GROUP is None: 55 | print("The environment variable TG_DEFAULT_STAFF_GROUP was not set correctly!") 56 | quit(1) 57 | if OPENWEATHER_API is None: 58 | print("The environment variable OPENWEATHER_TOKEN was not set correctly! this will not allow the weather plugin to work") 59 | -------------------------------------------------------------------------------- /core/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | """Import Files""" 7 | __all__ = ["commands", 8 | "decorators", 9 | "handlers", 10 | "utilities" 11 | ] 12 | 13 | from core import * -------------------------------------------------------------------------------- /core/commands/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | """Import Files""" 7 | __all__ = ["admin", 8 | "owner", 9 | "public", 10 | "index" 11 | ] 12 | 13 | from core.commands import * -------------------------------------------------------------------------------- /core/commands/admin/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | """Import Files""" 7 | __all__ = ["badword","ban","check_permission","dashboard","delete_message","filters","greport","info_group","mute","pin","promote","say","set_custom_handler","set_lang","set_rules","set_welcome","settings","shield","top","unban","user_info","warn"] 8 | 9 | from core.commands.admin import * -------------------------------------------------------------------------------- /core/commands/admin/badword.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | from core import decorators 7 | from languages.getLang import languages 8 | from core.utilities.message import message 9 | from core.utilities.functions import chat_object 10 | from core.database.repository.group import GroupRepository 11 | 12 | @decorators.admin.user_admin 13 | @decorators.delete.init 14 | def init(update,context): 15 | chat = chat_object(update) 16 | msg = update.message.text[8:].strip() 17 | if msg != "": 18 | data = [(msg,chat.id)] 19 | GroupRepository().insert_badword(data) 20 | message(update,context,languages.badlist_add.format(msg)) 21 | else: 22 | message(update, context,languages.badlist_add_empty) 23 | 24 | @decorators.admin.user_admin 25 | @decorators.delete.init 26 | def badlist(update,context): 27 | chat = chat_object(update) 28 | languages(update,context) 29 | rows = GroupRepository().get_badwords_group(chat.id) 30 | if rows: 31 | string = "" 32 | for row in rows: 33 | string += "▪️ {}\n".format(row['word']) 34 | message(update,context,languages.badlist_text.format(chat.title,string)) 35 | else: 36 | message(update,context,languages.badlist_empty) 37 | -------------------------------------------------------------------------------- /core/commands/admin/ban.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | from core import decorators 7 | from core.handlers.logs import sys_loggers, telegram_loggers 8 | from core.utilities.functions import ( 9 | ban_user_reply, 10 | ban_user_by_username, 11 | ban_user_by_id, 12 | bot_object, 13 | delete_message_reply, 14 | reply_member_status_object, 15 | chat_object) 16 | from core.utilities.message import message 17 | from core.utilities.strings import Strings 18 | from core.utilities.monads import Try 19 | from telegram.utils.helpers import mention_html 20 | from core.database.repository.group import GroupRepository 21 | from languages.getLang import languages 22 | 23 | def ban_error(update, context, username = None, id = None): 24 | message( 25 | update, 26 | context, 27 | "Si è verificato un problema per il ban dell'utente %s" % (username if username is not None else id)) 28 | 29 | def ban_success(update, context, username = None, id = None): 30 | message(update,context,"Ho bannato %s" % (username if username is not None else id)) 31 | 32 | @decorators.admin.user_admin 33 | @decorators.delete.init 34 | def init(update, context): 35 | languages(update,context) 36 | chat = chat_object(update) 37 | row = GroupRepository().getById(chat.id) 38 | 39 | bot = bot_object(update,context) 40 | chat = update.effective_chat 41 | reply = update.message.reply_to_message 42 | if row['set_gh'] == 0: 43 | if reply is not None: 44 | user_status = reply_member_status_object(update,context) 45 | user = reply.from_user 46 | row = GroupRepository().getById(chat.id) 47 | if user.id == bot.id: 48 | text = languages.ban_self_ban 49 | 50 | message(update,context,text) 51 | elif user_status.status == 'administrator' or user_status.status == 'creator': 52 | message(update,context,languages.ban_error_ac) 53 | else: 54 | if row['ban_message']: 55 | parsed_message = row['ban_message'].replace('{first_name}', 56 | user.first_name).replace('{chat}', 57 | update.message.chat.title).replace('{username}', 58 | "@"+user.username if user.username else user.first_name).replace('{mention}',mention_html(user.id, user.first_name)).replace('{userid}',str(user.id)) 59 | ban_text = "{}".format(parsed_message) 60 | else: 61 | ban_text = languages.ban_message.format( 62 | user = reply.from_user.username or reply.from_user.first_name, 63 | userid = reply.from_user.id, 64 | chat = chat.title 65 | ) 66 | #Log Ban 67 | logs_text = Strings.BAN_LOG.format( 68 | username = reply.from_user.username or reply.from_user.first_name, 69 | id = reply.from_user.id, 70 | chat = chat.title 71 | ) 72 | 73 | delete_message_reply(update,context) 74 | ban_user_reply(update,context) 75 | message(update,context,ban_text) 76 | telegram_loggers(update,context,logs_text) 77 | 78 | formatter = "Ban eseguito da: {} nella chat {}".format( 79 | update.message.from_user.id, 80 | chat.title) 81 | 82 | sys_loggers("[BAN_LOGS]",formatter,False,True) 83 | else: 84 | ban_argument = update.message.text[5:] 85 | 86 | is_user_id = Try.of(lambda: int(ban_argument)).valueOf() is not None 87 | 88 | if ban_argument[0] == '@': 89 | username = ban_argument 90 | 91 | Try.of(lambda: ban_user_by_username(update, context, username)) \ 92 | .catch(lambda err: ban_error(update, context, username = username)) \ 93 | .map(lambda x : ban_success(update, context, username = username)) 94 | elif is_user_id: 95 | userid = ban_argument 96 | 97 | Try.of(lambda: ban_user_by_id(update, context, userid)) \ 98 | .catch(lambda err: ban_error(update, context, id = userid)) \ 99 | .map(lambda x : ban_success(update, context, id = userid)) 100 | else: 101 | message( 102 | update, 103 | context, 104 | languages.ban_syntax_error.format(ban_argument) 105 | ) 106 | return 107 | else: 108 | return 109 | 110 | @decorators.admin.user_admin 111 | @decorators.delete.init 112 | def set_ban_message(update, context): 113 | languages(update,context) 114 | record = GroupRepository.BAN_MESSAGE 115 | chat = update.effective_chat.id 116 | msg = update.message.text[7:] 117 | reply = update.message.reply_to_message 118 | if reply: 119 | ban_text = str(reply.text).lower() 120 | data = [(ban_text, chat)] 121 | GroupRepository().update_group_settings(record, data) 122 | message(update,context, languages.set_ban_message) 123 | else: 124 | if msg != "": 125 | data = [(msg, chat)] 126 | GroupRepository().update_group_settings(record, data) 127 | message(update, context, languages.set_ban_message) 128 | else: 129 | message(update, context, languages.ban_error_empty) -------------------------------------------------------------------------------- /core/commands/admin/check_permission.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core import decorators 6 | from core.utilities.functions import bot_object 7 | from core.utilities.message import message 8 | from languages.getLang import languages 9 | 10 | @decorators.admin.user_admin 11 | @decorators.public.init 12 | def init(update, context): 13 | bot = bot_object(update, context) 14 | chat_id = update.message.chat_id 15 | get_bot = bot.getChatMember(chat_id,bot.id) 16 | languages(update,context) 17 | 18 | perm_delete = get_bot.can_delete_messages 19 | perm_ban = get_bot.can_restrict_members 20 | perm_pin = get_bot.can_pin_messages 21 | perm_edit_msg = get_bot.can_be_edited 22 | perm_media = get_bot.can_send_media_messages 23 | perm_send_message = get_bot.can_send_messages 24 | if None in [perm_delete, perm_ban, perm_pin, perm_edit_msg, perm_media, perm_send_message]: 25 | message(update,context, languages.perm_error) 26 | else: 27 | message(update, context, languages.perm_ok) -------------------------------------------------------------------------------- /core/commands/admin/dashboard.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | import datetime 7 | from core.utilities.functions import member_status_object, chat_status_object 8 | from core.database.repository.dashboard import DashboardRepository 9 | from core.utilities.message import message 10 | 11 | def init(update,context): 12 | reply = update.message.reply_to_message 13 | if reply: 14 | message(update,context,"Questo comando al momento non può essere utilizzato in risposta ad un messaggio!") 15 | else: 16 | user_status = member_status_object(update,context) 17 | chat_status = chat_status_object(update, context) 18 | if user_status.status == 'creator' or user_status.status == 'administrator': 19 | user = user_status.user 20 | username = "@"+user.username 21 | save_date = datetime.datetime.utcnow().isoformat() 22 | row = DashboardRepository().getById(user.id) 23 | if row: 24 | if row['enable'] == 0: 25 | message(update,context,"Mi dispiace sei stato disabilitato a questa funzionalità, Contatta un amministratore su: https://t.me/nebulabot_support") 26 | else: 27 | get_group_dashboard = DashboardRepository().getUserAndGroup((chat_status.id,user.id)) 28 | if get_group_dashboard: 29 | data = [(username, user_status.status, save_date, user.id, chat_status.id)] 30 | DashboardRepository().update(data) 31 | message(update,context,"Ho aggiornato i tuoi dati sul database!") 32 | else: 33 | data_add = [(user.id,username,chat_status.id,1,user_status.status,save_date,save_date)] 34 | DashboardRepository().add(data_add) 35 | message(update,context,"Ho aggiornato i tuoi dati sul database! e ho inserito {} nella Dashboard\n\nEsegui il login su: https://nebula.squirrel-network.online".format(chat_status.title)) 36 | else: 37 | data = [(user.id,username,chat_status.id,1,user_status.status,save_date,save_date)] 38 | DashboardRepository().add(data) 39 | message(update,context,"{} hai eseguito la prima abilitazione alla dashboard di Nebula \n\nEsegui il login su: https://nebula.squirrel-network.online".format(username)) 40 | else: 41 | msg = "Non sei amministratore o proprietario del gruppo non puoi usare questo comando!" 42 | message(update,context,msg) -------------------------------------------------------------------------------- /core/commands/admin/delete_message.py: -------------------------------------------------------------------------------- 1 | from core import decorators 2 | from languages.getLang import languages 3 | from core.utilities.functions import delete_message_reply 4 | from core.utilities.message import message 5 | 6 | @decorators.admin.user_admin 7 | @decorators.bot.check_is_admin 8 | @decorators.bot.check_can_delete 9 | @decorators.delete.init 10 | def init(update,context): 11 | languages(update,context) 12 | reply = update.message.reply_to_message 13 | if reply is not None: 14 | delete_message_reply(update,context) 15 | else: 16 | message(update, context, languages.delete_error_msg) -------------------------------------------------------------------------------- /core/commands/admin/filters.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core import decorators 6 | from core.utilities.menu import build_menu 7 | from core.utilities.functions import update_db_settings 8 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup 9 | from core.database.repository.group import GroupRepository 10 | 11 | def keyboard_filters(update,context,editkeyboard = False): 12 | bot = context.bot 13 | chat = update.message.chat_id 14 | chat_title = update.message.chat.title 15 | group = GroupRepository().getById(chat) 16 | list_buttons = [] 17 | list_buttons.append(InlineKeyboardButton('❇️ Activate All', callback_data='ffseall')) 18 | list_buttons.append(InlineKeyboardButton('⛔️ Deactivate All', callback_data='ffdeall')) 19 | list_buttons.append(InlineKeyboardButton('Exe Filters %s' % ('✅' if group['exe_filter'] == 1 else '❌'), callback_data='ffexe_filters')) 20 | list_buttons.append(InlineKeyboardButton('GIF Filters %s' % ('✅' if group['gif_filter'] == 1 else '❌'), callback_data='ffgif_filters')) 21 | list_buttons.append(InlineKeyboardButton('Zip Filters %s' % ('✅' if group['zip_filter'] == 1 else '❌'), callback_data='ffzip_filters')) 22 | list_buttons.append(InlineKeyboardButton('TarGZ Filters %s' % ('✅' if group['targz_filter'] == 1 else '❌'), callback_data='fftargz_filters')) 23 | list_buttons.append(InlineKeyboardButton('JPG Filters %s' % ('✅' if group['jpg_filter'] == 1 else '❌'), callback_data='ffjpg_filters')) 24 | list_buttons.append(InlineKeyboardButton('Doc/x Filters %s' % ('✅' if group['docx_filter'] == 1 else '❌'), callback_data='ffdocx_filters')) 25 | list_buttons.append(InlineKeyboardButton('Apk Filters %s' % ('✅' if group['apk_filter'] == 1 else '❌'), callback_data='ffapk_filters')) 26 | list_buttons.append(InlineKeyboardButton("Close", callback_data='closeMenu')) 27 | menu = build_menu(list_buttons,2) 28 | if editkeyboard == False: 29 | keyboard_menu = bot.send_message(chat,"⚙️ Group Filters Settings\n\n📜 Group Name: {}\n🏷 ChatId: {}".format(chat_title,chat),reply_markup=InlineKeyboardMarkup(menu),parse_mode='HTML') 30 | if editkeyboard == True: 31 | keyboard_menu = bot.edit_message_reply_markup(chat,update.message.message_id,reply_markup=InlineKeyboardMarkup(menu)) 32 | return keyboard_menu 33 | 34 | @decorators.public.init 35 | @decorators.admin.user_admin 36 | @decorators.bot.check_is_admin 37 | @decorators.delete.init 38 | def init(update,context): 39 | keyboard_filters(update,context) 40 | 41 | @decorators.admin.user_admin 42 | def update_filters(update,context): 43 | query = update.callback_query 44 | chat = update.effective_message.chat_id 45 | group = GroupRepository().getById(chat) 46 | ################################### 47 | #### SET CHAT FILTERS #### 48 | ################################### 49 | if query.data.startswith("ff"): 50 | txt = query.data[2:] 51 | if txt == 'exe_filters': 52 | record = GroupRepository.EXE_FILTER 53 | row = group['exe_filter'] 54 | if row == 0: 55 | update_db_settings(update, record, False) 56 | return keyboard_filters(query,context,True) 57 | else: 58 | update_db_settings(update, record, True) 59 | return keyboard_filters(query,context,True) 60 | if txt == 'zip_filters': 61 | record = GroupRepository.ZIP_FILTER 62 | row = group["zip_filter"] 63 | if row == 0: 64 | update_db_settings(update, record, False) 65 | return keyboard_filters(query,context,True) 66 | else: 67 | update_db_settings(update, record, True) 68 | return keyboard_filters(query,context,True) 69 | 70 | if txt== 'targz_filters': 71 | record = GroupRepository.TARGZ_FILTER 72 | row = group["targz_filter"] 73 | if row == 0: 74 | update_db_settings(update, record, False) 75 | return keyboard_filters(query,context,True) 76 | else: 77 | update_db_settings(update, record, True) 78 | return keyboard_filters(query,context,True) 79 | 80 | if txt == 'gif_filters': 81 | record = GroupRepository.GIF_FILTER 82 | row = group['gif_filter'] 83 | if row == 0: 84 | update_db_settings(update, record, False) 85 | return keyboard_filters(query,context,True) 86 | else: 87 | update_db_settings(update, record, True) 88 | return keyboard_filters(query,context,True) 89 | 90 | if txt == 'jpg_filters': 91 | record = GroupRepository.JPG_FILTER 92 | row = group['jpg_filter'] 93 | if row == 0: 94 | update_db_settings(update, record, False) 95 | return keyboard_filters(query,context,True) 96 | else: 97 | update_db_settings(update, record, True) 98 | return keyboard_filters(query,context,True) 99 | 100 | if txt == 'docx_filters': 101 | record = GroupRepository.DOCX_FILTER 102 | row = group['docx_filter'] 103 | if row == 0: 104 | update_db_settings(update, record, False) 105 | return keyboard_filters(query,context,True) 106 | else: 107 | update_db_settings(update, record, True) 108 | return keyboard_filters(query,context,True) 109 | 110 | if txt == 'apk_filters': 111 | record = GroupRepository.APK_FILTER 112 | row = group['apk_filter'] 113 | if row == 0: 114 | update_db_settings(update, record, False) 115 | return keyboard_filters(query,context,True) 116 | else: 117 | update_db_settings(update, record, True) 118 | return keyboard_filters(query,context,True) 119 | 120 | if txt == 'seall': 121 | record_TARGZ = GroupRepository.TARGZ_FILTER 122 | record_ZIP = GroupRepository.ZIP_FILTER 123 | record_EXE = GroupRepository.EXE_FILTER 124 | record_JPG = GroupRepository.JPG_FILTER 125 | record_APK = GroupRepository.APK_FILTER 126 | record_GIF = GroupRepository.GIF_FILTER 127 | record_DOCX = GroupRepository.DOCX_FILTER 128 | 129 | update_db_settings(update, record_TARGZ, False) 130 | update_db_settings(update, record_ZIP, False) 131 | update_db_settings(update, record_EXE, False) 132 | update_db_settings(update, record_JPG, False) 133 | update_db_settings(update, record_APK, False) 134 | update_db_settings(update, record_GIF, False) 135 | update_db_settings(update, record_DOCX, False) 136 | return keyboard_filters(query,context,True) 137 | 138 | if txt == 'deall': 139 | record_TARGZ = GroupRepository.TARGZ_FILTER 140 | record_ZIP = GroupRepository.ZIP_FILTER 141 | record_EXE = GroupRepository.EXE_FILTER 142 | record_JPG = GroupRepository.JPG_FILTER 143 | record_APK = GroupRepository.APK_FILTER 144 | record_GIF = GroupRepository.GIF_FILTER 145 | record_DOCX = GroupRepository.DOCX_FILTER 146 | 147 | update_db_settings(update, record_TARGZ, True) 148 | update_db_settings(update, record_ZIP, True) 149 | update_db_settings(update, record_EXE, True) 150 | update_db_settings(update, record_JPG, True) 151 | update_db_settings(update, record_APK, True) 152 | update_db_settings(update, record_GIF, True) 153 | update_db_settings(update, record_DOCX, True) 154 | return keyboard_filters(query,context,True) 155 | -------------------------------------------------------------------------------- /core/commands/admin/greport.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core import decorators 6 | from languages.getLang import languages 7 | from core.utilities.message import message 8 | from core.utilities.functions import chat_object 9 | from core.handlers.logs import staff_loggers 10 | 11 | @decorators.public.init 12 | @decorators.admin.user_admin 13 | @decorators.delete.init 14 | def init(update, context): 15 | bot = context.bot 16 | chat = chat_object(update) 17 | languages(update,context) 18 | if update.effective_message.reply_to_message: 19 | message(update, context, languages.delete_error_msg) 20 | else: 21 | link = bot.export_chat_invite_link(chat.id) 22 | msg = "#GlobalReport\nChatId: {}\nChat: {}\nLink: {}".format(chat.id, chat.title, link) 23 | msg_report = languages.global_report_msg 24 | staff_loggers(update, context, msg) 25 | message(update, context, msg_report) -------------------------------------------------------------------------------- /core/commands/admin/info_group.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | import time 6 | import calendar 7 | from core.database.repository.group import GroupRepository 8 | from languages.getLang import languages 9 | from core.utilities.message import message 10 | from core.utilities.functions import save_group 11 | from core import decorators 12 | 13 | @decorators.admin.user_admin 14 | @decorators.bot.check_is_admin 15 | @decorators.public.init 16 | @decorators.bot.check_can_delete 17 | @decorators.delete.init 18 | def init(update, context): 19 | languages(update,context) 20 | chat = update.effective_message.chat_id 21 | chat_title = update.effective_chat.title 22 | record = GroupRepository.SET_GROUP_NAME 23 | row = GroupRepository().getById([chat]) 24 | if row: 25 | current_GMT = time.gmtime() 26 | ts = calendar.timegm(current_GMT) 27 | data = [(chat_title, chat)] 28 | GroupRepository().update_group_settings(record, data) 29 | counter = GroupRepository().getUpdatesByChatMonth(chat) 30 | img = "{}?v={}".format(row['group_photo'],ts) 31 | caption = languages.group_info.format( 32 | row['group_name'], 33 | row['id_group'], 34 | row['languages'], 35 | row['max_warn'], 36 | row['total_users'], 37 | counter['counter']) 38 | message(update, context, caption, 'HTML', 'photo', None, img) 39 | else: 40 | save_group(update) 41 | 42 | @decorators.admin.user_admin 43 | @decorators.delete.init 44 | def id_chat(update,context): 45 | chat = update.effective_message.chat_id 46 | message(update,context,"⚙️ Chat Id:\n🏷 [{}]\n\nFor more information on the group type /status".format(chat)) -------------------------------------------------------------------------------- /core/commands/admin/mute.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | import re 7 | from core import decorators 8 | from core.utilities.regex import Regex 9 | from languages.getLang import languages 10 | from core.utilities.message import message 11 | from core.utilities.menu import build_menu 12 | from telegram.utils.helpers import mention_html 13 | from core.database.repository.group import GroupRepository 14 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup 15 | from core.utilities.functions import mute_user_reply, mute_user_by_id, mute_user_by_id_time, mute_user_by_username_time, chat_object 16 | 17 | def convert_time(update,context,time_args): 18 | if time_args == "1d": 19 | time_args = int(86400) 20 | elif time_args == "3d": 21 | time_args = int(259200) 22 | elif time_args == "7d": 23 | time_args = int(604800) 24 | elif time_args == "1h": 25 | time_args = int(3600) 26 | elif time_args == "30s": 27 | time_args = int(30) 28 | else: 29 | error_msg = "You must enter a valid time value for the bot among the following: 1d, 3d, 7d, 1h, 30s" 30 | message(update,context,error_msg) 31 | return int(time_args) 32 | 33 | def mute_message(user,time): 34 | message = '🔇 You muted the user {}\n[{}]\n\nfor {} Time'.format(mention_html(user.id, user.first_name),user.id,time) 35 | return message 36 | 37 | @decorators.admin.user_admin 38 | @decorators.delete.init 39 | def init(update,context): 40 | languages(update,context) 41 | chat = chat_object(update) 42 | row = GroupRepository().getById(chat.id) 43 | if row['set_gh'] == 0: 44 | if update.message.reply_to_message: 45 | user = update.message.reply_to_message.from_user 46 | buttons = [] 47 | buttons.append(InlineKeyboardButton(languages.mute_button, callback_data='CMunmute')) 48 | buttons.append(InlineKeyboardButton('30Sec', callback_data='CM30')) 49 | buttons.append(InlineKeyboardButton('1 Hour', callback_data='CM3600')) 50 | buttons.append(InlineKeyboardButton('1 Day', callback_data='CM86400')) 51 | buttons.append(InlineKeyboardButton('3 Days', callback_data='CM259200')) 52 | buttons.append(InlineKeyboardButton('7 Days', callback_data='CM604800')) 53 | buttons.append(InlineKeyboardButton('Forever', callback_data='CMforever')) 54 | menu = build_menu(buttons,2) 55 | msg = languages.mute_msg.format(user.id,user.first_name,user.id) 56 | update.message.reply_to_message.reply_text(msg, reply_markup=InlineKeyboardMarkup(menu),parse_mode='HTML') 57 | mute_user_reply(update,context,True) 58 | else: 59 | text = update.message.text 60 | input_user_id = text[5:].strip().split(" ", 1) 61 | user_id = input_user_id[0] 62 | time_args = input_user_id[1] 63 | if user_id != "" and time_args != "": 64 | #Mute via Username es: /mute @username 1d 65 | if user_id.startswith('@'): 66 | time_args = input_user_id[1] 67 | arg_time = convert_time(update,context,time_args) 68 | mute_user_by_username_time(update,context,user_id,True,arg_time) 69 | msg = '🔇 You muted the user {} for {} time'.format(user_id,time_args) 70 | message(update,context,msg) 71 | else: 72 | #Mute via Id es: /mute 1234568 1d 73 | time_args = input_user_id[1] 74 | number = re.search(Regex.HAS_NUMBER, user_id) 75 | if number is None: 76 | message(update,context,"Type a correct telegram id or type in the username!") 77 | else: 78 | mute_user_by_id_time(update,context,user_id,True,int(time_args)) 79 | msg = '🔇 You muted the user {} [{}] for {} time'.format(user_id,user_id,user_id,time_args) 80 | message(update,context,msg) 81 | else: 82 | message(update,context,"Attention you have not entered the user id and mute time correctly") 83 | else: 84 | return 85 | 86 | @decorators.admin.user_admin 87 | def update_mute(update,context): 88 | query = update.callback_query 89 | user = query.message.reply_to_message.from_user 90 | if query.data.startswith("CM"): 91 | txt = query.data[2:] 92 | if txt == "30": 93 | mute_user_by_id_time(update,context,user.id,True,int(txt)) 94 | query.edit_message_text(mute_message(user,txt), parse_mode='HTML') 95 | if txt == "3600": 96 | mute_user_by_id_time(update,context,user.id,True,int(txt)) 97 | query.edit_message_text(mute_message(user,'1 Hour'), parse_mode='HTML') 98 | if txt == "86400": 99 | mute_user_by_id_time(update,context,user.id,True,int(txt)) 100 | query.edit_message_text(mute_message(user,'1 Day'), parse_mode='HTML') 101 | if txt == "259200": 102 | mute_user_by_id_time(update,context,user.id,True,int(txt)) 103 | query.edit_message_text(mute_message(user,'3 Days'), parse_mode='HTML') 104 | if txt == "604800": 105 | mute_user_by_id_time(update,context,user.id,True,int(txt)) 106 | query.edit_message_text(mute_message(user,'7 Days'), parse_mode='HTML') 107 | if txt == "forever": 108 | mute_user_by_id(update,context,user.id,True) 109 | query.edit_message_text(mute_message(user,'Forever'), parse_mode='HTML') 110 | if txt == 'unmute': 111 | languages(update,context) 112 | mute_user_by_id(update,context,user.id,False) 113 | msg = languages.mute_msg_r.format(user.id,user.first_name,user.id) 114 | query.edit_message_text(msg, parse_mode='HTML') -------------------------------------------------------------------------------- /core/commands/admin/pin.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | from core import decorators 7 | from core.utilities.message import message 8 | 9 | @decorators.admin.user_admin 10 | @decorators.delete.init 11 | def pin(update,context): 12 | bot = context.bot 13 | reply = update.message.reply_to_message 14 | if reply: 15 | msg = str(reply.text).strip() 16 | if reply.photo: 17 | caption = update.message.reply_to_message.caption 18 | update.message.reply_to_message.reply_photo(photo=reply.photo[-1].file_id, caption=caption) 19 | bot.pin_chat_message(update.message.chat_id, update.message.message_id+1,disable_notification=True) 20 | else: 21 | message(update,context,msg) 22 | bot.pin_chat_message(update.message.chat_id, update.message.message_id+1,disable_notification=True) 23 | else: 24 | msg = update.message.text[4:].strip() 25 | message(update,context,msg) 26 | bot.pin_chat_message(update.message.chat_id, update.message.message_id+1,disable_notification=True) 27 | 28 | @decorators.admin.user_admin 29 | @decorators.delete.init 30 | def unpin_all(update, context): 31 | bot = context.bot 32 | bot.unpin_all_chat_messages(chat_id=update.effective_chat.id) 33 | message(update,context,"All messages have been Unpinned!") -------------------------------------------------------------------------------- /core/commands/admin/promote.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | from telegram.error import BadRequest 7 | from core import decorators 8 | from core.utilities.message import message 9 | from core.utilities.functions import bot_object, chat_object, user_reply_object 10 | from languages.getLang import languages 11 | 12 | @decorators.admin.user_admin 13 | def init(update,context): 14 | try: 15 | languages(update,context) 16 | if update.message.reply_to_message: 17 | bot = bot_object(update,context) 18 | chat = chat_object(update) 19 | user = user_reply_object(update) 20 | bot.promoteChatMember(chat.id,user.id, 21 | can_change_info=True, 22 | can_delete_messages=True, 23 | can_invite_users=True, 24 | can_restrict_members=True, 25 | can_pin_messages=True, 26 | can_promote_members=True 27 | ) 28 | else: 29 | message(update,context,languages.delete_error_msg) 30 | except BadRequest: 31 | message(update,context,text="Non ho il permesso per promuovere questo utente come admin!\nPuoi darmi questo permesso spuntando il flag:\n Aggiungere Amministratori") -------------------------------------------------------------------------------- /core/commands/admin/say.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core import decorators 6 | from languages.getLang import languages 7 | from core.utilities.message import message 8 | 9 | @decorators.admin.user_admin 10 | @decorators.bot.check_can_delete 11 | @decorators.delete.init 12 | def init(update,context): 13 | languages(update,context) 14 | msg = update.message.text[4:].strip() 15 | if msg != "": 16 | message(update, context, msg, 'HTML', 'message', None, None) 17 | else: 18 | message(update, context, languages.say_error, 'HTML', 'message', None, None) -------------------------------------------------------------------------------- /core/commands/admin/set_custom_handler.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | from core import decorators 7 | from core.utilities.message import message 8 | from core.utilities.functions import chat_object 9 | from core.database.repository.group import GroupRepository 10 | 11 | @decorators.admin.user_admin 12 | @decorators.delete.init 13 | def init(update, context): 14 | chat = chat_object(update) 15 | msg = update.message.text[7:] 16 | reply = update.message.reply_to_message 17 | if reply: 18 | custom_question = str(reply.text) 19 | if custom_question == '/test': 20 | message(update, context, 'This command is reserved for the bot!') 21 | else: 22 | custom_answer = str(msg).lower() 23 | data = [(chat.id,custom_question,custom_answer)] 24 | GroupRepository().insert_custom_handler(data) 25 | message(update,context,"Custom handler setted!\n\nQuestion: {}\nAnswer: {}".format(custom_question,custom_answer)) 26 | else: 27 | message(update,context,"You must reply to a message to use this command!") -------------------------------------------------------------------------------- /core/commands/admin/set_lang.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core import decorators 6 | from core.database.repository.group import GroupRepository 7 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup 8 | from core.utilities.message import message 9 | from core.utilities.functions import flag 10 | 11 | LANGUAGE_KEYBOARD = [[ 12 | InlineKeyboardButton(flag('gb'), callback_data='language_en'), 13 | InlineKeyboardButton(flag('it'), callback_data='language_it') 14 | ]] 15 | 16 | record = GroupRepository.SET_LANGUAGE 17 | 18 | @decorators.admin.user_admin 19 | def init(update,context): 20 | reply_markup = InlineKeyboardMarkup(LANGUAGE_KEYBOARD) 21 | msg = "Please select your preferred language\n\nPerfavore seleziona la tua lingua di preferenza" 22 | message(update,context,msg,reply_markup=reply_markup) 23 | 24 | @decorators.admin.user_admin 25 | def language_en(update, context): 26 | chat = update.effective_message.chat_id 27 | msg = "You have selected the English language for your group" 28 | query = update.callback_query 29 | query.answer() 30 | lang = "EN" 31 | data = [(lang,chat)] 32 | GroupRepository().update_group_settings(record, data) 33 | query.edit_message_text(msg,parse_mode='HTML') 34 | 35 | @decorators.admin.user_admin 36 | def language_it(update, context): 37 | chat = update.effective_message.chat_id 38 | msg = "Hai selezionato la lingua italiana per il tuo gruppo" 39 | query = update.callback_query 40 | query.answer() 41 | lang = "IT" 42 | data = [(lang,chat)] 43 | GroupRepository().update_group_settings(record, data) 44 | query.edit_message_text(msg,parse_mode='HTML') -------------------------------------------------------------------------------- /core/commands/admin/set_rules.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | from core import decorators 7 | from core.utilities.message import message 8 | from languages.getLang import languages 9 | from core.database.repository.group import GroupRepository 10 | 11 | @decorators.admin.user_admin 12 | @decorators.delete.init 13 | def init(update, context): 14 | record = GroupRepository.SET_RULES_TEXT 15 | chat = update.effective_chat.id 16 | msg = update.message.text[9:].strip() 17 | languages(update,context) 18 | if msg != "": 19 | data = [(msg, chat)] 20 | GroupRepository().update_group_settings(record, data) 21 | message(update, context, languages.rules_msg) 22 | else: 23 | message(update, context, languages.rules_error_msg) -------------------------------------------------------------------------------- /core/commands/admin/set_welcome.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | from core import decorators 7 | from core.utilities.message import message 8 | from languages.getLang import languages 9 | from core.database.repository.group import GroupRepository 10 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup 11 | from core.utilities.menu import build_menu 12 | import json 13 | 14 | def _remove_button(group_id, btn_id): 15 | """ 16 | group_id, int indicating the id of the group 17 | btn_id, json button id to remove 18 | """ 19 | # select 20 | group_record = GroupRepository().getById(group_id) 21 | welcome_btns = group_record['welcome_buttons'] 22 | welcome_btns = json.loads(welcome_btns)['buttons'] 23 | 24 | new_welcome_btns = [btn for btn in welcome_btns if btn['id'] != int(btn_id)] 25 | 26 | # insert 27 | welcome_btns_text = json.dumps({"buttons": new_welcome_btns}) 28 | GroupRepository().updateWelcomeButtonsByGroupId(group_id, welcome_btns_text) 29 | 30 | def _add_button(group_id, btn): 31 | """ 32 | group_id, int indicating the id of the group 33 | btn, dict representing a json button 34 | """ 35 | # select 36 | group_record = GroupRepository().getById(group_id) 37 | welcome_btns = group_record['welcome_buttons'] 38 | welcome_btns = (json.loads(welcome_btns))['buttons'] 39 | 40 | # add 41 | if len(welcome_btns) == 0: 42 | btn['id'] = 0 43 | else: 44 | btn['id'] = welcome_btns[-1]['id'] + 1 45 | 46 | welcome_btns.append(btn) 47 | 48 | # insert 49 | welcome_btns_text = json.dumps({"buttons": welcome_btns}) 50 | GroupRepository().updateWelcomeButtonsByGroupId(group_id, welcome_btns_text) 51 | 52 | @decorators.admin.user_admin 53 | @decorators.delete.init 54 | def set_welcome_buttons(update, context): 55 | try: 56 | cmd_args = update.message.text[16:].strip().split() 57 | action = cmd_args[0] 58 | group_id = update.effective_chat.id 59 | 60 | # Add Welcome Buttons /welcomebuttons add "title" "url" 61 | if action == 'add': 62 | title = cmd_args[1][1:-1] 63 | url = cmd_args[2][1:-1] 64 | button = {'title': title, 'url': url} 65 | 66 | _add_button(group_id, button) 67 | message(update, context, "You have added a button to the welcome!") 68 | # Remove Welcome Buttons /welcomebuttons remove "buttonid" 69 | elif action == 'remove': 70 | button_id = cmd_args[1][1:-1] 71 | _remove_button(group_id, button_id) 72 | message(update, context, "You have removed the button with id: {}".format(button_id)) 73 | # If no action has been taken, this error is returned 74 | else: 75 | message(update, context, "The action you requested is incorrect type add or remove") 76 | except IndexError: 77 | # List Welcome Buttons /welcomebuttons with no args 78 | chat = update.effective_message.chat_id 79 | buttons = GroupRepository().getById(chat) 80 | welcome_buttons = buttons['welcome_buttons'] 81 | format_json = json.loads(welcome_buttons) 82 | x = format_json['buttons'] 83 | options = "" 84 | for a in x: 85 | if 'id' in a: 86 | button_id = a['id'] 87 | else: 88 | button_id = -1 89 | title = a['title'] 90 | url = a['url'] 91 | options += "Button Id: {}\n".format(button_id) 92 | options += "Button Text: {}\n".format(title) 93 | options += "Button Url: {}\n\n\n".format(url) 94 | message(update, context, options) 95 | 96 | @decorators.admin.user_admin 97 | @decorators.delete.init 98 | def init(update, context): 99 | languages(update,context) 100 | record = GroupRepository.SET_WELCOME_TEXT 101 | chat = update.effective_chat.id 102 | msg = update.message.text[8:].strip() 103 | reply = update.message.reply_to_message 104 | if reply: 105 | welcome_text = str(reply.text).lower() 106 | data = [(welcome_text, chat)] 107 | GroupRepository().update_group_settings(record, data) 108 | message(update,context, text="Welcome impostato!") 109 | else: 110 | if msg != "": 111 | data = [(msg, chat)] 112 | GroupRepository().update_group_settings(record, data) 113 | message(update, context, languages.set_welcome_help) 114 | else: 115 | message(update, context, languages.set_welcome_main) 116 | 117 | 118 | @decorators.admin.user_admin 119 | @decorators.delete.init 120 | def set_type_no_username(update, context): 121 | bot = context.bot 122 | chat = update.effective_message.chat_id 123 | buttons = [] 124 | buttons.append(InlineKeyboardButton('Kick Only', callback_data='tpnu1')) 125 | buttons.append(InlineKeyboardButton('Message Only', callback_data='tpnu2')) 126 | buttons.append(InlineKeyboardButton('Mute Only', callback_data='tpnu3')) 127 | buttons.append(InlineKeyboardButton('Ban Only', callback_data='tpnu4')) 128 | buttons.append(InlineKeyboardButton('Silent Kick', callback_data='tpnu5')) 129 | buttons.append(InlineKeyboardButton('No action', callback_data='tpnu6')) 130 | buttons.append(InlineKeyboardButton('Close', callback_data='closeMenu')) 131 | menu = build_menu(buttons,3) 132 | bot.send_message(chat,"No Username Filter Settings\nThe message is always present except for the Silent Kick and No Action", reply_markup=InlineKeyboardMarkup(menu),parse_mode='HTML') 133 | 134 | 135 | @decorators.admin.user_admin 136 | def update_set_tpnu(update, context): 137 | query = update.callback_query 138 | if query.data.startswith("tpnu"): 139 | chat_id = query.message.chat_id 140 | tpnu_set = query.data[4:] 141 | record = GroupRepository.SET_TPNU 142 | data = [(tpnu_set,chat_id)] 143 | GroupRepository().update_group_settings(record, data) 144 | text = "You have set the filter to {}\nLegend:\n1 == Kick\n2 == Message\n3 == Mute\n4 == Ban\n5 == Silent Kick\n6 == No Action".format(tpnu_set) 145 | query.edit_message_text(text, parse_mode='HTML') 146 | -------------------------------------------------------------------------------- /core/commands/admin/settings.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core import decorators 6 | from languages.getLang import languages 7 | from core.commands.admin import set_lang 8 | from core.utilities.menu import build_menu 9 | from core.utilities.functions import update_db_settings, save_group 10 | from core.utilities.constants import PERM_TRUE, PERM_FALSE 11 | from core.utilities.message import message 12 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup 13 | from core.database.repository.group import GroupRepository 14 | 15 | def keyboard_settings(update,context,editkeyboard = False): 16 | bot = context.bot 17 | chat = update.message.chat_id 18 | chat_title = update.message.chat.title 19 | group = GroupRepository().getById(chat) 20 | if group: 21 | list_buttons = [] 22 | list_buttons.append(InlineKeyboardButton('%s Welcome 👋🏻' % ('✅' if group['set_welcome'] == 1 else '❌'), callback_data='setWelcome')) 23 | list_buttons.append(InlineKeyboardButton('%s Silence 🤫' % ('✅' if group['set_silence'] == 1 else '❌'), callback_data='setSilence')) 24 | list_buttons.append(InlineKeyboardButton('%s Deny All Entry 🚷' % ('✅' if group['block_new_member'] == 1 else '❌'), callback_data='setBlockEntry')) 25 | list_buttons.append(InlineKeyboardButton('%s AntiFlood 🚫' % ('✅' if group['set_antiflood'] == 1 else '❌'), callback_data='setAntiflood')) 26 | list_buttons.append(InlineKeyboardButton('%s No User Photo Entry ⛔️' % ('✅' if group['set_user_profile_picture'] == 1 else '❌'), callback_data='userPhoto')) 27 | list_buttons.append(InlineKeyboardButton('%s No Arabic Entry ⛔️' % ('✅' if group['set_arabic_filter'] == 1 else '❌'), callback_data='arabic')) 28 | list_buttons.append(InlineKeyboardButton('%s No Russian Entry ⛔️' % ('✅' if group['set_cirillic_filter'] == 1 else '❌'), callback_data='cirillic')) 29 | list_buttons.append(InlineKeyboardButton('%s No Chinese Entry ⛔️' % ('✅' if group['set_chinese_filter'] == 1 else '❌'), callback_data='chinese')) 30 | list_buttons.append(InlineKeyboardButton('%s No ZooPhile Entry ⛔️' % ('✅' if group['zoophile_filter'] == 1 else '❌'), callback_data='zoophile')) 31 | list_buttons.append(InlineKeyboardButton('%s Block Vocal ⛔️' % ('✅' if group['set_no_vocal'] == 1 else '❌'), callback_data='novocal')) 32 | list_buttons.append(InlineKeyboardButton('%s Block Channel 📢' % ('✅' if group['sender_chat_block'] == 1 else '❌'), callback_data='channelblock')) 33 | list_buttons.append(InlineKeyboardButton('%s Block Spoiler 🚫' % ('✅' if group['spoiler_block'] == 1 else '❌'), callback_data='spoilerblock')) 34 | list_buttons.append(InlineKeyboardButton('%s Live with GH 🤖' % ('✅' if group['set_gh'] == 1 else '❌'),callback_data='setgrouphelp')) 35 | list_buttons.append(InlineKeyboardButton('Languages 🌍', callback_data='lang')) 36 | list_buttons.append(InlineKeyboardButton('Commands', url='https://github.com/Squirrel-Network/nebula8/wiki/Command-List')) 37 | list_buttons.append(InlineKeyboardButton('Dashboard', url='https://nebula.squirrel-network.online')) 38 | list_buttons.append(InlineKeyboardButton("Close 🗑", callback_data='close')) 39 | menu = build_menu(list_buttons,2) 40 | if editkeyboard == False: 41 | keyboard_menu = message(update,context,"⚙️ Bot settings\n\n📜 Group Name: {}\n🏷 ChatId: {}".format(chat_title,chat),reply_markup=InlineKeyboardMarkup(menu)) 42 | if editkeyboard == True: 43 | keyboard_menu = bot.edit_message_reply_markup(chat,update.message.message_id,reply_markup=InlineKeyboardMarkup(menu)) 44 | return keyboard_menu 45 | else: 46 | save_group(update) 47 | 48 | @decorators.public.init 49 | @decorators.admin.user_admin 50 | @decorators.bot.check_is_admin 51 | @decorators.delete.init 52 | def init(update,context): 53 | keyboard_settings(update,context) 54 | 55 | @decorators.admin.user_admin 56 | def update_settings(update,context): 57 | bot = context.bot 58 | languages(update,context) 59 | query = update.callback_query 60 | chat = update.effective_message.chat_id 61 | group = GroupRepository().getById(chat) 62 | # Set Welcome 63 | if query.data == 'setWelcome': 64 | record = GroupRepository.SET_WELCOME 65 | row = group['set_welcome'] 66 | if row == 1: 67 | update_db_settings(update, record, True) 68 | return keyboard_settings(query,context,True) 69 | else: 70 | data_block = [(1,0,chat)] 71 | update_db_settings(update, record, False) 72 | GroupRepository().set_block_entry(data_block) 73 | return keyboard_settings(query,context,True) 74 | # Set Global Silence 75 | if query.data == 'setSilence': 76 | record = GroupRepository.SET_SILENCE 77 | row = group['set_silence'] 78 | if row == 0: 79 | update_db_settings(update, record, False) 80 | bot.set_chat_permissions(update.effective_chat.id, PERM_FALSE) 81 | return keyboard_settings(query,context,True) 82 | else: 83 | update_db_settings(update, record, True) 84 | bot.set_chat_permissions(update.effective_chat.id, PERM_TRUE) 85 | return keyboard_settings(query,context,True) 86 | # Set Block Entry 87 | if query.data == 'setBlockEntry': 88 | row = group['block_new_member'] 89 | if row == 0: 90 | data = [(0,1,chat)] 91 | GroupRepository().set_block_entry(data) 92 | return keyboard_settings(query,context,True) 93 | else: 94 | data = [(1,0,chat)] 95 | GroupRepository().set_block_entry(data) 96 | return keyboard_settings(query,context,True) 97 | if query.data == 'channelblock': 98 | record = GroupRepository.SENDER_CHAT_BLOCK 99 | row = group['sender_chat_block'] 100 | if row == 1: 101 | update_db_settings(update, record, True) 102 | return keyboard_settings(query,context,True) 103 | else: 104 | update_db_settings(update, record, False) 105 | return keyboard_settings(query,context,True) 106 | if query.data == 'spoilerblock': 107 | record = GroupRepository.SPOILER_BLOCK 108 | row = group['spoiler_block'] 109 | if row == 1: 110 | update_db_settings(update, record, True) 111 | return keyboard_settings(query,context,True) 112 | else: 113 | update_db_settings(update, record, False) 114 | return keyboard_settings(query,context,True) 115 | 116 | if query.data == 'novocal': 117 | record = GroupRepository.SET_NO_VOCAL 118 | row = group['set_no_vocal'] 119 | if row == 1: 120 | update_db_settings(update, record, True) 121 | return keyboard_settings(query,context,True) 122 | else: 123 | update_db_settings(update, record, False) 124 | return keyboard_settings(query,context,True) 125 | 126 | if query.data == 'setAntiflood': 127 | record = GroupRepository.SET_ANTIFLOOD 128 | row = group['set_antiflood'] 129 | if row == 1: 130 | update_db_settings(update, record, True) 131 | return keyboard_settings(query,context,True) 132 | else: 133 | update_db_settings(update, record, False) 134 | return keyboard_settings(query,context,True) 135 | 136 | if query.data == 'setgrouphelp': 137 | record = GroupRepository.SET_GH 138 | row = group['set_gh'] 139 | if row == 1: 140 | update_db_settings(update, record, True) 141 | return keyboard_settings(query,context,True) 142 | else: 143 | 144 | update_db_settings(update, record, False) 145 | return keyboard_settings(query,context,True) 146 | 147 | ################################### 148 | #### SET WELCOME FILTERS #### 149 | ################################### 150 | # Set Block Arabic Entry 151 | if query.data == 'arabic': 152 | record = GroupRepository.SET_ARABIC 153 | row = group['set_arabic_filter'] 154 | if row == 1: 155 | update_db_settings(update, record, True) 156 | return keyboard_settings(query,context,True) 157 | else: 158 | update_db_settings(update, record, False) 159 | return keyboard_settings(query,context,True) 160 | # Set Block Cirillic Entry 161 | if query.data == 'cirillic': 162 | record = GroupRepository.SET_CIRILLIC 163 | row = group['set_cirillic_filter'] 164 | if row == 1: 165 | update_db_settings(update, record, True) 166 | return keyboard_settings(query,context,True) 167 | else: 168 | update_db_settings(update, record, False) 169 | return keyboard_settings(query,context,True) 170 | if query.data == 'chinese': 171 | record = GroupRepository.SET_CHINESE 172 | row = group['set_chinese_filter'] 173 | if row == 1: 174 | update_db_settings(update, record, True) 175 | return keyboard_settings(query,context,True) 176 | else: 177 | update_db_settings(update, record, False) 178 | return keyboard_settings(query,context,True) 179 | if query.data == 'userPhoto': 180 | record = GroupRepository.SET_USER_PROFILE_PICT 181 | row = group['set_user_profile_picture'] 182 | if row == 1: 183 | update_db_settings(update, record, True) 184 | return keyboard_settings(query,context,True) 185 | else: 186 | update_db_settings(update, record, False) 187 | return keyboard_settings(query,context,True) 188 | if query.data == 'zoophile': 189 | record = GroupRepository.ZOOPHILE_FILTER 190 | row = group['zoophile_filter'] 191 | if row == 1: 192 | update_db_settings(update, record, True) 193 | return keyboard_settings(query,context,True) 194 | else: 195 | update_db_settings(update, record, False) 196 | return keyboard_settings(query,context,True) 197 | ################################### 198 | #### SET CHAT LANGUAGE #### 199 | ################################### 200 | if query.data == 'lang': 201 | set_lang.init(update, context) 202 | query.edit_message_text("You have closed the settings menu and open languages menu",parse_mode='HTML') 203 | 204 | # Close Menu 205 | if query.data == 'close': 206 | query.message.delete() -------------------------------------------------------------------------------- /core/commands/admin/shield.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | from core import decorators 7 | from languages.getLang import languages 8 | from core.utilities.functions import chat_object,update_db_settings 9 | from core.database.repository.group import GroupRepository 10 | from core.utilities.constants import PERM_FALSE, PERM_TRUE 11 | from core.utilities.menu import build_menu 12 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup 13 | from core.handlers.logs import telegram_loggers 14 | 15 | @decorators.admin.user_admin 16 | @decorators.delete.init 17 | def init(update, context): 18 | bot = context.bot 19 | chat = chat_object(update) 20 | languages(update,context) 21 | record_arabic = GroupRepository.SET_ARABIC 22 | record_chinese = GroupRepository.SET_CHINESE 23 | record_cirillic = GroupRepository.SET_CIRILLIC 24 | record_no_user_photo = GroupRepository.SET_USER_PROFILE_PICT 25 | record_silence = GroupRepository.SET_SILENCE 26 | record_block_channel = GroupRepository.SENDER_CHAT_BLOCK 27 | record_zoophile = GroupRepository.ZOOPHILE_FILTER 28 | 29 | 30 | data = [(0,1,chat.id)] 31 | GroupRepository().set_block_entry(data) 32 | update_db_settings(update, record_arabic, False) 33 | update_db_settings(update, record_chinese, False) 34 | update_db_settings(update, record_cirillic, False) 35 | update_db_settings(update, record_no_user_photo, False) 36 | update_db_settings(update, record_silence, False) 37 | update_db_settings(update, record_block_channel, False) 38 | update_db_settings(update, record_zoophile, False) 39 | buttons = [] 40 | buttons.append(InlineKeyboardButton('❌ Remove Shield', callback_data='removeShield')) 41 | menu = build_menu(buttons,1) 42 | 43 | bot.set_chat_permissions(update.effective_chat.id, PERM_FALSE) 44 | bot.send_message(chat.id,languages.shield_on,reply_markup=InlineKeyboardMarkup(menu),parse_mode='HTML') 45 | logs_text = '🛡Shield Activated in {} [{}]'.format(chat.title,chat.id) 46 | telegram_loggers(update,context,logs_text) 47 | 48 | @decorators.admin.user_admin 49 | def update_shield(update,context): 50 | bot = context.bot 51 | query = update.callback_query 52 | if query.data == 'removeShield': 53 | chat = update.effective_message.chat_id 54 | chat_title = update.effective_message.chat.title 55 | record_arabic = GroupRepository.SET_ARABIC 56 | record_chinese = GroupRepository.SET_CHINESE 57 | record_cirillic = GroupRepository.SET_CIRILLIC 58 | record_no_user_photo = GroupRepository.SET_USER_PROFILE_PICT 59 | record_silence = GroupRepository.SET_SILENCE 60 | record_block_channel = GroupRepository.SENDER_CHAT_BLOCK 61 | record_zoophile = GroupRepository.ZOOPHILE_FILTER 62 | 63 | 64 | data = [(1,0,chat)] 65 | GroupRepository().set_block_entry(data) 66 | update_db_settings(update, record_arabic, True) 67 | update_db_settings(update, record_chinese, True) 68 | update_db_settings(update, record_cirillic, True) 69 | update_db_settings(update, record_no_user_photo, True) 70 | update_db_settings(update, record_silence, True) 71 | update_db_settings(update, record_block_channel, True) 72 | update_db_settings(update, record_zoophile, True) 73 | bot.set_chat_permissions(update.effective_chat.id, PERM_TRUE) 74 | msg = '✅ Shield removed!' 75 | query.edit_message_text(msg, parse_mode='HTML') 76 | logs_text = '🛡Shield Deactivated in {} [{}]'.format(chat_title,chat) 77 | telegram_loggers(update,context,logs_text) -------------------------------------------------------------------------------- /core/commands/admin/top.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | import time 7 | import calendar 8 | from core import decorators 9 | from core.utilities.message import message 10 | from core.utilities.menu import build_menu 11 | from core.database.repository.group import GroupRepository 12 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup 13 | from core.utilities.functions import upd_charts_DESC, upd_charts_ASC 14 | 15 | 16 | @decorators.admin.user_admin 17 | @decorators.bot.check_is_admin 18 | @decorators.public.init 19 | @decorators.bot.check_can_delete 20 | @decorators.delete.init 21 | def init(update, context): 22 | list_buttons = [] 23 | list_buttons.append(InlineKeyboardButton('📈 Active', callback_data='useractive')) 24 | list_buttons.append(InlineKeyboardButton('📉 Inactive', callback_data='userinactive')) 25 | list_buttons.append(InlineKeyboardButton("🗑 Close", callback_data='close')) 26 | menu = build_menu(list_buttons,1) 27 | message(update,context,'Please select an option',reply_markup=InlineKeyboardMarkup(menu)) 28 | 29 | @decorators.admin.user_admin 30 | def update_top(update,context): 31 | query = update.callback_query 32 | current_GMT = time.gmtime() 33 | ts = calendar.timegm(current_GMT) 34 | if query.data == 'useractive': 35 | chat = update.effective_message.chat_id 36 | topUsers = GroupRepository().getTopActiveUsers(chat) 37 | string = "" 38 | for row in topUsers: 39 | username = row['tg_username'] 40 | user = username.replace('@', '') 41 | string += '▪️{} [{} messages]\n'.format(user,user,row['counter']) 42 | upd_charts_DESC(update,context) 43 | img = "https://naos.hersel.it/charts/{}desc.jpg?v={}".format(chat,ts) 44 | caption = 'Top 10 Active Users Until 30 Days\n\n{}'.format(string) 45 | time.sleep(1) 46 | query.message.delete() 47 | message(update, context, caption, 'HTML', 'photo', None, img) 48 | if query.data == 'userinactive': 49 | chat = update.effective_message.chat_id 50 | topUsers = GroupRepository().getTopInactiveUsers(chat) 51 | string = "" 52 | for row in topUsers: 53 | username = row['tg_username'] 54 | user = username.replace('@', '') 55 | string += '▪️{} [{} messages]\n'.format(user,user,row['counter']) 56 | upd_charts_ASC(update,context) 57 | img = "https://naos.hersel.it/charts/{}asc.jpg?v={}".format(chat,ts) 58 | caption = 'Top 10 Inactive Users Until 30 Days\n\n{}'.format(string) 59 | time.sleep(1) 60 | query.message.delete() 61 | message(update, context, caption, 'HTML', 'photo', None, img) -------------------------------------------------------------------------------- /core/commands/admin/unban.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | from core import decorators 7 | from core.utilities.message import message 8 | from telegram.utils.helpers import mention_html 9 | from core.utilities.functions import chat_object, user_reply_object 10 | from core.utilities.functions import reply_member_status_object 11 | 12 | @decorators.admin.user_admin 13 | def init(update,context): 14 | bot = context.bot 15 | reply = update.message.reply_to_message 16 | if reply is not None: 17 | user_status = reply_member_status_object(update,context) 18 | if user_status.status == 'kicked': 19 | chat = chat_object(update) 20 | user = user_reply_object(update) 21 | message(update,context,"the ban for the user {} [{}] has been removed".format(mention_html(user.id, user.first_name),user.id)) 22 | bot.unban_chat_member(chat.id, user.id) 23 | else: 24 | user = user_reply_object(update) 25 | message(update,context,"the user {} [{}] is not banned".format(mention_html(user.id, user.first_name),user.id)) 26 | else: 27 | message(update,context,"This command should be used in response to a user!") -------------------------------------------------------------------------------- /core/commands/admin/user_info.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | import datetime 6 | from core import decorators 7 | from core.utilities.message import message 8 | from core.utilities.functions import user_reply_object, chat_object 9 | from core.database.repository.user import UserRepository 10 | from core.utilities.strings import Strings 11 | 12 | @decorators.admin.user_admin 13 | @decorators.delete.init 14 | def init(update, context): 15 | user = user_reply_object(update) 16 | chat = chat_object(update) 17 | user_db = UserRepository().getById(user.id) 18 | get_warn = UserRepository().getUserByGroup([user.id,chat.id]) 19 | current_time = datetime.datetime.utcnow().isoformat() 20 | default_warn = 0 21 | default_score = 0 22 | if user_db: 23 | username = "@"+user.username 24 | data = [(username,current_time,user.id)] 25 | UserRepository().update(data) 26 | warn_count = get_warn['warn_count'] 27 | data_mtm = [(user.id, chat.id, default_warn, default_score)] 28 | UserRepository().add_into_mtm(data_mtm) 29 | msg = Strings.USER_INFO.format(id=user.id,username=user.username,chat=chat.title,warn=warn_count) 30 | message(update, context, msg, 'HTML', 'private') 31 | else: 32 | username = "@"+user.username 33 | data = [(user.id,username,current_time,current_time, default_score)] 34 | UserRepository().add(data) 35 | data_mtm = [(user.id, chat.id, default_warn)] 36 | UserRepository().add_into_mtm(data_mtm) 37 | msg = Strings.USER_INFO.format(id=user.id,username=user.username,chat=chat.title,warn=default_warn) 38 | message(update, context, msg, 'HTML', 'private') -------------------------------------------------------------------------------- /core/commands/admin/warn.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | import datetime 6 | from core import decorators 7 | from languages.getLang import languages 8 | from core.utilities.message import message 9 | from core.utilities.menu import build_menu 10 | from telegram.utils.helpers import mention_html 11 | from core.handlers.logs import telegram_loggers 12 | from core.database.repository.user import UserRepository 13 | from core.database.repository.group import GroupRepository 14 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup 15 | from core.utilities.functions import user_reply_object, chat_object, ban_user_reply, ban_user_by_id 16 | 17 | @decorators.admin.user_admin 18 | @decorators.delete.init 19 | def init(update,context): 20 | chat = chat_object(update) 21 | get_group = GroupRepository().getById(chat.id) 22 | max_warn = get_group['max_warn'] 23 | current_time = datetime.datetime.utcnow().isoformat() 24 | default_warn = 1 25 | languages(update,context) 26 | if get_group['set_gh'] == 0: 27 | if update.message.reply_to_message: 28 | reason = update.message.text[5:] 29 | user = user_reply_object(update) 30 | get_user = UserRepository().getUserByGroup([user.id,chat.id]) 31 | warn_count = get_user['warn_count'] if get_user is not None else 0 32 | if warn_count != max_warn: 33 | buttons = [] 34 | buttons.append(InlineKeyboardButton('➖ 1', callback_data='downWarn')) 35 | buttons.append(InlineKeyboardButton('➕ 1', callback_data='upWarn')) 36 | buttons.append(InlineKeyboardButton(languages.button_remove, callback_data='removeWarn')) 37 | menu = build_menu(buttons,3) 38 | if get_user: 39 | default_warn_count = 0 40 | default_user_score = 0 41 | username = "@"+user.username 42 | data = [(username,current_time,user.id)] 43 | UserRepository().update(data) 44 | data_mtm = [(user.id, chat.id, default_warn_count,default_user_score)] 45 | UserRepository().add_into_mtm(data_mtm) 46 | data_warn = [(user.id,chat.id)] 47 | UserRepository().updateWarn(data_warn) 48 | if reason: 49 | msg = languages.warn_with_reason.format(mention_html(user.id, user.first_name),get_user['warn_count']+1,max_warn,chat.title,chat.id,reason) 50 | update.message.reply_to_message.reply_text(msg, reply_markup=InlineKeyboardMarkup(menu),parse_mode='HTML') 51 | else: 52 | msg = languages.warn_user.format(mention_html(user.id, user.first_name),get_user['warn_count']+1,max_warn,chat.title,chat.id) 53 | update.message.reply_to_message.reply_text(msg, reply_markup=InlineKeyboardMarkup(menu),parse_mode='HTML') 54 | log_txt = "‼️ #Log {} was warned\nin the group: {} [{}]\nWarns: {}\{}".format(mention_html(user.id, user.first_name),chat.title,chat.id,get_user['warn_count']+1,max_warn) 55 | if reason: 56 | log_txt = "‼️ #Log {} was warned\nin the group: {} [{}]\nReason: {}\nWarns: {}\{}".format(mention_html(user.id, user.first_name),chat.title,chat.id,reason,get_user['warn_count']+1,max_warn) 57 | telegram_loggers(update,context,log_txt) 58 | else: 59 | username = "@"+user.username 60 | data = [(user.id,username,current_time,current_time)] 61 | UserRepository().add(data) 62 | data_mtm = [(user.id, chat.id, default_warn)] 63 | UserRepository().add_into_mtm(data_mtm) 64 | if reason: 65 | message(update,context,languages.warn_with_reason.format(username,chat.title,chat.id,reason)) 66 | else: 67 | message(update,context,languages.warn_user.format(username,chat.title,chat.id)) 68 | log_txt = "‼️ #Log {} was warned\nin the group: {} [{}]".format(mention_html(user.id, user.first_name),chat.title,chat.id) 69 | if reason: 70 | log_txt = "‼️ #Log {} was warned\nin the group: {} [{}]\nReason: {}".format(mention_html(user.id, user.first_name),chat.title,chat.id,reason) 71 | telegram_loggers(update,context,log_txt) 72 | else: 73 | ban_user_reply(update,context) 74 | buttons = [] 75 | buttons.append(InlineKeyboardButton('Remove', callback_data='removeWarn')) 76 | menu = build_menu(buttons,2) 77 | msg = languages.warn_user_max.format(user.username,chat.title) 78 | update.message.reply_to_message.reply_text(msg, reply_markup=InlineKeyboardMarkup(menu),parse_mode='HTML') 79 | else: 80 | message(update,context,languages.error_response_user_msg) 81 | else: 82 | return 83 | 84 | 85 | 86 | @decorators.admin.user_admin 87 | @decorators.delete.init 88 | def set_warn(update, context): 89 | bot = context.bot 90 | chat = update.effective_message.chat_id 91 | buttons = [] 92 | buttons.append(InlineKeyboardButton('2️⃣', callback_data='w2')) 93 | buttons.append(InlineKeyboardButton('3️⃣', callback_data='w3')) 94 | buttons.append(InlineKeyboardButton('4️⃣', callback_data='w4')) 95 | buttons.append(InlineKeyboardButton('5️⃣', callback_data='w5')) 96 | buttons.append(InlineKeyboardButton('6️⃣', callback_data='w6')) 97 | buttons.append(InlineKeyboardButton('7️⃣', callback_data='w7')) 98 | buttons.append(InlineKeyboardButton('8️⃣', callback_data='w8')) 99 | buttons.append(InlineKeyboardButton('9️⃣', callback_data='w9')) 100 | buttons.append(InlineKeyboardButton('🔟', callback_data='w10')) 101 | menu = build_menu(buttons,3) 102 | bot.send_message(chat,"⚙ Warn Settings", reply_markup=InlineKeyboardMarkup(menu),parse_mode='HTML' ) 103 | 104 | @decorators.admin.user_admin 105 | def update_set_warn(update, context): 106 | query = update.callback_query 107 | if query.data.startswith("w"): 108 | chat_id = query.message.chat_id 109 | warn_limit = query.data[1:] 110 | record = GroupRepository.SET_MAX_WARN 111 | data = [(warn_limit,chat_id)] 112 | GroupRepository().update_group_settings(record, data) 113 | text = "You have changed the maximum number\nof warns in this group to {}".format(warn_limit) 114 | query.edit_message_text(text, parse_mode='HTML') 115 | 116 | @decorators.admin.user_admin 117 | def update_warn(update,context): 118 | query = update.callback_query 119 | user_id = query.message.reply_to_message.from_user.id 120 | chat_id = query.message.reply_to_message.chat_id 121 | get_user = UserRepository().getUserByGroup([user_id,chat_id]) 122 | get_group = GroupRepository().getById(chat_id) 123 | max_warn = get_group['max_warn'] 124 | warn_count = get_user['warn_count'] if get_user is not None else 0 125 | if query.data == 'upWarn': 126 | if warn_count != max_warn: 127 | data_warn = [(user_id,chat_id)] 128 | UserRepository().updateWarn(data_warn) 129 | msg = 'You Upwarned: {}\nWarns: {}/{}'.format(user_id,user_id,get_user['warn_count']+1,max_warn) 130 | query.edit_message_text(msg, parse_mode='HTML') 131 | else: 132 | ban_user_by_id(update,context,user_id) 133 | msg = "The user has been banned because it has reached the maximum number of warns" 134 | query.edit_message_text(msg, parse_mode='HTML') 135 | if query.data == 'downWarn': 136 | if warn_count != 0: 137 | data_warn = [(user_id,chat_id)] 138 | UserRepository().downWarn(data_warn) 139 | msg = 'You Downwarned: {}\nWarns: {}/{}'.format(user_id,user_id,get_user['warn_count']-1,max_warn) 140 | query.edit_message_text(msg, parse_mode='HTML') 141 | else: 142 | msg = "The user cannot be downwarned anymore!" 143 | query.edit_message_text(msg, parse_mode='HTML') 144 | if query.data == 'removeWarn': 145 | data_warn = [(user_id,chat_id)] 146 | UserRepository().removeWarn(data_warn) 147 | msg = 'You have removed the Warns from user: {}'.format(user_id,user_id) 148 | query.edit_message_text(msg, parse_mode='HTML') -------------------------------------------------------------------------------- /core/commands/index.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core.commands import public ,admin, owner 6 | from telegram.ext import (CommandHandler as CMH,CallbackQueryHandler as CQH) 7 | from core.utilities.functions import close_menu 8 | 9 | """ 10 | Here are inserted all the commands with user permissions 11 | """ 12 | def user_command(dsp): 13 | function = dsp.add_handler 14 | ###################### 15 | ### CommandHandler ### 16 | ###################### 17 | function(CMH('start', public.start.init)) 18 | function(CMH('help', public.help.init)) 19 | function(CMH('rules', public.rules.init)) 20 | function(CMH('io', public.io.init)) 21 | function(CMH('source', public.source.init)) 22 | function(CMH('lost', public.eggs.egg_lost)) 23 | function(CMH('kickme', public.kickme.init)) 24 | function(CMH('staff', public.staff.init)) 25 | function(CMH('usearch', public.user_search.init)) 26 | 27 | """ 28 | Here are inserted all the commands with admin permissions 29 | """ 30 | def admin_command(dsp): 31 | function = dsp.add_handler 32 | ###################### 33 | ### CommandHandler ### 34 | ###################### 35 | function(CMH('ban', admin.ban.init)) 36 | function(CMH('unban', admin.unban.init)) 37 | function(CMH('setban', admin.ban.set_ban_message)) 38 | function(CMH('status', admin.info_group.init)) 39 | function(CMH('lang', admin.set_lang.init)) 40 | function(CMH('mute', admin.mute.init)) 41 | #function(CMH('check', admin.check_permission.init)) Need to Fix 42 | function(CMH('warn', admin.warn.init)) 43 | function(CMH('info', admin.user_info.init)) 44 | function(CMH('say', admin.say.init)) 45 | function(CMH('welcome', admin.set_welcome.init)) 46 | function(CMH('settings', admin.settings.init)) 47 | function(CMH('filters', admin.filters.init)) 48 | function(CMH('setwarn', admin.warn.set_warn)) 49 | function(CMH('setrules', admin.set_rules.init)) 50 | function(CMH('setnousername', admin.set_welcome.set_type_no_username)) 51 | function(CMH('del', admin.delete_message.init)) 52 | function(CMH('welcomebuttons', admin.set_welcome.set_welcome_buttons)) 53 | function(CMH('shield', admin.shield.init)) 54 | function(CMH('badword', admin.badword.init)) 55 | function(CMH('badlist', admin.badword.badlist)) 56 | function(CMH('promote', admin.promote.init)) 57 | function(CMH('dashboard', admin.dashboard.init)) 58 | function(CMH('chatid', admin.info_group.id_chat)) 59 | function(CMH('custom', admin.set_custom_handler.init)) 60 | function(CMH('top', admin.top.init)) 61 | function(CMH('unpinall', admin.pin.unpin_all)) 62 | function(CMH('pin', admin.pin.pin)) 63 | function(CMH('greport', admin.greport.init)) 64 | ############################# 65 | ### CallbackQuery Handler ### 66 | ############################# 67 | function(CQH(owner.superban.update_superban, pattern='m')) 68 | function(CQH(close_menu, pattern='closeMenu')) 69 | function(CQH(owner.superban.update_superban, pattern='removeSuperban')) 70 | function(CQH(owner.whitelist.remove_blacklist, pattern='removeBL')) 71 | function(CQH(owner.whitelist.remove_blacklist, pattern='closed')) 72 | function(CQH(admin.warn.update_set_warn, pattern='w')) 73 | function(CQH(admin.warn.update_warn, pattern='upWarn')) 74 | function(CQH(admin.warn.update_warn, pattern='downWarn')) 75 | function(CQH(admin.warn.update_warn, pattern='removeWarn')) 76 | function(CQH(admin.set_welcome.update_set_tpnu, pattern='tpnu')) 77 | function(CQH(owner.add_community.callback_community, pattern='comm')) 78 | function(CQH(admin.mute.update_mute, pattern='CM')) 79 | function(CQH(admin.set_lang.language_en, pattern='language_en')) 80 | function(CQH(admin.set_lang.language_it, pattern='language_it')) 81 | function(CQH(admin.filters.update_filters, pattern='ff')) 82 | function(CQH(public.rules.update_rules, pattern='openRules')) 83 | function(CQH(public.report.update_resolve, pattern='resolved')) 84 | function(CQH(admin.shield.update_shield, pattern='removeShield')) 85 | function(CQH(admin.top.update_top, pattern='useractive')) 86 | function(CQH(admin.top.update_top, pattern='userinactive')) 87 | function(CQH(owner.add_owner.update_owner, pattern='OwnerRemove')) 88 | function(CQH(admin.settings.update_settings)) 89 | """ 90 | Here are inserted all the commands with owner permissions 91 | """ 92 | def owner_command(dsp): 93 | function = dsp.add_handler 94 | ###################### 95 | ### CommandHandler ### 96 | ###################### 97 | function(CMH('b', owner.broadcast.init, run_async=True)) 98 | function(CMH('gb', owner.broadcast.global_broadcast, run_async=True)) 99 | function(CMH('s', owner.superban.init, run_async=True)) 100 | function(CMH('ms', owner.superban.multi_superban, run_async=True)) 101 | function(CMH('us', owner.superban.remove_superban_via_id, run_async=True)) 102 | function(CMH('w', owner.whitelist.init)) 103 | function(CMH('server', owner.server_info.init)) 104 | function(CMH('community', owner.add_community.init)) 105 | function(CMH('test', owner.test.init)) 106 | function(CMH('owner', owner.add_owner.init)) 107 | function(CMH('exit', owner.exit.init)) 108 | function(CMH('exportlink', owner.export_invite_link.init)) 109 | function(CMH('maxport', owner.export_invite_link.manual_export)) 110 | function(CMH('spam', owner.add_antispam.init)) 111 | function(CMH('channels', owner.list_community.channels)) 112 | function(CMH('groups', owner.list_community.groups)) 113 | function(CMH('rexit', owner.exit.remote_exit)) -------------------------------------------------------------------------------- /core/commands/owner/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | """Import Files""" 7 | __all__ = ["add_antispam","add_community","add_owner","broadcast","exit","export_invite_link","list_community","server_info","superban","test","whitelist"] 8 | 9 | from core.commands.owner import * -------------------------------------------------------------------------------- /core/commands/owner/add_antispam.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | from core import decorators 7 | from core.utilities.message import message 8 | from core.database.repository.group import GroupRepository 9 | 10 | @decorators.owner.init 11 | @decorators.delete.init 12 | def init(update,context): 13 | msg = update.message.text[5:].strip() 14 | if msg != "": 15 | GroupRepository().insert_spam(msg) 16 | message(update,context,"You have entered a new ANTISPAM logic in the database, the logic you have entered is the following: {}".format(msg)) 17 | else: 18 | message(update, context,"Empty Logic") -------------------------------------------------------------------------------- /core/commands/owner/add_community.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core import decorators 6 | from core.utilities.message import message 7 | from core.utilities.functions import chat_object 8 | from core.database.repository.community import CommunityRepository 9 | from core.database.repository.group import GroupRepository 10 | from core.utilities.menu import build_menu 11 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup 12 | 13 | @decorators.owner.init 14 | def init(update,context): 15 | bot = context.bot 16 | chat = chat_object(update) 17 | if chat.type == 'supergroup': 18 | row = CommunityRepository().getById(chat.id) 19 | if row: 20 | record = GroupRepository.SET_COMMUNITY 21 | default_community = 1 22 | data = [(chat.title,chat.id)] 23 | data_group = [(default_community, chat.id)] 24 | CommunityRepository().update(data) 25 | GroupRepository().update_group_settings(record,data_group) 26 | message(update,context,"I updated the community on the database") 27 | else: 28 | buttons = [] 29 | buttons.append(InlineKeyboardButton('IT', callback_data='commIT')) 30 | buttons.append(InlineKeyboardButton('EN', callback_data='commEN')) 31 | buttons.append(InlineKeyboardButton('Close', callback_data='closeMenu')) 32 | menu = build_menu(buttons,2) 33 | bot.send_message(chat_id=update.effective_chat.id,text="Please select the language of the community",reply_markup=InlineKeyboardMarkup(menu)) 34 | else: 35 | message(update,context,"Attention! this command can only be used in public supergroups!") 36 | 37 | @decorators.owner.init 38 | def callback_community(update,context): 39 | query = update.callback_query 40 | if query.data.startswith("comm"): 41 | lang_set = query.data[4:] 42 | type_community = query.message.chat.type 43 | chat_id = query.message.chat_id 44 | chat_title = query.message.chat.title 45 | chat_username = query.message.chat.username 46 | link = "https://t.me/{}".format(chat_username) 47 | record = GroupRepository.SET_COMMUNITY 48 | default_community = 1 49 | data = [(chat_title,chat_id,link,lang_set,type_community)] 50 | data_group = [(default_community, chat_id)] 51 | CommunityRepository().add(data) 52 | GroupRepository().update_group_settings(record,data_group) 53 | query.edit_message_text("I have added the community [{}] to the database".format(chat_title), parse_mode='HTML') -------------------------------------------------------------------------------- /core/commands/owner/add_owner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | from core import decorators 7 | from core.utilities.menu import build_menu 8 | from core.utilities.message import message 9 | from core.utilities.functions import user_reply_object 10 | from core.database.repository.user import UserRepository 11 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup 12 | 13 | @decorators.owner.init 14 | @decorators.delete.init 15 | def init(update,context): 16 | if update.message.reply_to_message: 17 | user = user_reply_object(update) 18 | user_id = user.id 19 | username = "@"+user.username 20 | row = UserRepository().getOwnerById(user.id) 21 | list_buttons = [] 22 | if row: 23 | list_buttons.append(InlineKeyboardButton('❌ Remove', callback_data='OwnerRemove')) 24 | list_buttons.append(InlineKeyboardButton("🗑 Close", callback_data='close')) 25 | menu = build_menu(list_buttons, 1) 26 | update.message.reply_to_message.reply_text('{} This owner already exists in the database'.format(username),reply_markup=InlineKeyboardMarkup(menu),parse_mode='HTML') 27 | else: 28 | data = [(user_id, username)] 29 | UserRepository().add_owner(data) 30 | message(update,context, "You have entered {} [{}] a new owner in the database!\nRestart the Bot!".format(username,user_id)) 31 | else: 32 | message(update,context, "Error! This command should be used in response to the user!") 33 | 34 | @decorators.owner.init 35 | def update_owner(update,context): 36 | query = update.callback_query 37 | user = query.message.reply_to_message.from_user 38 | if query.data == 'OwnerRemove': 39 | data = [(user.id)] 40 | UserRepository().remove_owner(data) 41 | query.edit_message_text("You have removed owner {} [{}] from the database".format(user.first_name,user.id), parse_mode='HTML') -------------------------------------------------------------------------------- /core/commands/owner/broadcast.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | import asyncio 6 | from core import decorators 7 | from core.utilities.message import message,messageWithAsyncById 8 | from core.utilities.strings import Strings 9 | from core.database.repository.community import CommunityRepository 10 | from core.database.repository.group import GroupRepository 11 | from telegram.error import BadRequest, Unauthorized 12 | 13 | loop = asyncio.get_event_loop() 14 | 15 | @decorators.owner.init 16 | def init(update, context): 17 | msg = update.message.text[2:].strip() 18 | rows = CommunityRepository().getAll() 19 | for a in rows: 20 | id_groups = a['tg_group_id'] 21 | try: 22 | if msg != "": 23 | loop.run_until_complete(messageWithAsyncById(update,context,id_groups,2,msg)) 24 | else: 25 | message(update,context,"You cannot send an empty message!") 26 | except (BadRequest,Unauthorized): 27 | category = a['type'] 28 | message(update,context,Strings.ERROR_HANDLING.format(id_groups,category)) 29 | 30 | @decorators.owner.init 31 | def global_broadcast(update, context): 32 | msg = update.message.text[3:].strip() 33 | rows = GroupRepository().getAll() 34 | for a in rows: 35 | id_groups = a['id_group'] 36 | try: 37 | if msg != "": 38 | loop.run_until_complete(messageWithAsyncById(update,context,id_groups,2,msg)) 39 | else: 40 | message(update,context,"You cannot send an empty message!") 41 | except (BadRequest,Unauthorized): 42 | message(update,context,Strings.ERROR_HANDLING.format(id_groups)) -------------------------------------------------------------------------------- /core/commands/owner/exit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | import time 4 | 5 | # Copyright SquirrelNetwork 6 | from config import Config 7 | from core import decorators 8 | from core.utilities.message import message 9 | from core.handlers.logs import sys_loggers 10 | from core.utilities.functions import chat_object 11 | from core.utilities.message import ApiGroupRemove 12 | #from core.database.repository.group import GroupRepository 13 | 14 | #TODO NEED FIX DELETE GROUP IN DATABASE 15 | 16 | @decorators.owner.init 17 | def init(update, context): 18 | bot = context.bot 19 | chat = chat_object(update) 20 | #GroupRepository.remove(chat.id) 21 | bot.leaveChat(update.message.chat_id) 22 | message(update, context, "#Log the bot has left the chat {}\nby operator {}".format(chat.id,update.message.from_user.id), 'HTML', 'messageid', Config.DEFAULT_LOG_CHANNEL, None) 23 | formatter = "Il bot è uscito dalla chat {} e il comando è stato eseguito da: {}".format(chat.id,update.message.from_user.id) 24 | sys_loggers("[BOT_EXIT_LOGS]",formatter,False,False,True) 25 | 26 | @decorators.owner.init 27 | def remote_exit(update,context): 28 | try: 29 | text = update.message.text 30 | input_user_id = text[6:].strip().split(" ", 1) 31 | chatid = input_user_id[0] 32 | message(update,context,"The bot remotely exited the following group: {}".format(chatid)) 33 | time.sleep(1) 34 | ApiGroupRemove(chatid) 35 | except Exception as e: 36 | print(e) -------------------------------------------------------------------------------- /core/commands/owner/export_invite_link.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core import decorators 6 | from core.utilities.functions import chat_object 7 | from core.utilities.message import message 8 | 9 | @decorators.owner.init 10 | @decorators.delete.init 11 | def init(update, context): 12 | bot = context.bot 13 | chat = chat_object(update) 14 | link = bot.export_chat_invite_link(chat.id) 15 | message(update, context, "An invitation link was generated for the chat {}\nThe invitation was sent in private".format(chat.title)) 16 | message(update, context, "Chat: {}\nInvite Link: {}".format(chat.title,link), 'HTML', 'private') 17 | 18 | @decorators.owner.init 19 | @decorators.delete.init 20 | def manual_export(update,context): 21 | bot = context.bot 22 | chat = update.message.text[8:].strip() 23 | print(chat) 24 | link = bot.export_chat_invite_link(chat) 25 | message(update, context, "Invite Link: {}".format(link), 'HTML', 'private') -------------------------------------------------------------------------------- /core/commands/owner/list_community.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core import decorators 6 | from core.database.repository.community import CommunityRepository 7 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup 8 | from core.utilities.menu import build_menu 9 | 10 | @decorators.owner.init 11 | def groups(update,context): 12 | bot = context.bot 13 | chat = update.effective_chat.id 14 | list_buttons = [] 15 | rows = CommunityRepository().getCommunityGroups() 16 | for link in rows: 17 | list_buttons.append(InlineKeyboardButton(text=link['tg_group_name'], url=link['tg_group_link'])) 18 | menu = build_menu(list_buttons,2) 19 | main_text = "=== 🐿[SN] Squirrel Network Official 🐿===\nTo participate in the Network contact:\n@TheLonelyAdventurer\n@SteelManITA\n@BluLupo" 20 | bot.send_message(chat,text=main_text,reply_markup=InlineKeyboardMarkup(menu), parse_mode="HTML") 21 | 22 | @decorators.owner.init 23 | def channels(update,context): 24 | bot = context.bot 25 | chat = update.effective_chat.id 26 | list_buttons = [] 27 | rows = CommunityRepository().getCommunityChannels() 28 | for link in rows: 29 | list_buttons.append(InlineKeyboardButton(text=link['tg_group_name'], url=link['tg_group_link'])) 30 | menu = build_menu(list_buttons,2) 31 | main_text = "=== 🐿[SN] Squirrel Network Official 🐿===\nTo participate in the Network contact:\n@TheLonelyAdventurer\n@SteelManITA\n@BluLupo" 32 | bot.send_message(chat,text=main_text,reply_markup=InlineKeyboardMarkup(menu), parse_mode="HTML") -------------------------------------------------------------------------------- /core/commands/owner/server_info.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | import psutil, datetime, platform 6 | from core import decorators 7 | from core.utilities.message import message 8 | from core.handlers.logs import sys_loggers 9 | 10 | NAME_SERVER = "NAOS" 11 | 12 | @decorators.owner.init 13 | @decorators.delete.init 14 | def init(update,context): 15 | msg = system_status() 16 | message(update,context,msg) 17 | formatter = "Eseguito da: {}".format(update.message.from_user.id) 18 | sys_loggers("[SERVER_INFO_LOGS]",formatter,False,False,True) 19 | 20 | def get_size(bytes, suffix="B"): 21 | """ 22 | Scale bytes to its proper format 23 | e.g: 24 | 1253656 => '1.20MB' 25 | 1253656678 => '1.17GB' 26 | """ 27 | factor = 1024 28 | for unit in ["", "K", "M", "G", "T", "P"]: 29 | if bytes < factor: 30 | return f"{bytes:.2f}{unit}{suffix}" 31 | bytes /= factor 32 | 33 | def system_status(): 34 | cpu_percent = psutil.cpu_percent() 35 | memory_percent = psutil.virtual_memory()[2] 36 | svmem = psutil.virtual_memory() 37 | boot_time = datetime.datetime.fromtimestamp(psutil.boot_time()) 38 | partitions = psutil.disk_partitions() 39 | uname = platform.uname() 40 | cpufreq = psutil.cpu_freq() 41 | net_io = psutil.net_io_counters() 42 | running_since = boot_time.strftime("%A %d. %B %Y") 43 | response = "{} Server Status:\n\n".format(NAME_SERVER) 44 | response += "⚙️ ==== SYSTEM INFO ==== ⚙️\n" 45 | response += "System: {}\n".format(uname.system) 46 | response +="Node Name: {}\n".format(uname.node) 47 | response +="Release: {}\n".format(uname.release) 48 | response +="Version: {}\n".format(uname.version) 49 | response +="Machine: {}\n\n".format(uname.machine) 50 | response += "⚙️ ==== CPU INFO ==== ⚙️\n" 51 | response += "Current CPU utilization is: {}%\n".format(cpu_percent) 52 | response += "Current Frequency: {}Mhz\n".format(cpufreq.current) 53 | response += "Physical cores: {}\n".format(psutil.cpu_count(logical=False)) 54 | response += "Total cores: {}\n\n".format(psutil.cpu_count(logical=True)) 55 | response += "⚙️ ==== DISK INFO ==== ⚙️\n" 56 | for partition in partitions: 57 | try: 58 | partition_usage = psutil.disk_usage(partition.mountpoint) 59 | except PermissionError: 60 | continue 61 | response += "Total Size: {}\n".format(get_size(partition_usage.total)) 62 | response += "Used: {}\n".format(get_size(partition_usage.used)) 63 | response += "Free: {}\n".format(get_size(partition_usage.free)) 64 | response += "Current Disk_percent is: {}%\n\n".format(partition_usage.percent) 65 | response += "⚙️ ==== MEMORY INFO ==== ⚙️ \n" 66 | response += "Current memory utilization: {}%\n".format(memory_percent) 67 | response += "Total: {}\n\n".format(get_size(svmem.total)) 68 | response += "⚙️ ==== NETWORK INFO ==== ⚙️ \n" 69 | response += "Total Bytes Sent: {}\n".format(get_size(net_io.bytes_sent)) 70 | response += "Total Bytes Received: {}\n".format(get_size(net_io.bytes_recv)) 71 | response += "It's running since {}".format(running_since) 72 | return response -------------------------------------------------------------------------------- /core/commands/owner/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | from core import decorators 7 | 8 | @decorators.owner.init 9 | def init(update,context): 10 | bot = context.bot 11 | chat = update.effective_chat.id 12 | thread_id = update.effective_message.message_thread_id 13 | text = "Test" 14 | bot.send_message(chat, text, parse_mode='HTML',message_thread_id=thread_id) -------------------------------------------------------------------------------- /core/commands/owner/whitelist.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core import decorators 6 | from core.utilities.message import message 7 | from core.database.repository.superban import SuperbanRepository 8 | from core.utilities.functions import user_reply_object 9 | from core.utilities.menu import build_menu 10 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup 11 | 12 | @decorators.owner.init 13 | @decorators.delete.init 14 | def init(update,context): 15 | if update.message.reply_to_message: 16 | user = user_reply_object(update) 17 | row = SuperbanRepository().getWhitelistById(user.id) 18 | get_superban = SuperbanRepository().getById(user.id) 19 | if get_superban: 20 | buttons = [] 21 | buttons.append(InlineKeyboardButton('Remove Superban', callback_data='removeBL')) 22 | buttons.append(InlineKeyboardButton('Close', callback_data='closed')) 23 | menu = build_menu(buttons,2) 24 | msg = "Attention the user is blacklisted! do you want to remove it?" 25 | update.message.reply_to_message.reply_text(msg, reply_markup=InlineKeyboardMarkup(menu),parse_mode='HTML') 26 | else: 27 | if row: 28 | message(update, context, "You have already whitelisted this user") 29 | else: 30 | user_username = "@"+user.username 31 | data = [(user.id, user_username)] 32 | SuperbanRepository().addWhitelist(data) 33 | message(update, context, "You have entered the user {} in the Whitelist".format(user_username)) 34 | else: 35 | message(update, context, "This message can only be used in response to a user") 36 | 37 | 38 | @decorators.owner.init 39 | def remove_blacklist(update,context): 40 | query = update.callback_query 41 | if query.data == 'removeBL': 42 | user_id = query.message.reply_to_message.from_user.id 43 | row = SuperbanRepository().getById(user_id) 44 | if row: 45 | data = [(user_id)] 46 | SuperbanRepository().remove(data) 47 | msg = "I removed the superban to user {}".format(user_id) 48 | query.edit_message_text(msg,parse_mode='HTML') 49 | else: 50 | query.edit_message_text("Attention this user not super banned!!!",parse_mode='HTML') 51 | if query.data == 'closed': 52 | query.edit_message_text("You have closed the Menu", parse_mode='HTML') -------------------------------------------------------------------------------- /core/commands/public/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | """Import Files""" 7 | __all__ = ["eggs","help","io","kickme","report","rules","source","staff","start","user_search"] 8 | 9 | from core.commands.public import * -------------------------------------------------------------------------------- /core/commands/public/eggs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | """ 7 | List of Easter Eggs 8 | """ 9 | from core import decorators 10 | from core.utilities.message import message 11 | 12 | @decorators.public.init 13 | @decorators.delete.init 14 | def egg_lost(update,context): 15 | message(update, context, "4 8 15 16 23 42") 16 | 17 | @decorators.public.init 18 | def egg_gh(update,context): 19 | if str(update.effective_message.text).lower().startswith(".fiko"): 20 | msg = "I'm not GroupHelp! If you want to know who they are type /source" 21 | animation = "https://i.imgur.com/LP23P90.gif" 22 | message(update,context,msg,type='animation',img=animation) 23 | 24 | @decorators.public.init 25 | def nanachi(update,context): 26 | if str(update.effective_message.text).lower().startswith("nanachi"): 27 | msg = "Naaaa~~ 🐾" 28 | animation = "https://i.imgur.com/P9HXqM8.mp4" 29 | message(update,context,msg,type='animation',img=animation) -------------------------------------------------------------------------------- /core/commands/public/help.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core.utilities.menu import build_menu 6 | from languages.getLang import languages 7 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup 8 | 9 | def init(update,context): 10 | bot = context.bot 11 | chat = update.effective_message.chat_id 12 | languages(update,context) 13 | msg = languages.helps.format("@"+bot.username) 14 | buttons = [] 15 | buttons.append(InlineKeyboardButton("Commands List", url='https://github.com/Squirrel-Network/nebula8/wiki/Command-List')) 16 | buttons.append(InlineKeyboardButton("Source", url='https://github.com/Squirrel-Network/nebula8')) 17 | buttons.append(InlineKeyboardButton("Logs Channel", url='https://t.me/nebulalogs')) 18 | buttons.append(InlineKeyboardButton("News Channel", url='https://t.me/nebulanewsbot')) 19 | buttons.append(InlineKeyboardButton("BlackList Search", url='https://squirrel-network.online/knowhere')) 20 | buttons.append(InlineKeyboardButton("Official API Docs", url='https://api.nebula.squirrel-network.online/apidocs')) 21 | buttons.append(InlineKeyboardButton("Network SN", url='https://t.me/squirrelnetwork')) 22 | menu = build_menu(buttons,3) 23 | bot.send_message(chat,msg,reply_markup=InlineKeyboardMarkup(menu)) -------------------------------------------------------------------------------- /core/commands/public/io.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core import decorators 6 | from core.utilities.message import message 7 | from core.utilities.functions import user_object 8 | from core.database.repository.superban import SuperbanRepository 9 | 10 | @decorators.private.init 11 | @decorators.delete.init 12 | def init(update,context): 13 | user = user_object(update) 14 | nickname = "@"+ user.username 15 | superban = SuperbanRepository().getById(user.id) 16 | if superban: 17 | msg = "User id: {}\nNickname: {}\nBlacklist: ✅".format(user.id, nickname or user.first_name) 18 | else: 19 | msg = "User id: {}\nNickname: {}\nBlacklist: ❌".format(user.id, nickname or user.first_name) 20 | message(update,context,msg) -------------------------------------------------------------------------------- /core/commands/public/kickme.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | from core import decorators 7 | from core.utilities.message import message 8 | from core.utilities.functions import kick_user_by_id, user_object 9 | 10 | @decorators.delete.init 11 | def init(update,context): 12 | user = user_object(update) 13 | img = 'https://i.imgur.com/CKU9Y75.png' 14 | kick_user_by_id(update, context, user.id) 15 | message(update, context, 'You kicked yourself [{}]\nWe only used 15 lines of code to make a free feature, not paid\nPut a stars to our repository => /source'.format(user.id), 'HTML', 'photo', None, img) -------------------------------------------------------------------------------- /core/commands/public/report.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core import decorators 6 | from languages.getLang import languages 7 | from core.utilities.strings import Strings 8 | from core.utilities.message import message 9 | from core.handlers.logs import telegram_loggers 10 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup 11 | from core.utilities.menu import build_menu 12 | 13 | 14 | @decorators.public.init 15 | def init(update,context): 16 | bot = context.bot 17 | staff_group_id = -1001267698171 18 | buttons = [] 19 | buttons.append(InlineKeyboardButton('Risolto✅', callback_data='resolved')) 20 | menu = build_menu(buttons,2) 21 | if update.effective_message.forward_date is not None: 22 | return 23 | 24 | chat = update.effective_chat 25 | languages(update,context) 26 | if str(update.effective_message.text).lower().startswith("@admin") or str(update.effective_message.text).lower().startswith("/report"): 27 | if update.effective_message.reply_to_message: 28 | msg = update.effective_message.reply_to_message 29 | format_link = "https://t.me/c/{}/{}".format(str(chat.id)[3:],msg.message_id) 30 | format_message = Strings.REPORT_MSG.format(chat.id,chat.title,msg.text,format_link) 31 | message(update, context, languages.report_msg, 'HTML', 'reply', None, None) 32 | telegram_loggers(update,context,format_message) 33 | bot.send_message(staff_group_id,format_message, reply_markup=InlineKeyboardMarkup(menu),parse_mode='HTML') 34 | else: 35 | msg_id = update.effective_message.message_id 36 | user_id = update.message.from_user.id 37 | user_first = update.message.from_user.first_name 38 | format_link = "https://t.me/c/{}/{}".format(str(chat.id)[3:],msg_id) 39 | format_message = '#Report\nUser: {}\nGroup Id: [{}]\nGroup Title: {}\nLink: {}'.format(user_id,user_first,str(chat.id)[3:],chat.title,format_link) 40 | message(update, context, languages.report_msg, 'HTML', 'reply', None, None) 41 | telegram_loggers(update,context,format_message) 42 | bot.send_message(staff_group_id,format_message, reply_markup=InlineKeyboardMarkup(menu),parse_mode='HTML') 43 | 44 | @decorators.admin.user_admin 45 | def update_resolve(update,context): 46 | query = update.callback_query 47 | var_message = query.message.text 48 | query.edit_message_text(text="{}\nRisolto da: @{username}" 49 | .format(var_message,username=str(update.effective_user.username)),parse_mode='HTML') -------------------------------------------------------------------------------- /core/commands/public/rules.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core import decorators 6 | from core.utilities.menu import build_menu 7 | from languages.getLang import languages 8 | from core.database.repository.group import GroupRepository 9 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup 10 | 11 | @decorators.public.init 12 | @decorators.delete.init 13 | def init(update, context): 14 | bot = context.bot 15 | languages(update,context) 16 | chat = update.effective_message.chat_id 17 | chat_title = update.message.chat.title 18 | list_buttons = [] 19 | list_buttons.append(InlineKeyboardButton(languages.rules_button, callback_data='openRules')) 20 | menu = build_menu(list_buttons,1) 21 | bot.send_message(chat,languages.rules_main.format(chat_title,chat),reply_markup=InlineKeyboardMarkup(menu),parse_mode='HTML') 22 | 23 | 24 | def update_rules(update,context): 25 | query = update.callback_query 26 | if query.data == 'openRules': 27 | languages(update,context) 28 | chat = update.effective_message.chat_id 29 | row = GroupRepository().getById([chat]) 30 | query.edit_message_text(languages.rules.format(row['rules_text']),parse_mode='HTML') -------------------------------------------------------------------------------- /core/commands/public/source.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from config import Config 6 | from core import decorators 7 | from core.utilities.message import message 8 | from core.utilities.functions import bot_object 9 | from core.utilities.strings import Strings 10 | 11 | @decorators.delete.init 12 | def init(update,context): 13 | bot = bot_object(update,context) 14 | version = Config.VERSION 15 | version_name = Config.VERSION_NAME 16 | repo = Config.REPO 17 | format_message = Strings.SOURCE.format("@"+bot.username,version,version_name,repo) 18 | message(update,context,format_message) -------------------------------------------------------------------------------- /core/commands/public/staff.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | from core import decorators 7 | from telegram.utils.helpers import mention_markdown 8 | 9 | @decorators.public.init 10 | @decorators.delete.init 11 | def init(update,context): 12 | bot = context.bot 13 | administrators = update.effective_chat.get_administrators() 14 | chat = update.effective_chat.id 15 | string = "Group Staff:\n" 16 | for admin in administrators: 17 | user = admin.user 18 | user_first = user.first_name 19 | string += "👮 {}\n".format(mention_markdown(user.id, user_first, version=2)) 20 | bot.send_message(chat,string,parse_mode='MarkdownV2') -------------------------------------------------------------------------------- /core/commands/public/start.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core import decorators 6 | from languages.getLang import languages 7 | from core.utilities.message import message 8 | from core.utilities.functions import bot_object, user_object, chat_object 9 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup 10 | from core.utilities.menu import build_menu 11 | 12 | @decorators.private.init 13 | @decorators.delete.init 14 | def init(update, context): 15 | bot = context.bot 16 | languages(update,context) 17 | chat = update.effective_message.chat_id 18 | get_bot = bot_object(update,context) 19 | user = user_object(update) 20 | get_user_lang = user.language_code 21 | if get_user_lang == 'it': 22 | list_buttons = [] 23 | list_buttons.append(InlineKeyboardButton('Commands', url='https://github.com/Squirrel-Network/nebula8/wiki/Command-List')) 24 | list_buttons.append(InlineKeyboardButton('Dashboard', url='https://nebula.squirrel-network.online')) 25 | list_buttons.append(InlineKeyboardButton('Api', url='https://api.nebula.squirrel-network.online')) 26 | list_buttons.append(InlineKeyboardButton('Knowhere', url='https://squirrel-network.online/knowhere')) 27 | list_buttons.append(InlineKeyboardButton('News', url='https://t.me/nebulanewsbot')) 28 | list_buttons.append(InlineKeyboardButton('Logs', url='https://t.me/nebulalogs')) 29 | list_buttons.append(InlineKeyboardButton('SquirrelNetwork', url='https://t.me/squirrelnetwork')) 30 | list_buttons.append(InlineKeyboardButton('👥 Add me to a Group', url='https://t.me/thenebulabot?startgroup=start')) 31 | menu = build_menu(list_buttons, 3) 32 | text = "🤖 Ciao io mi chiamo {}\n\nSono un bot ricco di funzionalità per la gestione dei gruppi\n"\ 33 | "Possiedo una Blacklist enorme ho un antispam, un antiflood e molto altro ancora!!\n\n"\ 34 | "ℹ Se hai bisogno di aiuto: [/help]\n\n\n🔵 Sapevi che sono OpenSource e cerco sempre aiuto? [/source]".format("@"+get_bot.username) 35 | bot.send_message(chat, text, reply_markup=InlineKeyboardMarkup(menu),parse_mode='HTML') 36 | else: 37 | message(update,context,languages.start.format("@"+get_bot.username)) -------------------------------------------------------------------------------- /core/commands/public/user_search.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core import decorators 6 | from core.utilities.functions import user_reply_object 7 | from core.utilities.message import message 8 | from core.database.repository.user import UserRepository 9 | 10 | @decorators.admin.user_admin 11 | @decorators.delete.init 12 | def init(update,context): 13 | text = update.message.text 14 | if update.message.reply_to_message: 15 | user = user_reply_object(update) 16 | row = UserRepository().getById(user.id) 17 | if row: 18 | message(update, context, text="The user search returned the following results:\nTelegram Id: {}\nUsername: {}\nLast Update: {} [UTC]" 19 | .format( 20 | row['tg_id'], 21 | row['tg_username'], 22 | row['updated_at'].isoformat() 23 | )) 24 | else: 25 | message(update,context, text="The user is not present in the database") 26 | else: 27 | input_user_id = text[8:].strip().split(" ", 1) 28 | user_id = input_user_id[0] 29 | if user_id != "": 30 | row = UserRepository().getByUsername(user_id) 31 | if row: 32 | message(update, context, text="The user search returned the following results:\nTelegram Id: {}\nUsername: {}\nLast Update: {} [UTC]" 33 | .format( 34 | row['tg_id'], 35 | row['tg_username'], 36 | row['updated_at'].isoformat() 37 | )) 38 | else: 39 | message(update,context, text="The user is not present in the database") 40 | else: 41 | message(update,context,"Attention the user id you entered does not exist!") -------------------------------------------------------------------------------- /core/database/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ["repository","db_connect","migrations","redis_connect"] 2 | 3 | from core.database import * -------------------------------------------------------------------------------- /core/database/db_connect.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | import pymysql 6 | from pymysql import OperationalError 7 | from config import Config 8 | from loguru import logger 9 | from sqlalchemy import create_engine 10 | from core.database.migrations import Migrations 11 | 12 | """ 13 | This class handles database connection and inbound queries 14 | """ 15 | class Connection: 16 | def __init__(self): 17 | try: 18 | self.con = pymysql.connect( 19 | host = Config.HOST, 20 | port = Config.PORT, 21 | user = Config.USER, 22 | password = Config.PASSWORD, 23 | db = Config.DBNAME, 24 | autocommit=True, 25 | charset = 'utf8mb4', 26 | cursorclass = pymysql.cursors.DictCursor 27 | ) 28 | self.cur = self.con.cursor() 29 | except OperationalError as e: 30 | logger.error(e) 31 | args = e.args 32 | self.con = pymysql.connect( 33 | host = Config.HOST, 34 | port = Config.PORT, 35 | user = Config.USER, 36 | password = Config.PASSWORD, 37 | autocommit=True, 38 | charset = 'utf8mb4', 39 | cursorclass = pymysql.cursors.DictCursor 40 | ) 41 | #Pseudo Migrations 42 | if args[0] == 1049: 43 | def _execute(self,sql): 44 | self.cur = self.con.cursor() 45 | query = self.cur 46 | q = query.execute(sql) 47 | return q 48 | _execute(self,'CREATE DATABASE IF NOT EXISTS nebula') 49 | _execute(self,Migrations.OWNERS) 50 | _execute(self,Migrations.USERS) 51 | _execute(self,Migrations.GROUPS) 52 | _execute(self,Migrations.COMMUNITY) 53 | _execute(self,Migrations.GROUPS_BADWORDS) 54 | _execute(self,Migrations.GROUP_USERS) 55 | _execute(self,Migrations.NEBULA_UPDATES) 56 | logger.info('I created the nebula database and Tables') 57 | quit(1) 58 | 59 | def _select(self,sql,args=None): 60 | self.cur.execute(sql,args) 61 | self.sel = self.cur.fetchone() 62 | self.cur.close() 63 | self.con.close() 64 | return self.sel 65 | 66 | def _selectAll(self,sql,args=None): 67 | self.cur.execute(sql,args) 68 | self.sel = self.cur.fetchall() 69 | self.cur.close() 70 | self.con.close() 71 | return self.sel 72 | 73 | def _insert(self,sql,args=None): 74 | self.ins = self.cur.executemany(sql,args) 75 | return self.ins 76 | 77 | def _single_insert(self,sql,args=None): 78 | self.sins = self.cur.execute(sql,args) 79 | return self.sins 80 | 81 | def _dict_insert(self, sql, dictionary): 82 | self.dins = self.cur.execute(sql, list(dictionary.values())) 83 | return self.dins 84 | 85 | def _update(self,sql, args=None): 86 | self.upd = self.cur.executemany(sql,args) 87 | return self.upd 88 | 89 | def _delete(self, sql, args=None): 90 | self.delete = self.cur.executemany(sql,args) 91 | return self.delete 92 | 93 | 94 | class SqlAlchemyConnection: 95 | def __init__(self): 96 | self.server = '{}:{}'.format(Config.HOST,Config.PORT) 97 | self.db = Config.DBNAME 98 | self.login = Config.USER 99 | self.passwd = Config.PASSWORD 100 | self.engine_str = 'mysql+pymysql://{}:{}@{}/{}'.format(self.login, self.passwd, self.server, self.db) 101 | self.engine = create_engine(self.engine_str) -------------------------------------------------------------------------------- /core/database/migrations.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | class Migrations(object): 7 | USERS = 'CREATE TABLE IF NOT EXISTS nebula.users (id int(11) NOT NULL,tg_id varchar(50) NOT NULL,tg_username varchar(50) NOT NULL,created_at datetime NOT NULL,updated_at datetime NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4' 8 | OWNERS = 'CREATE TABLE IF NOT EXISTS nebula.owner_list (id int(11) NOT NULL,tg_id varchar(255) NOT NULL,tg_username varchar(255) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4' 9 | GROUPS = "CREATE TABLE IF NOT EXISTS nebula.groups (" \ 10 | "id int(11) NOT NULL AUTO_INCREMENT," \ 11 | "id_group varchar(50) NOT NULL," \ 12 | "group_name varchar(255) NOT NULL," \ 13 | "welcome_text text NOT NULL," \ 14 | "welcome_buttons longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '{}'," \ 15 | "rules_text text NOT NULL," \ 16 | "community tinyint(1) NOT NULL DEFAULT 0," \ 17 | "languages varchar(20) DEFAULT 'EN'," \ 18 | "set_welcome tinyint(2) NOT NULL DEFAULT 1," \ 19 | "max_warn int(11) NOT NULL DEFAULT 3," \ 20 | "set_silence tinyint(2) NOT NULL DEFAULT 0," \ 21 | "exe_filter tinyint(1) NOT NULL DEFAULT 0," \ 22 | "block_new_member tinyint(1) NOT NULL DEFAULT 0," \ 23 | "set_arabic_filter tinyint(1) NOT NULL DEFAULT 1," \ 24 | "set_cirillic_filter tinyint(1) NOT NULL DEFAULT 1," \ 25 | "set_chinese_filter tinyint(1) NOT NULL DEFAULT 1," \ 26 | "set_user_profile_picture tinyint(1) NOT NULL DEFAULT 0," \ 27 | "gif_filter tinyint(1) NOT NULL DEFAULT 0," \ 28 | "set_cas_ban tinyint(1) NOT NULL DEFAULT 1," \ 29 | "type_no_username int(1) NOT NULL DEFAULT 1," \ 30 | "log_channel varchar(50) NOT NULL DEFAULT '-1001359708474'," \ 31 | "group_photo varchar(255) NOT NULL DEFAULT 'https://naos.hersel.it/group_photo/default.jpg'," \ 32 | "total_users int(50) NOT NULL DEFAULT 0," \ 33 | "zip_filter tinyint(1) NOT NULL DEFAULT 0," \ 34 | "targz_filter tinyint(1) NOT NULL DEFAULT 0," \ 35 | "jpg_filter tinyint(1) NOT NULL DEFAULT 0," \ 36 | "docx_filter tinyint(1) NOT NULL DEFAULT 0," \ 37 | "apk_filter tinyint(1) NOT NULL DEFAULT 0," \ 38 | "zoophile_filter tinyint(1) NOT NULL DEFAULT 1," \ 39 | "sender_chat_block tinyint(1) NOT NULL DEFAULT 1," \ 40 | "spoiler_block tinyint(1) NOT NULL DEFAULT 0," \ 41 | "set_no_vocal tinyint(1) NOT NULL DEFAULT 0," \ 42 | "set_antiflood tinyint(1) NOT NULL DEFAULT 1," \ 43 | "ban_message text NOT NULL DEFAULT '{mention} has been banned from: {chat}'",\ 44 | "PRIMARY KEY (id)," \ 45 | "UNIQUE KEY group_id (id_group)" \ 46 | ") ENGINE=InnoDB AUTO_INCREMENT=141 DEFAULT CHARSET=utf8mb4".format('{ "buttons": [{"id": 0,"title": "Bot Logs","url": "https://t.me/nebulalogs"}]}') 47 | COMMUNITY = "CREATE TABLE IF NOT EXISTS nebula.community (id int(11) NOT NULL,tg_group_name varchar(50) DEFAULT NULL,tg_group_id varchar(50) DEFAULT NULL,tg_group_link varchar(50) DEFAULT NULL,language varchar(50) NOT NULL DEFAULT 'IT',type varchar(50) NOT NULL DEFAULT 'supergroup') ENGINE=InnoDB DEFAULT CHARSET=utf8mb4" 48 | GROUPS_BADWORDS = "CREATE TABLE IF NOT EXISTS nebula.groups_badwords (id int(11) NOT NULL,word varchar(255) NOT NULL,tg_group_id varchar(255) NOT NULL,user_score bigint(20) NOT NULL DEFAULT 0) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4" 49 | GROUP_USERS = "CREATE TABLE IF NOT EXISTS nebula.group_users (id int(11) NOT NULL,tg_id varchar(50) DEFAULT NULL,tg_group_id varchar(50) DEFAULT NULL,warn_count int(11) NOT NULL DEFAULT 0) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4" 50 | NEBULA_UPDATES = "CREATE TABLE IF NOT EXISTS nebula.nebula_updates (id int(11) NOT NULL AUTO_INCREMENT,update_id varchar(255) NOT NULL,tg_group_id varchar(255) NOT NULL,tg_user_id varchar(255) NOT NULL,date datetime(6) NOT NULL,PRIMARY KEY (id),UNIQUE KEY update_index (update_id)) ENGINE=InnoDB AUTO_INCREMENT=184434 DEFAULT CHARSET=utf8mb4" -------------------------------------------------------------------------------- /core/database/redis_connect.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | import redis 7 | from config import Config 8 | from loguru import logger 9 | 10 | class RedisConnect(): 11 | def __init__(self): 12 | try: 13 | self.con = redis.Redis( 14 | host=Config.RD_HOST, 15 | port=Config.RD_PORT, 16 | password=Config.RD_PASSWORD, 17 | db=Config.RD_DB 18 | ) 19 | except Exception as e: 20 | logger.error(e) 21 | 22 | def hdel(self,key,field): 23 | self.con.hdel(key,field) 24 | 25 | def hexists(self,key,field): 26 | return self.con.hexists(key,field) 27 | 28 | def hget(self,key,field): 29 | return self.con.hget(key,field) 30 | 31 | def hset(self,key,field,value): 32 | self.con.hset(key,field,value) -------------------------------------------------------------------------------- /core/database/repository/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = [ 2 | "community", 3 | "dashboard", 4 | "group", 5 | "user", 6 | "group_language", 7 | "superban" 8 | ] 9 | 10 | from core.database.repository import * -------------------------------------------------------------------------------- /core/database/repository/community.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core.database.db_connect import Connection 6 | from pypika import Query, Table 7 | 8 | community = Table("community") 9 | 10 | class CommunityRepository(Connection): 11 | def getAll(self): 12 | query = Query.from_(community).select("*") 13 | q = query.get_sql(quote_char=None) 14 | return self._selectAll(q) 15 | 16 | def getById(self, args=None): 17 | query = Query.from_(community).select("*").where(community.tg_group_id == '%s') 18 | q = query.get_sql(quote_char=None) 19 | 20 | return self._select(q, args) 21 | 22 | def update(self, args=None): 23 | q = "UPDATE community SET tg_group_name = %s WHERE tg_group_id = %s" 24 | return self._update(q, args) 25 | 26 | def add(self, args=None): 27 | q = "INSERT INTO community(tg_group_name, tg_group_id, tg_group_link, language, type) VALUES (%s,%s,%s,%s,%s)" 28 | return self._insert(q, args) 29 | 30 | def getCommunityGroups(self): 31 | 32 | q = "SELECT * FROM community WHERE type = 'supergroup'" 33 | 34 | return self._selectAll(q) 35 | 36 | def getCommunityChannels(self): 37 | 38 | q = "SELECT * FROM community WHERE type = 'channel'" 39 | 40 | return self._selectAll(q) -------------------------------------------------------------------------------- /core/database/repository/dashboard.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core.database.db_connect import Connection 6 | from pypika import Query, Table 7 | 8 | 9 | dashboard = Table("nebula_dashboard") 10 | 11 | class DashboardRepository(Connection): 12 | 13 | def getById(self, args=None): 14 | query = Query.from_(dashboard).select("*").where(dashboard.tg_id == "%s") 15 | q = query.get_sql(quote_char=None) 16 | 17 | return self._select(q, args) 18 | 19 | def getByGroupId(self, args=None): 20 | query = Query.from_(dashboard).select("*").where(dashboard.tg_group_id == "%s") 21 | q = query.get_sql(quote_char=None) 22 | 23 | return self._select(q, args) 24 | 25 | def getByUsername(self, args=None): 26 | q = "SELECT * FROM nebula_dashboard WHERE tg_username = %s" 27 | 28 | return self._select(q, args) 29 | 30 | def getUserAndGroup(self, args=None): 31 | q = "SELECT * FROM nebula_dashboard WHERE tg_group_id = %s AND tg_id = %s" 32 | 33 | return self._select(q, args) 34 | 35 | def add(self, args=None): 36 | q = "INSERT INTO nebula_dashboard (tg_id, tg_username, tg_group_id, enable, role, created_at, updated_at) VALUES (%s,%s,%s,%s,%s,%s,%s)" 37 | return self._insert(q, args) 38 | 39 | def update(self, args=None): 40 | q = "UPDATE nebula_dashboard SET tg_username = %s, role = %s, updated_at = %s WHERE tg_id = %s AND tg_group_id = %s" 41 | return self._update(q, args) -------------------------------------------------------------------------------- /core/database/repository/group.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core.database.db_connect import Connection 6 | from pypika import Query, Table 7 | 8 | groups = Table("groups") 9 | whitelist_channels = Table("whitelist_channel") 10 | 11 | class GroupRepository(Connection): 12 | ###### Column constants of the table ###### 13 | SET_ID_GROUP = "id_group" 14 | SET_GROUP_NAME = "group_name" 15 | SET_WELCOME_TEXT = "welcome_text" 16 | SET_WELCOME_BUTTONS = "welcome_buttons" 17 | SET_RULES_TEXT = "rules_text" 18 | SET_COMMUNITY = "community" 19 | SET_LANGUAGE = "languages" 20 | SET_WELCOME = "set_welcome" 21 | SET_MAX_WARN = "max_warn" 22 | SET_SILENCE = "set_silence" 23 | EXE_FILTER = "exe_filter" 24 | SET_BLOCK_N_M = "block_new_member" 25 | SET_ARABIC = "set_arabic_filter" 26 | SET_CIRILLIC = "set_cirillic_filter" 27 | SET_CHINESE = "set_chinese_filter" 28 | SET_USER_PROFILE_PICT = "set_user_profile_picture" 29 | GIF_FILTER = "gif_filter" 30 | SET_CAS_BAN = "set_cas_ban" 31 | SET_TPNU = "type_no_username" 32 | SET_LOG_CHANNEL = "log_channel" 33 | SET_GROUP_PHOTO = "group_photo" 34 | SET_GROUP_MEMBERS_COUNT = "total_users" 35 | ZIP_FILTER = "zip_filter" 36 | TARGZ_FILTER = "targz_filter" 37 | JPG_FILTER = "jpg_filter" 38 | DOCX_FILTER = "docx_filter" 39 | APK_FILTER = "apk_filter" 40 | ZOOPHILE_FILTER = "zoophile_filter" 41 | SENDER_CHAT_BLOCK = "sender_chat_block" 42 | SPOILER_BLOCK = "spoiler_block" 43 | SET_NO_VOCAL = "set_no_vocal" 44 | SET_ANTIFLOOD = "set_antiflood" 45 | BAN_MESSAGE = "ban_message" 46 | CREATED_AT = "created_at" 47 | UPDATED_AT = "updated_at" 48 | SET_GH = "set_gh" 49 | 50 | def getById(self, args=None): 51 | query = Query.from_(groups).select("*").where(groups.id_group == '%s') 52 | q = query.get_sql(quote_char=None) 53 | 54 | return self._select(q, args) 55 | 56 | def getAllById(self, args=None): 57 | query = Query.from_(groups).select("*").where(groups.id_group == '%s') 58 | q = query.get_sql(quote_char=None) 59 | 60 | return self._selectAll(q, args) 61 | 62 | def getAll(self): 63 | query = Query.from_(groups).select("*") 64 | q = query.get_sql(quote_char=None) 65 | 66 | return self._selectAll(q) 67 | 68 | # Save group by Welcome 69 | def add_with_dict(self,dictionary): 70 | placeholders = ', '.join(['%s'] * len(dictionary)) 71 | columns = ', '.join(dictionary.keys()) 72 | sql = "INSERT INTO groups ( %s ) VALUES ( %s )" % (columns, placeholders) # pylint: disable-this-line-in-some-way 73 | return self._dict_insert(sql, dictionary) 74 | 75 | #Update welcome buttons 76 | def updateWelcomeButtonsByGroupId(self, group_id, button): 77 | query = Query.update(groups).set(groups.welcome_buttons, '%s').where(groups.id_group == '%s') 78 | query = query.get_sql(quote_char='`') 79 | query = query.replace("'", "") 80 | 81 | self._update(query, [(button, group_id)]) 82 | 83 | # I update the group id if the group changes from group to supergroup 84 | def update(self, args=None): 85 | q = "UPDATE groups SET id_group = %s WHERE id_group = %s" 86 | return self._update(q, args) 87 | 88 | # I insert the updates for the message count by group 89 | def insert_updates(self, args=None): 90 | q = "INSERT INTO nebula_updates (update_id, message_id, tg_group_id, tg_user_id, date) VALUES (%s,%s,%s,%s,%s)" 91 | return self._insert(q, args) 92 | 93 | # I collect the updates to know how many messages have been sent 94 | def getUpdatesByChatMonth(self, args=None): 95 | q = 'SELECT COUNT(*) AS counter FROM nebula_updates WHERE date BETWEEN DATE_SUB(NOW(), INTERVAL 31 DAY) AND NOW() AND tg_group_id = %s ORDER BY date DESC' 96 | 97 | return self._select(q, args) 98 | 99 | def getUpdatesByUserMonth(self, args=None): 100 | q = 'SELECT COUNT(*) AS counter FROM nebula_updates WHERE DATE BETWEEN DATE_SUB(NOW(), INTERVAL 30 DAY) AND NOW() AND tg_group_id = %s AND tg_user_id = %s ORDER BY DATE DESC' 101 | 102 | return self._select(q, args) 103 | 104 | def getAllUpdates(self): 105 | q = 'SELECT COUNT(*) AS counter FROM nebula_updates' 106 | 107 | return self._select(q) 108 | 109 | def change_group_photo(self, args=None): 110 | q = "INSERT INTO groups SET group_photo = %s WHERE id_group = %s" 111 | 112 | return self._insert(q, args) 113 | 114 | def get_group_badwords(self, args=None): 115 | q = "SELECT * FROM groups_badwords WHERE INSTR(%s, word) <> 0 AND tg_group_id = %s" 116 | 117 | return self._select(q, args) 118 | 119 | def get_antispam_logic(self, args=None): 120 | q = "SELECT logic FROM nebula_antispam WHERE INSTR(%s, logic) <> 0" 121 | 122 | return self._select(q, args) 123 | 124 | def get_badwords_group(self, args=None): 125 | q = "SELECT * FROM groups_badwords WHERE tg_group_id = %s" 126 | 127 | return self._selectAll(q, args) 128 | 129 | def insert_badword(self, args=None): 130 | q = "INSERT IGNORE INTO groups_badwords (word, tg_group_id) VALUES (%s,%s)" 131 | 132 | return self._insert(q, args) 133 | 134 | def insert_spam(self, args=None): 135 | q = "INSERT IGNORE INTO nebula_antispam (logic) VALUES (%s)" 136 | 137 | return self._single_insert(q, args) 138 | 139 | 140 | def remove(self, args=None): 141 | q = "DELETE FROM groups WHERE id_group = %s" 142 | return self._delete(q, args) 143 | 144 | def get_custom_handler(self, args=None): 145 | q = "SELECT answer FROM custom_handler WHERE question = %s AND chat_id = %s" 146 | 147 | return self._select(q, args) 148 | 149 | def insert_custom_handler(self, args=None): 150 | q = "INSERT INTO custom_handler (chat_id, question, answer) VALUES (%s,%s,%s)" 151 | 152 | return self._insert(q, args) 153 | 154 | def getTopActiveUsers(self, args=None): 155 | 156 | q = "SELECT COUNT(*) AS counter, u.tg_username, u.tg_id FROM nebula_updates nu INNER JOIN users u ON u.tg_id = nu.tg_user_id WHERE DATE BETWEEN DATE_SUB(NOW(), INTERVAL 30 DAY) AND NOW() AND nu.tg_group_id = %s GROUP BY nu.tg_user_id ORDER BY counter DESC LIMIT 10" 157 | 158 | return self._selectAll(q, args) 159 | 160 | def getTopInactiveUsers(self, args=None): 161 | 162 | q = "SELECT COUNT(*) AS counter, u.tg_username, u.tg_id FROM nebula_updates nu INNER JOIN users u ON u.tg_id = nu.tg_user_id WHERE DATE BETWEEN DATE_SUB(NOW(), INTERVAL 30 DAY) AND NOW() AND nu.tg_group_id = %s GROUP BY nu.tg_user_id ORDER BY counter ASC LIMIT 10" 163 | 164 | return self._selectAll(q, args) 165 | 166 | ########################## 167 | ##### GROUP SETTINGS ##### 168 | ########################## 169 | 170 | def set_block_entry(self, args=None): 171 | q = "UPDATE groups SET set_welcome = %s, block_new_member = %s WHERE id_group = %s" 172 | return self._update(q, args) 173 | 174 | def update_group_settings(self, record, args=None): 175 | q = "UPDATE groups SET @record = %s WHERE id_group = %s".replace('@record',record) 176 | return self._update(q, args) 177 | 178 | def job_nebula_updates(self, args=None): 179 | q = "DELETE FROM nebula_updates WHERE date < NOW() - INTERVAL 90 DAY" 180 | return self._delete(q, args) 181 | -------------------------------------------------------------------------------- /core/database/repository/group_language.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core.database.db_connect import Connection 6 | from pypika import Query, Table 7 | 8 | 9 | class GroupLanguageRepository(Connection): 10 | def getById(self, args=None): 11 | groups = Table("groups") 12 | query = Query.from_(groups).select(groups.languages).where(groups.id_group == '%s') 13 | q = query.get_sql(quote_char=None) 14 | 15 | return self._select(q, args) -------------------------------------------------------------------------------- /core/database/repository/superban.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core.database.db_connect import Connection 6 | from pypika import Query, Table 7 | 8 | superban = Table("superban_table") 9 | whitelist = Table("whitelist_table") 10 | group_blacklist = Table("groups_blacklist") 11 | 12 | class SuperbanRepository(Connection): 13 | def getById(self, args=None): 14 | query = Query.from_(superban).select("*").where(superban.user_id == '%s') 15 | q = query.get_sql(quote_char=None) 16 | 17 | return self._select(q, args) 18 | 19 | def getWhitelistById(self, args=None): 20 | query = Query.from_(whitelist).select("*").where(whitelist.tg_id == '%s') 21 | q = query.get_sql(quote_char=None) 22 | 23 | return self._select(q, args) 24 | 25 | def getGroupBlacklistById(self, args=None): 26 | query = Query.from_(group_blacklist).select("*").where(group_blacklist.tg_id_group == '%s') 27 | q = query.get_sql(quote_char=None) 28 | 29 | return self._select(q, args) 30 | 31 | def addWhitelist(self, args=None): 32 | q = "INSERT IGNORE INTO whitelist_table(tg_id, tg_username) VALUES (%s,%s)" 33 | return self._insert(q, args) 34 | 35 | def getAll(self, args=None): 36 | query = Query.from_(superban).select("user_id").where(superban.user_id == '%s') 37 | q = query.get_sql(quote_char=None) 38 | 39 | return self._selectAll(q, args) 40 | 41 | def add(self, args=None): 42 | q = "INSERT IGNORE INTO superban_table(user_id, user_first_name, motivation_text, user_date, id_operator, username_operator, first_name_operator) VALUES (%s,%s,%s,%s,%s,%s,%s)" 43 | return self._insert(q, args) 44 | 45 | def remove(self, args=None): 46 | q = "DELETE FROM superban_table WHERE user_id = %s" 47 | return self._delete(q, args) -------------------------------------------------------------------------------- /core/database/repository/user.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core.database.db_connect import Connection 6 | from pypika import Query, Table 7 | 8 | users = Table("users") 9 | owners = Table("owner_list") 10 | 11 | class UserRepository(Connection): 12 | def getById(self, args=None): 13 | query = Query.from_(users).select("*").where(users.tg_id == "%s") 14 | q = query.get_sql(quote_char=None) 15 | 16 | return self._select(q, args) 17 | 18 | def getByUsername(self, args=None): 19 | q = "SELECT * FROM users WHERE tg_username = %s" 20 | 21 | return self._select(q, args) 22 | 23 | def getUserByGroup(self, args=None): 24 | q = "SELECT u.tg_id,u.tg_username,gr.id_group,gu.warn_count, gr.max_warn, gr.group_name FROM users u INNER JOIN group_users gu ON gu.tg_id = u.tg_id INNER JOIN groups gr ON gu.tg_group_id = gr.id_group WHERE u.tg_id = %s AND gr.id_group = %s" 25 | return self._select(q, args) 26 | 27 | def getUserByGroups(self, args=None): 28 | q = "SELECT u.tg_id,u.tg_username,gr.id_group,gu.warn_count, gr.max_warn, gr.group_name FROM users u INNER JOIN group_users gu ON gu.tg_id = u.tg_id INNER JOIN groups gr ON gu.tg_group_id = gr.id_group WHERE u.tg_id = %s" 29 | return self._selectAll(q, args) 30 | 31 | def getAll(self, args=None): 32 | query = Query.from_(users).select("*").where(users.tg_id == "%s") 33 | q = query.get_sql(quote_char=None) 34 | 35 | return self._selectAll(q, args) 36 | 37 | def add(self, args=None): 38 | q = "INSERT IGNORE INTO users (tg_id, tg_username, created_at, updated_at) VALUES (%s,%s,%s,%s)" 39 | return self._insert(q, args) 40 | 41 | def add_owner(self, args=None): 42 | q = "INSERT IGNORE INTO owner_list (tg_id, tg_username) VALUES (%s,%s)" 43 | return self._insert(q, args) 44 | 45 | def remove_owner(self, args=None): 46 | q = "DELETE FROM owner_list WHERE tg_id = %s" 47 | return self._delete(q, args) 48 | 49 | def add_into_mtm(self, args=None): 50 | q = "INSERT IGNORE INTO group_users (tg_id, tg_group_id, warn_count, user_score) VALUES (%s,%s,%s,%s)" 51 | return self._insert(q, args) 52 | 53 | def update(self, args=None): 54 | q = "UPDATE users SET tg_username = %s, updated_at = %s WHERE tg_id = %s" 55 | return self._update(q, args) 56 | 57 | def delete_user(self, args=None): 58 | q = "DELETE FROM users WHERE tg_id = %s" 59 | return self._delete(q, args) 60 | 61 | def updateWarn(self, args=None): 62 | q = "UPDATE group_users SET warn_count = warn_count + 1 WHERE tg_id = %s AND tg_group_id = %s" 63 | return self._update(q, args) 64 | 65 | def downWarn(self, args=None): 66 | q = "UPDATE group_users SET warn_count = warn_count - 1 WHERE tg_id = %s AND tg_group_id = %s" 67 | return self._update(q, args) 68 | 69 | def removeWarn(self, args=None): 70 | q = "UPDATE group_users SET warn_count = 0 WHERE tg_id = %s AND tg_group_id = %s" 71 | return self._update(q, args) 72 | 73 | def getOwners(self): 74 | query = Query.from_(owners).select("*") 75 | q = query.get_sql(quote_char=None) 76 | 77 | return self._selectAll(q) 78 | 79 | def getOwnerById(self, args=None): 80 | query = Query.from_(owners).select("*").where(owners.tg_id == "%s") 81 | q = query.get_sql(quote_char=None) 82 | 83 | return self._select(q, args) -------------------------------------------------------------------------------- /core/decorators/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | """ 7 | Import Files 8 | """ 9 | __all__ = ["admin","bot","delete","owner","private","public"] 10 | 11 | from core.decorators import * -------------------------------------------------------------------------------- /core/decorators/admin.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from functools import wraps 6 | from core.decorators.owner import OWNER_LIST 7 | 8 | TITLES = ['creator', 'administrator'] 9 | 10 | def user_admin(func): 11 | @wraps(func) 12 | def wrapped(update, context): 13 | user_id = update.effective_user 14 | try: 15 | stat = context.bot.get_chat_member(update.message.chat_id, update.effective_user['id'])['status'] 16 | except: 17 | stat = context.bot.get_chat_member(update.callback_query.message.chat_id, update.callback_query.from_user['id'])['status'] 18 | if (user_id['id'] not in OWNER_LIST) and (stat not in TITLES): 19 | print("Unauthorized access denied for {}.".format(user_id['id'])) 20 | return 21 | return func(update, context) 22 | return wrapped -------------------------------------------------------------------------------- /core/decorators/bot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from functools import wraps 6 | from core.utilities.functions import bot_object 7 | 8 | def check_is_admin(func): 9 | @wraps(func) 10 | def wrapped(update, context): 11 | bot = bot_object(update, context) 12 | chat = update.effective_message.chat_id 13 | get_bot = bot.getChatMember(chat,bot.id) 14 | if get_bot.status == 'administrator': 15 | print("is_admin") 16 | else: 17 | update.effective_message.reply_text("I'm not admin!") 18 | return False 19 | return func(update, context) 20 | return wrapped 21 | 22 | def check_can_delete(func): 23 | @wraps(func) 24 | def wrapped(update, context): 25 | bot = bot_object(update, context) 26 | chat = update.effective_message.chat_id 27 | get_bot = bot.getChatMember(chat,bot.id) 28 | perm_delete = get_bot.can_delete_messages 29 | print(perm_delete) 30 | if perm_delete is not False or not None: 31 | print("can_delete") 32 | else: 33 | update.effective_message.reply_text("I can't delete messages here!\nMake sure I'm admin and can delete other user's messages.") 34 | return False 35 | return func(update, context) 36 | return wrapped -------------------------------------------------------------------------------- /core/decorators/delete.py: -------------------------------------------------------------------------------- 1 | from functools import wraps 2 | 3 | def init(func): 4 | @wraps(func) 5 | def wrapped(update, context): 6 | bot = context.bot 7 | if update.message.text is not None: 8 | if update.message.text.startswith("/"): 9 | bot.delete_message(update.effective_message.chat_id, update.message.message_id) 10 | else: 11 | print("AAA") 12 | return func(update, context) 13 | return wrapped -------------------------------------------------------------------------------- /core/decorators/owner.py: -------------------------------------------------------------------------------- 1 | from functools import wraps 2 | from core.utilities.functions import get_owner_list 3 | 4 | OWNER_LIST = get_owner_list() 5 | 6 | def init(func): 7 | @wraps(func) 8 | def wrapped(update, context): 9 | if update.effective_user is not None: 10 | user_id = update.effective_user.id 11 | if user_id not in OWNER_LIST: 12 | print("Unauthorized access denied for {}.".format(user_id)) 13 | return 14 | else: 15 | return False 16 | return func(update, context) 17 | return wrapped -------------------------------------------------------------------------------- /core/decorators/private.py: -------------------------------------------------------------------------------- 1 | def init(fn): 2 | def wrapper(*args,**kwargs): 3 | message = args[0].message 4 | if message.chat.type == 'private': 5 | return fn(*args,**kwargs) 6 | else: 7 | return False 8 | return wrapper -------------------------------------------------------------------------------- /core/decorators/public.py: -------------------------------------------------------------------------------- 1 | def init(fn): 2 | def wrapper(update,context): 3 | chat = update.effective_chat 4 | if chat.type == 'supergroup' or chat.type == 'group': 5 | return fn(update,context) 6 | else: 7 | return False 8 | return wrapper -------------------------------------------------------------------------------- /core/handlers/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | __all__ = ["check_status_chat","check_status_user","custom_handler","errors","filters_chat","flood_wait","handler_errors","handlers_index","logs","welcome"] 6 | 7 | from core.handlers import * -------------------------------------------------------------------------------- /core/handlers/check_status_user.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | import datetime 6 | from core import decorators 7 | from core.utilities.constants import * 8 | from core.utilities.message import message 9 | from core.database.repository.user import UserRepository 10 | from core.handlers.flood_wait import Flood_Manager_Python 11 | from core.database.repository.group import GroupRepository 12 | from core.database.repository.superban import SuperbanRepository 13 | from core.database.repository.dashboard import DashboardRepository 14 | from core.utilities.functions import user_object, chat_object, ban_user, kick_user, delete_message, mute_user_by_id, member_status_object, chat_status_object, check_user_permission 15 | 16 | flood_manager = Flood_Manager_Python() 17 | 18 | @decorators.public.init 19 | def check_status(update,context): 20 | # Telegram Variables 21 | bot = context.bot 22 | chat = chat_object(update) 23 | user = user_object(update) 24 | get_superban_user_id = update.effective_user.id 25 | user_photo = user.get_profile_photos(user.id) 26 | user_status = member_status_object(update,context) 27 | chat_status = chat_status_object(update, context) 28 | 29 | #Get Group via Database 30 | get_group = GroupRepository().getById(chat.id) 31 | #Get User via Database 32 | user_db = UserRepository().getById(user.id) 33 | #Get User via Database in Many to Many Association 34 | get_user = UserRepository().getUserByGroup([user.id,chat.id]) 35 | #Get User in Superban Table 36 | get_superban = SuperbanRepository().getById(get_superban_user_id) 37 | #get user in Dashboard 38 | get_dashboard = DashboardRepository().getById(user.id) 39 | #Get User Warn 40 | warn_count = get_user['warn_count'] if get_user is not None else DEFAULT_COUNT_WARN 41 | #Get Max Warn in group 42 | max_warn = get_group['max_warn'] if get_group is not None else DEFAULT_MAX_WARN 43 | 44 | if get_group: 45 | user_set_photo = get_group['set_user_profile_picture'] 46 | type_no_username = get_group['type_no_username'] 47 | else: 48 | user_set_photo = 0 49 | #Check if the user has a username if he does not have a username I perform a temporary kick and check that the user is not a service account 50 | if update.effective_user.id == SERVICE_ACCOUNT: 51 | print("Service Account") 52 | elif user.username is None or user.username == "": 53 | if type_no_username == 1: 54 | kick_user(update, context) 55 | msg = "#Automatic Handler\n{} set an username! You were kicked for safety!" 56 | message(update,context,msg.format(user.id)) 57 | elif type_no_username == 2: 58 | msg = "#Automatic Handler\n{} set an username!" 59 | message(update,context,msg.format(user.id)) 60 | elif type_no_username == 3: 61 | mute_user_by_id(update, context, user.id, True) 62 | msg = "#Automatic Handler\n{} set an username! You were Muted for safety!" 63 | message(update,context,msg.format(user.id)) 64 | elif type_no_username == 4: 65 | ban_user(update,context) 66 | msg = "#Automatic Handler\n{} was banned because they didn't have an username" 67 | message(update,context,msg.format(user.id)) 68 | elif type_no_username == 5: 69 | kick_user(update, context) 70 | else: 71 | print("No action even if you don't have a username") 72 | else: 73 | #Check if the user exists on the database if it exists makes an update of his username and his latest update if not exist insert it 74 | if user_db: 75 | #Get the Current Time 76 | current_time = datetime.datetime.utcnow().isoformat() 77 | username = "@"+user.username 78 | data = [(username,current_time,user.id)] 79 | UserRepository().update(data) 80 | data_mtm = [(user.id, chat.id, DEFAULT_COUNT_WARN,DEFAULT_USER_SCORE)] 81 | UserRepository().add_into_mtm(data_mtm) 82 | else: 83 | #Get the Current Time 84 | current_time = datetime.datetime.utcnow().isoformat() 85 | username = "@"+user.username 86 | data = [(user.id,username,current_time,current_time)] 87 | UserRepository().add(data) 88 | data_mtm = [(user.id, chat.id, DEFAULT_COUNT_WARN,DEFAULT_USER_SCORE)] 89 | UserRepository().add_into_mtm(data_mtm) 90 | #Check if the user has a profile photo 91 | if user_photo.total_count == 0 and user_set_photo == 1: 92 | kick_user(update, context) 93 | msg = "#Automatic Handler\n{} set a profile picture! You were kicked for safety!" 94 | message(update,context,msg.format(user.id)) 95 | #Check if the user has been blacklisted 96 | if get_superban: 97 | superban_reason = get_superban['motivation_text'] 98 | msg = '#Automatic Handler\nI got super banned {} [{}]\nFor the following Reason: {}'.format(user.id,user.first_name,user.id,superban_reason) 99 | message(update,context,msg) 100 | delete_message(update,context) 101 | ban_user(update,context) 102 | #If a user is enabled on the dashboard, I perform an update 103 | if get_dashboard: 104 | username = "@"+user.username 105 | save_date = datetime.datetime.utcnow().isoformat() 106 | dash_data = [(username, user_status.status, save_date, user.id, chat_status.id)] 107 | DashboardRepository().update(dash_data) 108 | #Check if the user has reached the maximum number of warns and ban him 109 | if warn_count == max_warn and check_user_permission(update,context) == False: 110 | ban_user(update,context) 111 | msg = "#Automatic Handler\n{} has reached the maximum number of warns" 112 | message(update,context,msg.format(user.id)) 113 | #I run an antiflood check if a user exceeds the allowed limit the antiflood starts working 114 | if flood_manager.check_flood_wait(update) == 1 and get_group['set_antiflood'] == 1 and check_user_permission(update,context) == False: 115 | bot.delete_message(update.effective_message.chat_id, update.message.message_id) 116 | kick_user(update, context) 117 | msg = "#Automatic Handler\n{} has been kicked for flood".format(user.id) 118 | message(update,context,msg.format(user.id)) -------------------------------------------------------------------------------- /core/handlers/custom_handler.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | from core.utilities.functions import chat_object, user_object 7 | from core.utilities.message import message 8 | from core.database.repository.group import GroupRepository 9 | from telegram.utils.helpers import mention_html 10 | 11 | def init(update,context): 12 | if str(update.effective_message.text).lower().startswith("nebula") or str(update.effective_message.text).lower().startswith("!") or str(update.effective_message.text).lower().startswith("/"): 13 | chat = chat_object(update) 14 | user = user_object(update) 15 | question = str(update.message.text.lower()) 16 | row = GroupRepository().get_custom_handler([question,chat.id]) 17 | if row: 18 | parsed_message = row['answer'].replace('{first_name}', 19 | user.first_name).replace('{chat}', 20 | update.message.chat.title).replace('{username}', 21 | "@"+user.username).replace('{mention}',mention_html(user.id, user.first_name)).replace('{userid}',str(user.id)) 22 | text = "{}".format(parsed_message) 23 | message(update,context,text) 24 | else: 25 | return -------------------------------------------------------------------------------- /core/handlers/errors.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | import html 7 | import json 8 | import logging 9 | import traceback 10 | from telegram import Update, ParseMode 11 | from telegram.ext import CallbackContext 12 | 13 | logging.basicConfig( 14 | format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO 15 | ) 16 | 17 | logger = logging.getLogger(__name__) 18 | 19 | DEVELOPER_CHAT_ID = 1065189838 20 | 21 | #ERROR HANDLER 3.0 22 | def error_handler(update: Update, context: CallbackContext) -> None: 23 | """Log the error and send a telegram message to notify the developer.""" 24 | # Log the error before we do anything else, so we can see it even if something breaks. 25 | logger.error(msg="Exception while handling an update:", exc_info=context.error) 26 | 27 | # traceback.format_exception returns the usual python message about an exception, but as a 28 | # list of strings rather than a single string, so we have to join them together. 29 | tb_list = traceback.format_exception(None, context.error, context.error.__traceback__) 30 | tb_string = ''.join(tb_list) 31 | 32 | # Build the message with some markup and additional information about what happened. 33 | # You might need to add some logic to deal with messages longer than the 4096 character limit. 34 | message = ( 35 | 'An exception was raised while handling an update\n' 36 | '
update = {}
\n\n' 37 | '
context.chat_data = {}
\n\n' 38 | '
context.user_data = {}
\n\n' 39 | '
{}
' 40 | ).format( 41 | html.escape(json.dumps(update.to_dict(), indent=2, ensure_ascii=False)), 42 | html.escape(str(context.chat_data)), 43 | html.escape(str(context.user_data)), 44 | html.escape(tb_string), 45 | ) 46 | 47 | # Finally, send the message 48 | context.bot.send_message(chat_id=DEVELOPER_CHAT_ID, text=message, parse_mode=ParseMode.HTML) -------------------------------------------------------------------------------- /core/handlers/filters_chat.py: -------------------------------------------------------------------------------- 1 | from core.utilities.functions import delete_message 2 | from core.utilities.message import message 3 | from core.database.repository.group import GroupRepository 4 | """ 5 | This function allows you to terminate the type 6 | of file that contains a message on telegram and filter it 7 | """ 8 | def init(update, context): 9 | # Mime Types 10 | apk = 'application/vnd.android.package-archive' 11 | doc = 'application/msword' 12 | docx = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' 13 | exe = 'application/x-ms-dos-executable' 14 | gif = 'video/mp4' 15 | jpg = 'image/jpeg' 16 | mp3 = 'audio/mpeg' 17 | pdf = 'application/pdf' 18 | py = 'text/x-python' 19 | svg = 'image/svg+xml' 20 | txt = 'text/plain' 21 | targz = 'application/x-compressed-tar' 22 | wav = 'audio/x-wav' 23 | xml = 'application/xml' 24 | filezip = 'application/zip' 25 | 26 | #Variables 27 | msg = update.effective_message 28 | chat = update.effective_message.chat_id 29 | group = GroupRepository().getById(chat) 30 | 31 | #Start Control 32 | if msg.document is not None: 33 | #No APK Allowed 34 | if msg.document.mime_type == apk and group['apk_filter'] == 1: 35 | delete_message(update,context) 36 | message(update, context, "#Automatic Filter Handler: No APK Allowed!") 37 | #No DOC/DOCX Allowed 38 | if msg.document.mime_type == doc or msg.document.mime_type == docx and group['docx_filter'] == 1: 39 | delete_message(update,context) 40 | message(update, context, "#Automatic Filter Handler: No DOC/DOCX Allowed!") 41 | #No EXE Allowed 42 | if msg.document.mime_type == exe and group['exe_filter'] == 1: 43 | delete_message(update,context) 44 | message(update, context, "#Automatic Filter Handler: No EXE Allowed!") 45 | #No GIF Allowed 46 | if msg.document.mime_type == gif and group['gif_filter'] == 1: 47 | delete_message(update,context) 48 | message(update, context, "#Automatic Filter Handler: No GIF Allowed!") 49 | #No JPG Allowed 50 | if msg.document.mime_type == jpg and group['jpg_filter'] == 1: 51 | delete_message(update,context) 52 | message(update, context, "#Automatic Filter Handler: No JPG Allowed!") 53 | #No TARGZ Allowed 54 | if msg.document.mime_type == targz and group['targz_filter'] == 1: 55 | delete_message(update,context) 56 | message(update, context, "#Automatic Filter Handler: No TARGZ Allowed!") 57 | #No ZIP Allowed 58 | if msg.document.mime_type == filezip and group['zip_filter'] == 1: 59 | delete_message(update,context) 60 | message(update, context, "#Automatic Filter Handler: No ZIP Allowed!") 61 | if msg.document.mime_type == wav: 62 | print("NO WAV ALLOWED") 63 | if msg.document.mime_type == xml: 64 | print("NO XML ALLOWED") 65 | if msg.document.mime_type == mp3: 66 | print("NO MP3 ALLOWED") 67 | if msg.document.mime_type == pdf: 68 | print("NO PDF ALLOWED") 69 | if msg.document.mime_type == py: 70 | print("NO PY ALLOWED") 71 | if msg.document.mime_type == svg: 72 | print("NO SVG ALLOWED") 73 | if msg.document.mime_type == txt: 74 | print("NO TXT ALLOWED") -------------------------------------------------------------------------------- /core/handlers/flood_wait.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | # Credits LakyDev 6 | 7 | import json 8 | from typing import List 9 | from core.database.redis_connect import RedisConnect 10 | from time import time 11 | 12 | 13 | class Flood_Manager_Python(RedisConnect): 14 | def __init__(self): 15 | super().__init__() 16 | self._knows_gids: List[str] = [] 17 | 18 | def _register_id(self, user_id: int, chat_id: int, group_id: int): 19 | self._knows_gids.append(f'{chat_id}{user_id}{group_id}') 20 | 21 | def _is_known_id(self, user_id: int, chat_id: int, group_id: int) -> bool: 22 | return f'{chat_id}{user_id}{group_id}' in self._knows_gids 23 | 24 | def check_flood_wait(self,update) -> int: 25 | # 0 = No Flood 26 | # 1 = Flood Start 27 | # 2 = Flood Wait 28 | 29 | user_id = update.effective_user.id 30 | chat_id = update.effective_chat.id 31 | media_id = update.effective_message.media_group_id 32 | if media_id is not None: 33 | if self._is_known_id(user_id, chat_id, media_id): 34 | return 0 35 | else: 36 | self._register_id(user_id, chat_id, media_id) 37 | 38 | id_data = f'{chat_id}:{user_id}' 39 | now_time = int(time()) 40 | if not self.hexists('groups',chat_id): 41 | self.update_group_data(chat_id, 5, 5, 30) 42 | print("No Group Data") 43 | else: 44 | chat_data = json.loads(self.hget('groups',chat_id)) 45 | self.hget('groups', chat_id) 46 | get_data = { 47 | 'messages': 1, 48 | 'last_message': now_time, 49 | } 50 | if self.hexists('flood_wait', id_data): 51 | get_data = json.loads(self.hget('flood_wait', id_data)) 52 | if get_data['messages'] >= chat_data['max_message']: 53 | mute_time = (get_data['last_message'] + chat_data['mute_time']) - now_time 54 | if mute_time > 0: 55 | return 2 56 | else: 57 | get_data['last_message'] = now_time 58 | get_data['messages'] = 1 59 | else: 60 | limit_exceeded = now_time - get_data['last_message'] > chat_data['max_time'] 61 | get_data['messages'] = 0 if limit_exceeded else get_data['messages'] + 1 62 | get_data['last_message'] = now_time if limit_exceeded else get_data['last_message'] 63 | self.hset('flood_wait', id_data, json.dumps(get_data)) 64 | return 1 if get_data['messages'] >= chat_data['max_message'] else 0 65 | 66 | def update_group_data(self, chat_id, max_time, max_message, mute_time): 67 | self.hset('groups', chat_id, json.dumps({'max_time': max_time, 'max_message': max_message,'mute_time': mute_time})) 68 | 69 | 70 | #print(check_flood_wait('-1001497049823', 1065189838)) 71 | -------------------------------------------------------------------------------- /core/handlers/handler_errors.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from config import Config 3 | from telegram.error import (TelegramError, Unauthorized, BadRequest, TimedOut, ChatMigrated, NetworkError) 4 | from core.utilities.message import message 5 | 6 | 7 | def init(update, context): 8 | txt = update.message.text 9 | err = '[error]' 10 | try: 11 | raise context.error 12 | except Unauthorized: 13 | err = '🔴 [ERROR]: Unauthorized\n' 14 | # remove update.message.chat_id from conversation list 15 | except BadRequest: 16 | err = '🔴 [ERROR]: BadRequest - malformed requests\n' 17 | # handle malformed requests - read more below! 18 | except TimedOut: 19 | err = '🔴 [ERROR]: TimedOut - slow connection problems\n' 20 | # handle slow connection problems 21 | except NetworkError: 22 | err = '🔴 [ERROR]: NetworkError - other connection problems\n' 23 | # handle other connection problems 24 | except ChatMigrated: 25 | err = '🔴 [ERROR]: ChatMigrated - chat_id not found (maybe group/channel migrated?)\n' 26 | # the chat_id of a group has changed, use e.new_chat_id instead 27 | except TelegramError: 28 | err = '🔴 [ERROR]: TelegramError\nThis is a generic error not handled by other handlers, check the console logs for info\n' 29 | # handle all other telegram related errors 30 | except AttributeError: 31 | err = '🔴 [ERROR]: AttributeError - bad code' 32 | except TypeError: 33 | # err = '[ERROR] TypeError - Unknown' 34 | # need to fix this... 35 | err = None 36 | 37 | if err != None: 38 | error_message(update, context, err, txt) 39 | 40 | logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) 41 | logger = logging.getLogger(__name__) 42 | def error_message(update, context, err, txt): 43 | chat_id = Config.DEVELOPER_CHAT_ID 44 | log = '\n🔵 [LOG_ERROR]: {}'.format(context.error) 45 | txt = "🤖 Bot Command: {}\n\n{}{}".format(txt, err, log) 46 | message(update, context, txt, 'HTML', 'messageid', chat_id, None) -------------------------------------------------------------------------------- /core/handlers/handlers_index.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from core import handlers 6 | from core.commands import public 7 | from telegram.ext import (MessageHandler as MH,Filters) 8 | from core.utilities import constants 9 | from core import jobs 10 | 11 | def core_handlers(dsp): 12 | function = dsp.add_handler 13 | function(MH(Filters.status_update.new_chat_members, handlers.welcome.init, run_async=True)) 14 | function(MH(Filters.chat_type, group_handlers, run_async=True)) 15 | 16 | def group_handlers(update,context): 17 | handlers.check_status_user.check_status(update, context) 18 | handlers.check_status_chat.check_status(update, context) 19 | handlers.check_status_chat.check_updates(update) 20 | handlers.custom_handler.init(update, context) 21 | public.report.init(update,context) 22 | public.eggs.egg_gh(update,context) 23 | public.eggs.nanachi(update,context) 24 | handlers.filters_chat.init(update, context) 25 | handlers.logs.set_log_channel(update,context) 26 | 27 | # Jobs Handlers Without Update Object 28 | def jobs_handlers(job_updater): 29 | job_updater.run_repeating(jobs.send_debug.send_log,interval=constants.DAILY,first=0.0, name="[DEBUG_LOG_JOB]") 30 | job_updater.run_repeating(jobs.query_repeat.query,interval=constants.FOUR_HOUR,first=0.0, name="[QUERY_REPEAT_JOB]") 31 | #job_updater.run_repeating(jobs.send_db_backup.send_backup, interval=constants.ONE_MINUTE, first=0.0,name="[DATABASE_BACKUP]") -------------------------------------------------------------------------------- /core/handlers/logs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | # Credits https://github.com/PaulSonOfLars/tgbot/ 6 | import logging 7 | from config import Config 8 | from telegram.error import BadRequest, Unauthorized 9 | from core.utilities.message import message 10 | from core.database.repository.group import GroupRepository 11 | 12 | SET_CHANNEL_DEBUG = True 13 | 14 | def sys_loggers(name="",message="",debugs = False,info = False,warning = False,errors = False, critical = False): 15 | logger = logging.getLogger(name) 16 | logger.setLevel((logging.INFO, logging.DEBUG)[Config.DEBUG]) 17 | fh = logging.FileHandler('debug.log') 18 | fh.setLevel(logging.INFO) 19 | logger.addHandler(fh) 20 | formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 21 | fh.setFormatter(formatter) 22 | logger.addHandler(fh) 23 | if debugs == True: 24 | logger.debug(message) 25 | elif info == True: 26 | logger.info(message) 27 | elif warning == True: 28 | logger.warning(message) 29 | elif errors == True: 30 | logger.error(message) 31 | elif critical == True: 32 | logger.critical(message) 33 | 34 | """ 35 | This function makes a logger on the telegram channel 36 | set if it is not set it is sent to the default channel 37 | """ 38 | def telegram_loggers(update,context,msg = ""): 39 | chat = update.effective_message.chat_id 40 | row = GroupRepository().getById([chat]) 41 | id_channel = Config.DEFAULT_LOG_CHANNEL 42 | if row: 43 | get_log_channel = row['log_channel'] 44 | send = message(update, context, msg, 'HTML', 'messageid', get_log_channel, None) 45 | else: 46 | send = message(update, context, msg, 'HTML', 'messageid', id_channel, None) 47 | return send 48 | 49 | def staff_loggers(update,context,msg = ""): 50 | id_staff_group = Config.DEFAULT_STAFF_GROUP 51 | send = message(update, context, msg, 'HTML', 'messageid', id_staff_group, None) 52 | return send 53 | 54 | def debug_channel(update,context,msg = ""): 55 | id_debug_channel = -1001540824311 56 | if SET_CHANNEL_DEBUG == True: 57 | send = message(update, context, msg, 'HTML', 'messageid', id_debug_channel, None) 58 | else: 59 | return 60 | return send 61 | 62 | def set_log_channel(update,context): 63 | msg = update.effective_message 64 | chat = update.effective_chat 65 | user = update.effective_user 66 | record = GroupRepository.SET_LOG_CHANNEL 67 | if user is not None: 68 | member = chat.get_member(user.id) 69 | if chat.type == 'channel' and str(update.effective_message.text).lower().startswith("/setlog"): 70 | msg.reply_text("Now, forward the /setlog to the group you want to tie this channel to!") 71 | 72 | elif msg.forward_from_chat and msg.text == '/setlog' and member.status == 'creator': 73 | data = [(msg.forward_from_chat.id, chat.id)] 74 | GroupRepository().update_group_settings(record, data) 75 | try: 76 | msg.delete() 77 | except BadRequest as excp: 78 | if excp.message == "Message to delete not found": 79 | pass 80 | else: 81 | message(update,context,"Error deleting message in log channel. Should work anyway though.") 82 | 83 | try: 84 | msg = "This channel has been set as the log channel for {}.".format(chat.title or chat.first_name) 85 | message(update, context, msg, 'HTML', 'messageid', msg.forward_from_chat.id, None) 86 | except Unauthorized as excp: 87 | if excp.message == "Forbidden: bot is not a member of the channel chat": 88 | message(update,context, "Successfully set log channel!") 89 | else: 90 | message(update,context,"ERROR in setting the log channel.") 91 | 92 | message(update,context, "Successfully set log channel!") 93 | 94 | else: 95 | if str(update.effective_message.text).lower().startswith("/setlog"): 96 | msg.reply_text("The steps to set a log channel are:\n" 97 | " - add bot to the desired channel\n" 98 | " - send /setlog to the channel\n" 99 | " - forward the /setlog to the group\n" 100 | " - You need to be a creator of the group") -------------------------------------------------------------------------------- /core/jobs/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | """Import Files""" 7 | __all__ = ["night_mode","query_repeat","send_db_backup","send_debug"] 8 | 9 | from core.jobs import * -------------------------------------------------------------------------------- /core/jobs/night_mode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | from core.utilities.constants import PERM_FALSE 7 | 8 | def init(update,context): 9 | context.job_queue.run_repeating(callback_night,interval=10.0,first=0.0, name="[NIGHT_SCHEDULE_JOB]",context=update.effective_chat.id) 10 | 11 | def callback_night(context): 12 | chat_id = context.job.context 13 | context.bot.send_message(chat_id=chat_id, text="TEST_NIGHT_SCHEDULE") 14 | context.bot.set_chat_permissions(chat_id, PERM_FALSE) 15 | print(chat_id) -------------------------------------------------------------------------------- /core/jobs/query_repeat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | #Send debug.log into Dev_Channel 7 | from core.database.repository.group import GroupRepository 8 | 9 | def query(context): 10 | bot = context.bot 11 | chat = '-1001540824311' 12 | GroupRepository().job_nebula_updates() 13 | bot.send_message(chat,text="[DEBUG LOGGER] I ran the nebula_updates table cleanup query",parse_mode='HTML') -------------------------------------------------------------------------------- /core/jobs/send_db_backup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | #Send database backup into Telegram Private Channel 7 | def send_backup(context): 8 | context.bot.send_document(chat_id='-1001316452992', document=open('/home/HgeyPaZppivx/internal_db_backup/nebula.sql', 'rb')) -------------------------------------------------------------------------------- /core/jobs/send_debug.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | #Send debug.log into Dev_Channel 7 | def send_log(context): 8 | context.bot.send_document(chat_id='-1001540824311', document=open('debug.log', 'rb')) -------------------------------------------------------------------------------- /core/utilities/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | """Import Files""" 7 | __all__ = ["constants","menu","message","functions","strings","regex","monads"] 8 | 9 | from core.utilities import * -------------------------------------------------------------------------------- /core/utilities/constants.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | from telegram import ChatPermissions 7 | 8 | #general constants 9 | DEFAULT_COUNT_WARN = 0 10 | DEFAULT_USER_SCORE = 0 11 | DEFAULT_MAX_WARN = 3 12 | SERVICE_ACCOUNT = 777000 13 | 14 | # constants for time management 15 | # DAILY == 24h ; TWELVE_HOUR == 12h ; EIGHT_HOUR == 8h ; FOUR_HOUR == 4h ; ONE_HOUR == 1h 16 | DAILY = 86400.0 17 | TWELVE_HOUR = 43200.0 18 | EIGHT_HOUR = 28800.0 19 | FOUR_HOUR = 14400.0 20 | ONE_HOUR = 3600.0 21 | ONE_MINUTE = 60.0 22 | 23 | #these constants change and disrupt an entire group 24 | PERM_FALSE = ChatPermissions( 25 | can_send_messages=False, 26 | can_send_media_messages=False, 27 | can_send_polls=False, 28 | can_send_other_messages=False, 29 | can_add_web_page_previews=False, 30 | can_change_info=False, 31 | can_invite_users=False, 32 | can_pin_messages=False 33 | ) 34 | PERM_TRUE = ChatPermissions( 35 | can_send_messages=True, 36 | can_send_media_messages=True, 37 | can_send_polls=True, 38 | can_send_other_messages=True, 39 | can_add_web_page_previews=True, 40 | can_change_info=False, 41 | can_invite_users=False, 42 | can_pin_messages=False 43 | ) 44 | 45 | PERM_MEDIA_TRUE = ChatPermissions( 46 | can_send_messages=True, 47 | can_send_media_messages=True, 48 | can_send_polls=True, 49 | can_send_other_messages=True, 50 | can_add_web_page_previews=True, 51 | can_change_info=False, 52 | can_invite_users=False, 53 | can_pin_messages=False 54 | ) 55 | 56 | PERM_MEDIA_FALSE = ChatPermissions( 57 | can_send_messages=True, 58 | can_send_media_messages=False, 59 | can_send_polls=True, 60 | can_send_other_messages=False, 61 | can_add_web_page_previews=True, 62 | can_change_info=False, 63 | can_invite_users=False, 64 | can_pin_messages=False 65 | ) -------------------------------------------------------------------------------- /core/utilities/menu.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | from typing import Union, List 6 | from telegram import InlineKeyboardButton 7 | 8 | # Build Menu 2.0 9 | """ 10 | Example to use(https://github.com/python-telegram-bot/python-telegram-bot/wiki/Code-snippets#build-a-menu-with-buttons): 11 | ########################################################################################################################## 12 | You can use the header_buttons and footer_buttons lists to put buttons in the first or last row respectively. 13 | ########################################################################################################################## 14 | button_list = [ 15 | InlineKeyboardButton("col1", callback_data=...), 16 | InlineKeyboardButton("col2", callback_data=...), 17 | InlineKeyboardButton("row 2", callback_data=...) 18 | ] 19 | reply_markup = InlineKeyboardMarkup(util.build_menu(button_list, n_cols=2)) 20 | bot.send_message(..., "A two-column menu", reply_markup=reply_markup) 21 | 22 | 23 | ########################################################################################################################## 24 | Or, if you need a dynamic version, use list comprehension to generate your button_list dynamically from a list of strings: 25 | ########################################################################################################################## 26 | some_strings = ["col1", "col2", "row2"] 27 | button_list = [[KeyboardButton(s)] for s in some_strings] 28 | 29 | """ 30 | def build_menu( 31 | buttons: List[InlineKeyboardButton], 32 | n_cols: int, 33 | header_buttons: Union[InlineKeyboardButton, List[InlineKeyboardButton]]=None, 34 | footer_buttons: Union[InlineKeyboardButton, List[InlineKeyboardButton]]=None 35 | ) -> List[List[InlineKeyboardButton]]: 36 | menu = [buttons[i:i + n_cols] for i in range(0, len(buttons), n_cols)] 37 | if header_buttons: 38 | menu.insert(0, header_buttons if isinstance(header_buttons, list) else [header_buttons]) 39 | if footer_buttons: 40 | menu.append(footer_buttons if isinstance(footer_buttons, list) else [footer_buttons]) 41 | return menu 42 | -------------------------------------------------------------------------------- /core/utilities/message.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | import asyncio 6 | import urllib.request 7 | import requests 8 | from config import Config 9 | 10 | MAIN_URL = "https://api.telegram.org/" 11 | TOKEN = Config.BOT_TOKEN 12 | 13 | def TopicMessage(thread_id,chat_id,text = ""): 14 | url = MAIN_URL + "bot{}/sendmessage?message_thread_id={}&chat_id={}&text={}&parse_mode=HTML".format(TOKEN, thread_id,chat_id, text) 15 | send = requests.get(url) 16 | return send 17 | def message(update, context, text = "", parse = 'HTML', type = 'message', chatid=None, img=None, reply_markup = None): 18 | bot = context.bot 19 | chat = update.effective_chat.id 20 | forum = bot.getChat(chat).is_forum 21 | thread_id = update.effective_message.message_thread_id if forum is not None else 0 22 | 23 | if type == 'message': 24 | send = bot.send_message(chat, text, parse_mode=parse,message_thread_id=thread_id,reply_markup=reply_markup) 25 | elif type == 'photo': 26 | send = bot.sendPhoto(chat_id=update.effective_chat.id, photo=img, caption=text, parse_mode=parse,message_thread_id=thread_id) 27 | elif type == 'reply': 28 | send = update.message.reply_text(text, parse_mode=parse,message_thread_id=thread_id,reply_markup=reply_markup) 29 | elif type == 'messageid': 30 | send = bot.send_message(chatid,text,parse_mode=parse) 31 | elif type == 'private': 32 | send = bot.send_message(update.message.from_user.id,text,parse_mode=parse,reply_markup=reply_markup) 33 | elif type == 'animation': 34 | send = bot.sendAnimation(chat, img, caption=text,message_thread_id=thread_id) 35 | return send 36 | 37 | def ApiMessage(text, chat_id): 38 | text = urllib.parse.quote_plus(text) 39 | url = MAIN_URL + "bot{}/sendmessage?chat_id={}&text={}&parse_mode=HTML".format(TOKEN, chat_id, text) 40 | send = requests.get(url) 41 | return send 42 | 43 | def ApiGroupRemove(chat_id): 44 | url = MAIN_URL + "bot{}/leaveChat?chat_id={}".format(TOKEN,chat_id) 45 | send = requests.get(url) 46 | return send 47 | 48 | async def messageWithAsync(update,context,delay,text = ""): 49 | bot = context.bot 50 | chat = update.effective_chat.id 51 | await asyncio.sleep(delay) 52 | msg = bot.send_message(chat,text,parse_mode='HTML') 53 | return msg 54 | 55 | async def messageWithAsyncById(update,context,chat,delay,text = ""): 56 | bot = context.bot 57 | await asyncio.sleep(delay) 58 | msg = bot.send_message(chat,text,parse_mode='HTML') 59 | return msg 60 | -------------------------------------------------------------------------------- /core/utilities/monads.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | # Schrödinger's cat but in Python 7 | class Optional: 8 | @staticmethod 9 | def of(value = None): 10 | if value == None: 11 | return Nope() 12 | else: 13 | return Just(value) 14 | 15 | def __init__(self, value = None): 16 | self.maybeValue = value 17 | 18 | def valueOf(self): 19 | return self.maybeValue 20 | 21 | class Nope(Optional): 22 | def map(self, f): 23 | return Nope() 24 | 25 | def flatMap(self, f): 26 | return Nope() 27 | 28 | def valueOf(self): 29 | return None 30 | 31 | class Just(Optional): 32 | @staticmethod 33 | def of(value = None): 34 | return Just(value) 35 | 36 | def map(self, f): 37 | return Optional.of(f(self.maybeValue)) 38 | 39 | def flatMap(self, f): 40 | flattened = f(self.maybeValue) 41 | assert isinstance(flattened, Optional) 42 | return flattened 43 | 44 | def valueOf(self): 45 | return self.maybeValue 46 | 47 | class Given(Optional): 48 | def of(value = None): 49 | return Given(value) 50 | 51 | def when(self, predicate, then): 52 | if predicate(self.maybeValue): 53 | return GivenJust(then) 54 | else: 55 | return GivenNope(self.maybeValue) 56 | 57 | def otherwise(self, then): 58 | return Just.of(then) 59 | 60 | def valueOf(self): 61 | return self.maybeValue 62 | 63 | class GivenNope(Given): 64 | def __init__(self, searchVal = None): 65 | self.maybeValue = searchVal 66 | 67 | def valueOf(self): 68 | return None 69 | 70 | def otherwise(self, then): 71 | return Just.of(then) 72 | 73 | class GivenJust(Given): 74 | def valueOf(self): 75 | return self.maybeValue 76 | 77 | def when(self, predicate, then): 78 | return self 79 | 80 | def otherwise(self, then): 81 | return Just.of(self.maybeValue) 82 | 83 | class Try(Optional): 84 | @staticmethod 85 | def of(f): 86 | assert callable(f) 87 | return Try(f) 88 | 89 | def __init__(self, f): 90 | self.maybeValue = False 91 | try: 92 | value = f() 93 | self.maybeValue = True 94 | 95 | self.tryResult = value 96 | except Exception as e: 97 | self.error = e 98 | 99 | def catch(self, f): 100 | if not self.maybeValue: 101 | f(self.error) 102 | return self 103 | 104 | def map(self, f): 105 | if self.maybeValue: 106 | return Just(self.tryResult).map(f) 107 | else: 108 | return Nope() 109 | 110 | def flatMap(self, f): 111 | if self.maybeValue: 112 | return Just(self.tryResult).flatMap(f) 113 | else: 114 | return Nope() 115 | 116 | def valueOf(self): 117 | if self.maybeValue: 118 | return self.maybeValue 119 | else: 120 | return None -------------------------------------------------------------------------------- /core/utilities/regex.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | import re 7 | 8 | class Regex(object): 9 | HAS_ARABIC = "[\u0600-\u06ff]|[\u0750-\u077f]|[\ufb50-\ufbc1]|[\ufbd3-\ufd3f]|[\ufd50-\ufd8f]|[\ufd92-\ufdc7]|[\ufe70-\ufefc]|[\uFDF0-\uFDFD]+" 10 | HAS_CIRILLIC = "[а-яА-Я]+" 11 | HAS_CHINESE = "[\u4e00-\u9fff]+" 12 | HAS_NUMBER = "^[0-9]+$" 13 | HAS_LETTER = "^[a-zA-Z]+$" 14 | HAS_ZOOPHILE = "[ζ]" 15 | HAS_URL = "((http|https)\:\/\/)?[a-zA-Z0-9\.\/\?\:@\-_=#]+\.([a-zA-Z]){2,6}([a-zA-Z0-9\.\&\/\?\:@\-_=#])*" 16 | 17 | def check_string(regex_type,string): 18 | check = re.search(regex_type, string) 19 | if check is None: 20 | return False 21 | else: 22 | return True -------------------------------------------------------------------------------- /core/utilities/strings.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | class Strings(object): 7 | ERROR_HANDLING = "Attention I detected a problem to send the message in the following group:\n ID: {}\nTYPE: {}" 8 | BAN_LOG = "⚠️ #Log User Banned!\n👤 User_Id: {id}\n"\ 9 | '👤 Username: {username}\n'\ 10 | "👥 Group: {chat}\n" 11 | SUPERBAN_LOG = '🚷 #Log User Superbanned!\n👤 User: {}[{}]\n📜 Reason: {}\n🕐 Datetime: {}\n👮‍♀️ Operator: {}\n{} [{}]' 12 | REPORT_MSG = "⚠️#Report\nGroup Id: {}\nGroup Title: {}\nMessage: {}\n📎 Link: {}" 13 | SOURCE = "Hi! my name is: {}\nMy Version is: {} {}\nMy repository is: {}" 14 | USER_INFO = '⚙️ INFO USER:\n👤 UserId: {id}\n👤 Username: {username}\n⚠️ Warn: {warn}\n👥 Group: {chat}' 15 | WELCOME_BOT = "Thanks for adding me to the group ❤️\nPlease select your language => [/lang]\n\n❇️ Remember to make me administrator to work properly❗️\n\n🆘 Need Help? => /help\n\n⚙️ To change the group settings, press the [/settings] command\n\n⚙️ To change the filters in the group, type [/filters]\n\n⚙️ To change the warn limit in the group, type [/setwarn]\n\n⚙️ To change welcome type [/welcome] and follow the instructions\n\nMy Version is: {} {}" -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | 3 | services: 4 | bot: 5 | image: squirrelnet/nebula8 6 | build: 7 | context: docker/bot/ 8 | volumes: 9 | - bot_data:/opt/service/data 10 | - bot_requirements:/root 11 | environment: 12 | REPO: $REPO 13 | BRANCH: $BRANCH 14 | 15 | HOST: $HOST 16 | PORT: $PORT 17 | USER: $USER 18 | PASSWORD: $PASSWORD 19 | DBNAME: $DBNAME 20 | 21 | BOT_TOKEN: $BOT_TOKEN 22 | SUPERADMIN: $SUPERADMIN 23 | OWNER: $OWNER 24 | DEFAULT_WELCOME: $DEFAULT_WELCOME 25 | DEFAULT_RULES: $DEFAULT_RULES 26 | DEFAULT_LOG_CHANNEL: $DEFAULT_LOG_CHANNEL 27 | DEFAULT_STAFF_GROUP: $DEFAULT_STAFF_GROUP 28 | 29 | OPENWEATHER_API: $OPENWEATHER_API 30 | ENABLE_PLUGINS: $ENABLE_PLUGINS 31 | DEFAULT_LANGUAGE: $DEFAULT_LANGUAGE 32 | VERSION: $VERSION 33 | VERSION_NAME: $VERSION_NAME 34 | 35 | DEBUG: $DEBUG 36 | 37 | volumes: 38 | bot_data: 39 | bot_requirements: -------------------------------------------------------------------------------- /languages/EN.py: -------------------------------------------------------------------------------- 1 | English = { 2 | "LANG_DEFAULT": "en", 3 | "START_COMMAND": "Hi, my name is {} and I am a tool for managing groups with many special functions to be discovered and I am Open Source! If you want to see my source type: /source If you need help, type /help", 4 | "HELP_COMMAND": "Hi my name is {}\nDo You need Help?", 5 | "GROUP_INFO": "Group Title: {}\n\nGroup Id: {}\n\nGroup's Language: {}\n\nWarn Limit: {}\n\nTotal Group Users: {}\n\nTotal Group Messages: {} In the last 30 days", 6 | "BOT_WELCOME": "Thank you for adding me to the {} group\nFor working properly i need admins privileges!", 7 | "BAN_MESSAGE": '{user} has been banned from: {chat}', 8 | "RULES": "Here are the group rules: {}", 9 | "BAN_USER": "I got banned %s", 10 | "BAN_BOT": "I can't ban myself!", 11 | "BAN_ERROR": "Incorrect command syntax or unrecognized user: {}", 12 | "BAN_USER_ERROR": "There was a problem with the user ban %s", 13 | "SAY_MESSAGE": "Error the message cannot be empty!", 14 | "DELETE_MESSAGE": "You must use this command in response to a message!", 15 | "CLOSE_SETTINGS": "You have closed the bot settings menu!", 16 | "MAIN_TEXT_SETTINGS": "Bot Settings menu", 17 | "WELCOME_SETTINGS": "Welcome %s", 18 | "SET_MAIN_WELCOME": "Group Welcome Instructions:\nYou have to use the command like this /welcome args\nwhere args is the text you need to insert\nit is possible to use special tags that are interpreted by the bot:\n{username} = user's username\n{chat} = group name\n{first_name} = user's first name\n{userid} = user id\n{mention} = user mention\nHTML tags can also be used\nb , i, code\nand emojis can also be used\n\nEXAMPLE:\nWelcome {username} in {chat}", 19 | "WELCOME_MAIN_HELP_SET": "I changed the welcome of the group!\nif you want help type /welcome without any message", 20 | "WEATHER_MSG": "Current weather in {}\nMin: {} C°\nMax: {} C°\nHumidity: {}%\nIl The sky is: {}", 21 | "REPORT_ADMIN_MSG": "Reporting done! an admin will take care of your request!", 22 | "RULES_MSG": "You have correctly changed the rules of the group!", 23 | "RULES_ERROR_MSG": "The message is empty! The correct format is: /setrules args", 24 | "PERM_MSG_ERROR": "The bot does not have the correct permissions to function properly!❌\nPlease promote the bot as an admin", 25 | "PERM_MSG_OK": "The bot has the correct permissions to function properly ✅", 26 | "CLOSE_MENU": "You have closed the Menu", 27 | "GLOBAL_REPORT_MSG": "You have reported a problem to the bot staff, an available operator will come to assist", 28 | "ERROR_RESPONSE_USER_MSG": "You must use this command in response to a user", 29 | "WARN_USER": "‼️ {} was warned! For the {}° time (su {}).\nin the {} group [{}]", 30 | "WARN_USER_MAX": "User @{} has reached the maximum number\n of warns in the {} group and has been banned", 31 | "BUTTON_REMOVE": '🗑 Remove', 32 | "MUTE_MSG": 'You muted the user {} [{}]', 33 | "MUTE_MSG_R": 'You have removed the mute from user {} [{}]', 34 | "MUTE_BUTTON": "✅ Unmute", 35 | "RULES_MAIN_TEXT": "📜 Rules of: {} [{}]", 36 | "RULES_BUTTON": "▶️ Rules ◀️", 37 | "BADWORD_LIST_TEXT": "🗒 Badword list of the group {}:\n{}", 38 | "BADWORD_LIST_EMPTY": "There is no badword for this group.\nYou can add a badword with the command /badword word", 39 | "BADWORD_ADD_TEXT": "You have entered the forbidden word: [{}] in the database", 40 | "BADWORD_ADD_EMPTY": "You cannot enter an empty forbidden word!\nthe correct format of the command is: /badword banana", 41 | "SHIELD_ON": "🛡Shield Activated!\nAttention! By activating this command you have completely blocked the group!!!\nto change the settings again you have to type /settings", 42 | "WARN_USER_REASON": "‼️ {} was warned! For the {}° time (su {}).\nin the {} group [{}]\nfor the following reason: {}", 43 | "KICKED_USER_MESSAGE_NO_USERNAME": "⛔️ {}, to be welcome in the group, set your own username!\nAction: {}", 44 | "SET_BAN_MESSAGE": "You have set up the custom ban message successfully!", 45 | "BAN_ERROR_SYNTAX": "Incorrect command syntax or unrecognized user: {}", 46 | "BAN_ERROR_AC": "I can't ban an administrator or owner!", 47 | "BAN_EMPTY_ERROR": "The text of the ban cannot be empty!", 48 | "BAN_SELF_BAN": "I can't ban myself, Use this command in the correct way!" 49 | } -------------------------------------------------------------------------------- /languages/IT.py: -------------------------------------------------------------------------------- 1 | Italian = { 2 | "LANG_DEFAULT": "it", 3 | "START_COMMAND": "Ciao io mi chiamo {} e sono uno strumento per la gestione dei gruppi con tante funzioni speciali tutte da scoprire e sono Open Source! Se vuoi vedere il mio sorgente digita: /source Se hai bisogno di aiuto digita /help", 4 | "HELP_COMMAND": "Ciao mi chiamo {}\nHai bisogno di aiuto?", 5 | "GROUP_INFO": "Titolo Gruppo: {}\n\nId del gruppo: {}\n\nLingua del gruppo: {}\n\nLimite Warn: {}\n\nTotale Utenti Gruppo: {}\n\nTotale Messaggi Gruppo: {} Negli ultimi 30 giorni", 6 | "BOT_WELCOME": "Grazie di avermi aggiunta al gruppo {}\nPer funzionare correttamente ho bisogno dei privilegi di amministratore!", 7 | "BAN_MESSAGE": '{user} è stato bannato da {chat}', 8 | "RULES": "Ecco il regolamento del gruppo: {}", 9 | "BAN_USER": "Ho bannato %s", 10 | "BAN_BOT": "Non posso bannarmi da sola!", 11 | "BAN_ERROR": "Sintassi del comando errata o utente non riconosciuto: {}", 12 | "BAN_USER_ERROR": "Si è verificato un problema per il ban dell'utente %s", 13 | "SAY_MESSAGE": "Errore il messaggio non può essere vuoto!", 14 | "DELETE_MESSAGE": "Devi utilizzare questo comando in risposta ad un messaggio!", 15 | "CLOSE_SETTINGS": "Hai chiuso il menu impostazioni del bot!", 16 | "MAIN_TEXT_SETTINGS": "Menu Impostazioni del bot", 17 | "WELCOME_SETTINGS": "Benvenuto %s", 18 | "SET_MAIN_WELCOME": "Istruzioni per il benvenuto del Gruppo:\nDovete utilizzare il comando in questo modo /welcome args\ndove args è il testo che dovete inserire\nè possibilie utilizzare dei tag speciali che vengono interpretati dal bot:\n{username} = username utente\n{chat} = nome del gruppo\n{first_name} = nome utente\n{userid} = id utente\n{mention} = menzione utente\nè possibile utilizzare anche i tag HTML\nb , i, code\ne possono essere usate anche le Emoji\n\nESEMPIO:\nBenvenuto {username} in {chat}", 19 | "WELCOME_MAIN_HELP_SET": "Ho modificato il welcome del gruppo!\nse vuoi un aiuto digita /welcome senza nessun messaggio", 20 | "WEATHER_MSG": "Tempo attuale a {}\nMin: {} C°\nMax: {} C°\nUmidità: {}%\nIl Cielo è: {}", 21 | "REPORT_ADMIN_MSG": "Segnalazione effettuata! un admin prenderà in carico la tua richiesta!", 22 | "RULES_MSG": "Hai cambiato correttamente le regole del gruppo!", 23 | "RULES_ERROR_MSG": "Il messaggio è vuoto! Il formato corretto è: /setrules args", 24 | "PERM_MSG_ERROR": "Il bot non ha i permessi corretti per funzionare correttamente!❌\nPromuovi il bot come amministratore", 25 | "PERM_MSG_OK": "Il bot ha i permessi corretti per funzionare correttamente ✅", 26 | "CLOSE_MENU": "Hai chiuso il Menu", 27 | "GLOBAL_REPORT_MSG": "Hai segnalato un problema al personale del bot, un operatore disponibile verrà ad aiutarti", 28 | "ERROR_RESPONSE_USER_MSG": "È necessario utilizzare questo comando in risposta a un utente", 29 | "WARN_USER": "‼️ {} è stato warnato! per la {}° volta (su {}).\nnel gruppo {} [{}]", 30 | "WARN_USER_MAX": "L'utente @{} ha raggiunto il numero massimo\n di avvertimenti nel gruppo {} ed è stato bannato", 31 | "BUTTON_REMOVE": '🗑 Rimuovi', 32 | "MUTE_MSG": 'Hai mutato {} [{}]', 33 | "MUTE_MSG_R": 'Hai rimosso il muta di {} [{}]', 34 | "MUTE_BUTTON": "✅ Smuta", 35 | "RULES_MAIN_TEXT": "📜 Regole di: {} [{}]", 36 | "RULES_BUTTON": "▶️ Regole ◀️", 37 | "BADWORD_LIST_TEXT": "🗒 Lista Badword del gruppo {}:\n{}", 38 | "BADWORD_LIST_EMPTY": "Non c'è nessuna badword per questo gruppo.\nPuoi aggiungere una badword con il comando /badword word", 39 | "BADWORD_ADD_TEXT": "Hai inserito la parola proibita: [{}] nel database", 40 | "BADWORD_ADD_EMPTY": "Non puoi inserire una badword vuota!\nIl formato corretto del comando è: /badword banana", 41 | "SHIELD_ON": "🛡Scudo attivato!\nAttenzione! Attivando questo comando hai completamente bloccato il gruppo!!!\nper modificare nuovamente le impostazioni è necessario digitare /settings", 42 | "WARN_USER_REASON": "‼️ {} è stato warnato! per la {}° volta (su {}).\nnel gruppo {} [{}]\nper il seguente motivo: {}", 43 | "KICKED_USER_MESSAGE_NO_USERNAME": '⛔️ {}, per essere ben accetto nel gruppo, imposta un tuo username!\nAzione: {}', 44 | "SET_BAN_MESSAGE": "Hai impostato il messaggio di ban personalizzato con successo!", 45 | "BAN_ERROR_SYNTAX": "Sintassi del comando errata o utente non riconosciuto: {}", 46 | "BAN_ERROR_AC": "Non posso bannare un amministratore o un owner!", 47 | "BAN_EMPTY_ERROR": "Il testo del ban non può essere vuoto!", 48 | "BAN_SELF_BAN": "Non posso bannarmi da sola, usa questo comando nel modo corretto!" 49 | } -------------------------------------------------------------------------------- /languages/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | """Import Files""" 7 | __all__ = ["EN","getLang","IT"] 8 | 9 | from languages import * -------------------------------------------------------------------------------- /languages/getLang.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | from config import Config 7 | from core.database.repository.group_language import GroupLanguageRepository 8 | from languages import (EN,IT) 9 | 10 | def get(update, context): 11 | chat = update.effective_message.chat_id 12 | row = GroupLanguageRepository().getById([chat]) 13 | if row is None: 14 | return None 15 | else: 16 | return row['languages'] 17 | 18 | def languages(update, context): 19 | LANGUAGE = get(update,context) 20 | 21 | if LANGUAGE == "" or LANGUAGE is None: 22 | LANGUAGE = Config.DEFAULT_LANGUAGE 23 | 24 | if LANGUAGE == "IT": 25 | setLang = IT.Italian 26 | elif LANGUAGE == "EN": 27 | setLang = EN.English 28 | 29 | languages.lang_default = setLang["LANG_DEFAULT"] 30 | languages.start = setLang["START_COMMAND"] 31 | languages.helps = setLang["HELP_COMMAND"] 32 | languages.group_info = setLang["GROUP_INFO"] 33 | languages.bot_welcome = setLang["BOT_WELCOME"] 34 | languages.ban_message = setLang["BAN_MESSAGE"] 35 | languages.rules = setLang["RULES"] 36 | languages.user_ban = setLang["BAN_USER"] 37 | languages.bot_ban = setLang["BAN_BOT"] 38 | languages.ban_error = setLang["BAN_ERROR"] 39 | languages.ban_user_error = setLang["BAN_USER_ERROR"] 40 | languages.say_error = setLang["SAY_MESSAGE"] 41 | languages.delete_error_msg = setLang["DELETE_MESSAGE"] 42 | languages.close_menu_msg = setLang["CLOSE_SETTINGS"] 43 | languages.main_menu_msg = setLang["MAIN_TEXT_SETTINGS"] 44 | languages.welcome_set = setLang["WELCOME_SETTINGS"] 45 | languages.set_welcome_main = setLang["SET_MAIN_WELCOME"] 46 | languages.set_welcome_help = setLang["WELCOME_MAIN_HELP_SET"] 47 | languages.weather_message = setLang["WEATHER_MSG"] 48 | languages.report_msg = setLang["REPORT_ADMIN_MSG"] 49 | languages.rules_msg = setLang["RULES_MSG"] 50 | languages.rules_error_msg = setLang["RULES_ERROR_MSG"] 51 | languages.perm_error = setLang["PERM_MSG_ERROR"] 52 | languages.perm_ok = setLang["PERM_MSG_OK"] 53 | languages.close_menu_general = setLang["CLOSE_MENU"] 54 | languages.global_report_msg = setLang["GLOBAL_REPORT_MSG"] 55 | languages.error_response_user_msg = setLang["ERROR_RESPONSE_USER_MSG"] 56 | languages.warn_user = setLang["WARN_USER"] 57 | languages.warn_user_max = setLang["WARN_USER_MAX"] 58 | languages.button_remove = setLang["BUTTON_REMOVE"] 59 | languages.mute_msg = setLang["MUTE_MSG"] 60 | languages.mute_msg_r = setLang["MUTE_MSG_R"] 61 | languages.mute_button = setLang["MUTE_BUTTON"] 62 | languages.rules_main = setLang["RULES_MAIN_TEXT"] 63 | languages.rules_button = setLang["RULES_BUTTON"] 64 | languages.badlist_text = setLang["BADWORD_LIST_TEXT"] 65 | languages.badlist_empty = setLang["BADWORD_LIST_EMPTY"] 66 | languages.badlist_add = setLang["BADWORD_ADD_TEXT"] 67 | languages.badlist_add_empty = setLang["BADWORD_ADD_EMPTY"] 68 | languages.shield_on = setLang["SHIELD_ON"] 69 | languages.warn_with_reason = setLang["WARN_USER_REASON"] 70 | languages.kicked_user_message = setLang["KICKED_USER_MESSAGE_NO_USERNAME"] 71 | languages.set_ban_message = setLang["SET_BAN_MESSAGE"] 72 | languages.ban_syntax_error = setLang["BAN_ERROR_SYNTAX"] 73 | languages.ban_error_ac = setLang["BAN_ERROR_AC"] 74 | languages.ban_error_empty = setLang["BAN_EMPTY_ERROR"] 75 | languages.ban_self_ban = setLang["BAN_SELF_BAN"] 76 | return LANGUAGE -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | import sys 6 | import pytz 7 | import logging 8 | from config import Config 9 | from loguru import logger 10 | from telegram.ext import Updater, Defaults 11 | from telegram import ParseMode 12 | from core.commands import index 13 | from plugins import plugin_index 14 | from core import handlers 15 | from core.handlers import handlers_index 16 | from tabulate import tabulate 17 | 18 | # crea la tabella con i dati desiderati 19 | table_data = [ 20 | ["Type", "Description", "Extra"], 21 | ["Version", Config.VERSION, Config.VERSION_NAME], 22 | ["Author", "SquirrelNetwork", Config.REPO], 23 | ["Debug", Config.DEBUG], 24 | ["Plugins", "Enable"] 25 | ] 26 | 27 | # stampa la tabella formattata 28 | 29 | 30 | 31 | 32 | # if version < 3.7, stop bot. 33 | LOGGING = logging.getLogger(__name__) 34 | if sys.version_info[0] < 3 or sys.version_info[1] < 7: 35 | LOGGING.error("You MUST have a python version of at least 3.7! Multiple features depend on this. Bot quitting.") 36 | quit(1) 37 | 38 | # Enable logging (In config.py DEBUG = True enable Debug Logging) 39 | logging.basicConfig(level=(logging.INFO, logging.DEBUG)[Config.DEBUG], format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') 40 | 41 | @logger.catch 42 | def main(): 43 | """Instantiate a Defaults object""" 44 | defaults = Defaults(parse_mode=ParseMode.HTML, tzinfo=pytz.timezone('Europe/Rome')) 45 | updater = Updater(Config.BOT_TOKEN, defaults=defaults, workers=32) 46 | dsp = updater.dispatcher 47 | job_updater = updater.job_queue 48 | 49 | # I load all admin, user and owner commands 50 | index.user_command(dsp) 51 | index.admin_command(dsp) 52 | index.owner_command(dsp) 53 | 54 | #Plugins Section (if in the config.py ENABLE_PLUGINS is True it loads the plugins if ENABLE_PLUGINS is False it does not load them) 55 | if Config.ENABLE_PLUGINS == True : 56 | plugin_index.function_plugins(dsp) 57 | logger.info('Plugin Enabled') 58 | else: 59 | logger.info('Plugin Disabled') 60 | 61 | # I load all handlers, commands without '/' 62 | handlers_index.core_handlers(dsp) 63 | handlers.logs.sys_loggers() 64 | handlers.handlers_index.jobs_handlers(job_updater) 65 | # I load the error handler, when the bot receives an error it sends a private message to the developer 66 | dsp.add_error_handler(handlers.errors.error_handler) 67 | dsp.add_error_handler(handlers.handler_errors.init) 68 | 69 | # Start the Bot Polling 70 | updater.start_polling(poll_interval=1.0, timeout=5.0) 71 | updater.idle() 72 | 73 | if __name__ == '__main__': 74 | main() -------------------------------------------------------------------------------- /plugins/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | """Import Files""" 7 | __all__ = ["distrowatch","search","inspire","plugin_index","weather","wikipedia"] 8 | 9 | from plugins import * -------------------------------------------------------------------------------- /plugins/distrowatch.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | import requests 7 | from core import decorators 8 | from bs4 import BeautifulSoup 9 | from core.utilities.menu import build_menu 10 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup 11 | 12 | @decorators.delete.init 13 | def init(update, context): 14 | bot = context.bot 15 | r = requests.get("https://distrowatch.com/random.php") 16 | parsed_html = BeautifulSoup(r.text, features="html.parser") 17 | distro_long_name = parsed_html.title.string[17:].lower() 18 | distro_name = distro_long_name.split()[0] 19 | distro_url = f'https://distrowatch.com/table.php?distribution={distro_name}' 20 | distro_message = "Here is a random linux distribution: " 21 | button_list = [InlineKeyboardButton("🐧 ▶️ ", url=distro_url)] 22 | reply_markup = InlineKeyboardMarkup(build_menu(button_list, n_cols=1)) 23 | bot.send_message(update.message.chat_id,text=distro_message,reply_markup=reply_markup,parse_mode='HTML') -------------------------------------------------------------------------------- /plugins/inspire.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | import requests 6 | from core import decorators 7 | 8 | @decorators.delete.init 9 | def init(update,context): 10 | bot = context.bot 11 | url = r"http://inspirobot.me/api?generate=true" 12 | get = requests.get(url) 13 | img = get.text 14 | bot.sendPhoto(chat_id=update.effective_chat.id, photo=img, caption="Want another one? click /inspire") -------------------------------------------------------------------------------- /plugins/plugin_index.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | import plugins 7 | from telegram.ext import (CommandHandler as CMH) 8 | 9 | def function_plugins(dsp): 10 | function = dsp.add_handler 11 | function(CMH('distro',plugins.distrowatch.init)) 12 | function(CMH('google',plugins.search.google)) 13 | function(CMH('mdn',plugins.search.mdn)) 14 | function(CMH('ddg',plugins.search.duckduckgo)) 15 | function(CMH('wiki',plugins.wikipedia.init)) 16 | function(CMH('weather',plugins.weather.init)) 17 | function(CMH('inspire',plugins.inspire.init)) -------------------------------------------------------------------------------- /plugins/search.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright SquirrelNetwork 5 | 6 | from core.utilities.menu import build_menu 7 | from core.utilities.message import message 8 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup 9 | 10 | """ 11 | /mdn {terms} 12 | """ 13 | def mdn(update, context): 14 | bot = context.bot 15 | msg=str(update.message.text[4:]).strip() 16 | if msg != "": 17 | main_text = "Here are the results of your MDN search" 18 | gurl = "https://developer.mozilla.org/en-US/search?q={0}".format(msg.replace(' ','+')) 19 | button_list = [InlineKeyboardButton("🔎 Search", url=gurl)] 20 | reply_markup = InlineKeyboardMarkup(build_menu(button_list, n_cols=1)) 21 | bot.send_message(update.message.chat_id,text=main_text,reply_markup=reply_markup,parse_mode='HTML') 22 | else: 23 | message(update,context, text="You need to type a search criteria!\nHow to use the command: /mdn text") 24 | """ 25 | /google {terms} 26 | """ 27 | def google(update, context): 28 | bot = context.bot 29 | msg=str(update.message.text[7:]).strip() 30 | if msg != "": 31 | main_text = "Here are the results of your Google search" 32 | gurl = "https://www.google.com/search?&q={0}".format(msg.replace(' ','+')) 33 | button_list = [InlineKeyboardButton("🔎 Search", url=gurl)] 34 | reply_markup = InlineKeyboardMarkup(build_menu(button_list, n_cols=1)) 35 | bot.send_message(update.message.chat_id,text=main_text,reply_markup=reply_markup,parse_mode='HTML') 36 | else: 37 | message(update,context, text="You need to type a search criteria!\nHow to use the command: /google text") 38 | """ 39 | /ddg {terms} 40 | """ 41 | def duckduckgo(update, context): 42 | bot = context.bot 43 | msg=str(update.message.text[4:]).strip() 44 | if msg != "": 45 | main_text = "Here are the results of your DuckDuckGo search" 46 | gurl = "https://duckduckgo.com/?q={0}".format(msg.replace(' ','+')) 47 | button_list = [InlineKeyboardButton("🔎 Search", url=gurl)] 48 | reply_markup = InlineKeyboardMarkup(build_menu(button_list, n_cols=1)) 49 | bot.send_message(update.message.chat_id,text=main_text,reply_markup=reply_markup,parse_mode='HTML') 50 | else: 51 | message(update,context, text="You need to type a search criteria!\nHow to use the command: /ddg text") -------------------------------------------------------------------------------- /plugins/weather.py: -------------------------------------------------------------------------------- 1 | from pyowm import OWM 2 | from pyowm.commons import exceptions 3 | from config import Config 4 | from core import decorators 5 | from core.utilities.message import message 6 | from languages.getLang import languages 7 | 8 | def sendWeatherMessage(update,context,city,mintemp,maxtemp,humidity,icon): 9 | languages(update,context) 10 | stringMessage = languages.weather_message.format(city,mintemp,maxtemp,humidity,icon) 11 | msg = message(update,context,stringMessage) 12 | return msg 13 | 14 | @decorators.delete.init 15 | def init(update, context): 16 | text = update.message.text[8:].strip().capitalize() 17 | if text != "": 18 | try: 19 | owm = OWM(Config.OPENWEATHER_API) 20 | mgr = owm.weather_manager() 21 | observation = mgr.weather_at_place(text) 22 | w = observation.weather 23 | temp = w.temperature('celsius') 24 | mintemp = temp['temp_min'] 25 | maxtemp = temp['temp_max'] 26 | humidity = w.humidity 27 | status = w.status 28 | if status == 'Clear': 29 | sendWeatherMessage(update,context,text,mintemp,maxtemp,humidity,'☀️') 30 | elif status == 'Clouds': 31 | sendWeatherMessage(update,context,text,mintemp,maxtemp,humidity,'☁️') 32 | elif status == 'Rain': 33 | sendWeatherMessage(update,context,text,mintemp,maxtemp,humidity,'🌧') 34 | elif status == 'Drizzle': 35 | sendWeatherMessage(update,context,text,mintemp,maxtemp,humidity,'🌧') 36 | elif status == 'Mist': 37 | sendWeatherMessage(update,context,text,mintemp,maxtemp,humidity,'🌫') 38 | else: 39 | sendWeatherMessage(update,context,text,mintemp,maxtemp,humidity,status) 40 | except exceptions.NotFoundError: 41 | message(update,context, text="The city you searched for does not exist!") 42 | else: 43 | message(update,context, text="You need to type a search criteria!\nHow to use the command: /weather text") -------------------------------------------------------------------------------- /plugins/wikipedia.py: -------------------------------------------------------------------------------- 1 | import wikipedia as wiki 2 | from core.utilities.message import message 3 | from telegram import InlineKeyboardButton, InlineKeyboardMarkup 4 | from core.utilities.menu import build_menu 5 | from core.database.repository.group import GroupRepository 6 | 7 | def init(update, context): 8 | arg = update.message.text[5:] 9 | chat = update.effective_message.chat_id 10 | group = GroupRepository().getById(chat) 11 | if group is None: 12 | lang = 'EN' 13 | else: 14 | lang = group['languages'] 15 | wiki.set_lang(lang.lower()) 16 | try: 17 | pg = wiki.page(wiki.search(arg)[0]) 18 | title = pg.title 19 | pg_url = pg.url 20 | define = pg.summary 21 | button_list = [InlineKeyboardButton("Go to ==>", url=pg_url)] 22 | reply_markup = InlineKeyboardMarkup(build_menu(button_list, n_cols=1)) 23 | text = "*{}:*\n\n{}".format(title, define) 24 | update.message.reply_markdown(text, reply_markup=reply_markup) 25 | except: 26 | message(update, context, "Sorry {} I didn't find what you were looking for".format(update.message.from_user.first_name)) -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "nebula" 3 | version = "8.6.2" 4 | description = "Open source bot to administer a telegram group with different functionalities and blacklist" 5 | authors = ["SquirrelNetwork"] 6 | license = "Apache 2.0" 7 | readme = "README.md" 8 | 9 | [tool.poetry.dependencies] 10 | python = "3.9.2" 11 | pandas = "^1.4.4" 12 | matplotlib = "^3.5.3" 13 | PyMySQL = "^1.0.2" 14 | python-telegram-bot = "^13.14" 15 | telegram = "^0.0.1" 16 | psutil = "^5.9.2" 17 | loguru = "^0.6.0" 18 | pyowm = "^3.3.0" 19 | PyPika = "^0.48.9" 20 | wikipedia = "^1.4.0" 21 | beautifulsoup4 = "^4.11.1" 22 | pip = "^22.2.2" 23 | SQLAlchemy = "^1.4.40" 24 | 25 | 26 | [build-system] 27 | requires = ["poetry-core"] 28 | build-backend = "poetry.core.masonry.api" 29 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | APScheduler==3.6.3 2 | async-timeout==4.0.2 3 | beautifulsoup4==4.11.1 4 | cachetools==4.2.2 5 | certifi==2022.9.24 6 | charset-normalizer==2.1.1 7 | contourpy==1.0.5 8 | cycler==0.11.0 9 | Deprecated==1.2.13 10 | fonttools==4.38.0 11 | geojson==2.5.0 12 | greenlet==1.1.3.post0 13 | idna==3.4 14 | kiwisolver==1.4.4 15 | loguru==0.6.0 16 | matplotlib==3.6.1 17 | numpy==1.23.4 18 | packaging==21.3 19 | pandas==1.5.1 20 | Pillow==9.2.0 21 | psutil==5.9.3 22 | PyMySQL==1.0.2 23 | pyowm==3.3.0 24 | pyparsing==3.0.9 25 | PyPika==0.48.9 26 | PySocks==1.7.1 27 | python-dateutil==2.8.2 28 | python-dotenv==0.21.0 29 | python-telegram-bot==13.14 30 | pytz==2022.5 31 | pytz-deprecation-shim==0.1.0.post0 32 | redis==4.5.3 33 | requests==2.28.1 34 | six==1.16.0 35 | soupsieve==2.3.2.post1 36 | SQLAlchemy==1.4.42 37 | telegram==0.0.1 38 | tornado==6.1 39 | tzdata==2022.5 40 | tzlocal==4.2 41 | urllib3==1.26.12 42 | wikipedia==1.4.0 43 | wrapt==1.14.1 44 | -------------------------------------------------------------------------------- /runtime.txt: -------------------------------------------------------------------------------- 1 | python-3.9.6 --------------------------------------------------------------------------------