From 94750f244733a6a3474a3c5f74dd331342b7e1be Mon Sep 17 00:00:00 2001 From: timotheyca Date: Mon, 29 Nov 2021 00:12:19 +0300 Subject: [PATCH] initial commit --- .gitignore | 215 ++++++++++++++++++ .idea/.gitignore | 8 + .idea/inspectionProfiles/Project_Default.xml | 51 +++++ .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 4 + .idea/modules.xml | 8 + .idea/v6d3losyash.iml | 10 + .idea/vcs.xml | 6 + Dockerfile | 8 + requirements.txt | 4 + v6d3losyash/__init__.py | 0 v6d3losyash/app.py | 44 ++++ v6d3losyash/config.py | 7 + v6d3losyash/run-bot.py | 87 +++++++ v6d3losyash/stop-bot.py | 18 ++ 15 files changed, 476 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/v6d3losyash.iml create mode 100644 .idea/vcs.xml create mode 100644 Dockerfile create mode 100644 requirements.txt create mode 100644 v6d3losyash/__init__.py create mode 100644 v6d3losyash/app.py create mode 100644 v6d3losyash/config.py create mode 100644 v6d3losyash/run-bot.py create mode 100644 v6d3losyash/stop-bot.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..12e4ba6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,215 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + + + +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + + +/data/ diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..73f69e0 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..69f4ba6 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,51 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..467204e --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..47f83e3 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/v6d3losyash.iml b/.idea/v6d3losyash.iml new file mode 100644 index 0000000..74d515a --- /dev/null +++ b/.idea/v6d3losyash.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..36dcf70 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,8 @@ +# syntax=docker/dockerfile:1 +FROM python:3.9 +WORKDIR /v6 +ENV v6root=/v6data +COPY requirements.txt requirements.txt +RUN pip install -r requirements.txt +COPY v6d3losyash v6d3losyash +CMD ["python3", "-m", "v6d3losyash.run-bot"] diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..8ae8314 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +aiohttp +discord.py~=1.7.3 +git+https://gitea.ongoteam.net/PTV/v6d0auth.git +git+https://gitea.ongoteam.net/PTV/v6d1tokens.git diff --git a/v6d3losyash/__init__.py b/v6d3losyash/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/v6d3losyash/app.py b/v6d3losyash/app.py new file mode 100644 index 0000000..ba9ed5a --- /dev/null +++ b/v6d3losyash/app.py @@ -0,0 +1,44 @@ +import time + +# noinspection PyPackageRequirements +import discord +from aiohttp import web +from nacl.exceptions import BadSignatureError +from v6d0auth import certs + + +def define_routes(routes: web.RouteTableDef, client: discord.Client): + @routes.get('/') + async def home(_request: web.Request): + return web.Response(body='v6d3losyash\n') + + @routes.post('/stop') + async def stop(request: web.Request): + try: + assert abs(float(certs.verify(await request.read())) - time.time()) < 1 + except ValueError: + raise web.HTTPBadRequest + except BadSignatureError: + raise web.HTTPUnauthorized + except AssertionError: + raise web.HTTPRequestTimeout + else: + await client.change_presence(status=discord.Status.offline) + await client.close() + raise web.HTTPOk + + +def app_routes(client: discord.Client) -> web.RouteTableDef: + routes = web.RouteTableDef() + define_routes(routes, client) + return routes + + +def app_with_routes(routes: web.RouteTableDef): + app = web.Application() + app.add_routes(routes) + return app + + +def get_app(client: discord.Client) -> web.Application: + return app_with_routes(app_routes(client)) diff --git a/v6d3losyash/config.py b/v6d3losyash/config.py new file mode 100644 index 0000000..d420e7a --- /dev/null +++ b/v6d3losyash/config.py @@ -0,0 +1,7 @@ +import os + +guild = int(os.getenv('v6guild', 541241763042689025)) +emoji = int(os.getenv('v6emoji', 586669134406877270)) +role = int(os.getenv('v6role', 643896112977018880)) +message = int(os.getenv('v6message', 825385619097518110)) +channel = int(os.getenv('v6channel', 876814972968116224)) diff --git a/v6d3losyash/run-bot.py b/v6d3losyash/run-bot.py new file mode 100644 index 0000000..24f054f --- /dev/null +++ b/v6d3losyash/run-bot.py @@ -0,0 +1,87 @@ +import asyncio +from io import StringIO + +# noinspection PyPackageRequirements +import discord +from v6d0auth.run_app import start_app +from v6d1tokens.client import request_token + +from v6d3losyash import config +from v6d3losyash.app import get_app + +loop = asyncio.get_event_loop() +token = loop.run_until_complete(request_token('losyash')) +client = discord.Client( + intents=discord.Intents( + members=True, + guilds=True, + emojis=True, + reactions=True, + invites=True, + bans=True, + ), +) +ESCAPED = '`_*\'"\\' + + +def escape(s: str): + res = StringIO() + for c in s: + if c in ESCAPED: + c = '\\' + c + res.write(c) + return res.getvalue() + + +@client.event +async def on_ready(): + print("ready") + await client.change_presence(activity=discord.Game( + name='феноменально', + )) + + +@client.event +async def on_raw_reaction_add(payload: discord.RawReactionActionEvent): + emoji: discord.Emoji = payload.emoji + if emoji.id != config.emoji: + return + if payload.message_id != config.message: + return + guild: discord.Guild = client.get_guild(config.guild) + member: discord.Member = guild.get_member(payload.user_id) + role = guild.get_role(config.role) + if role in member.roles: + return + await member.add_roles(role, reason='феноменально') + + channel: discord.TextChannel = guild.get_channel(config.channel) + await channel.send(f'{escape(str(member))} <:Jesus:586669134406877270>') + + +@client.event +async def on_member_join(member: discord.Member): + guild: discord.Guild = member.guild + if guild.id != config.guild: + return + channel: discord.TextChannel = guild.get_channel(config.channel) + await channel.send(f'{escape(str(member))} joined') + + +@client.event +async def on_member_remove(member: discord.Member): + guild: discord.Guild = member.guild + if guild.id != config.guild: + return + channel: discord.TextChannel = guild.get_channel(config.channel) + await channel.send(f'{escape(str(member))} left') + + +async def main(): + await start_app(get_app(client)) + await client.login(token) + await client.connect() + + +if __name__ == '__main__': + loop.run_until_complete(main()) diff --git a/v6d3losyash/stop-bot.py b/v6d3losyash/stop-bot.py new file mode 100644 index 0000000..8ba72a9 --- /dev/null +++ b/v6d3losyash/stop-bot.py @@ -0,0 +1,18 @@ +import asyncio +import time + +import aiohttp +from v6d0auth import certs +from v6d0auth.config import host, port + + +async def main(): + request = certs.sign(str(time.time()).encode()) + async with aiohttp.ClientSession() as session: + # noinspection HttpUrlsUsage + async with session.post(f'http://{host}:{port}/stop', data=request) as response: + print(response.status) + + +if __name__ == '__main__': + asyncio.run(main())