diff options
-rw-r--r-- | .gitignore | 155 | ||||
-rw-r--r-- | api/__init__.py | 74 | ||||
-rw-r--r-- | api/db.py | 56 | ||||
-rw-r--r-- | api/schema.sql | 8 |
4 files changed, 293 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6d979ed --- /dev/null +++ b/.gitignore @@ -0,0 +1,155 @@ +# 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 + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.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/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +# ignore config file +config.json diff --git a/api/__init__.py b/api/__init__.py new file mode 100644 index 0000000..73e2135 --- /dev/null +++ b/api/__init__.py @@ -0,0 +1,74 @@ +import os +import json +from flask import Flask, request, abort +import socket + +addr = "/tmp/bot.sock" + +def create_app(test_config=None): + # create and configure the app + app = Flask(__name__, instance_relative_config=True) + app.config.from_mapping( + SECRET_KEY='dev', + DATABASE=os.path.join(app.instance_path, 'api.sqlite'), + ) + + if test_config is None: + # load the instance config, if it exists, when not testing + app.config.from_pyfile('config.py', silent=True) + else: + # load the test config if passed in + app.config.from_mapping(test_config) + + # ensure the instance folder exists + try: + os.makedirs(app.instance_path) + except OSError: + pass + + from . import db + db.init_app(app) + + # a simple page that says hello + @app.route('/hello') + def hello(): + return 'Hello, World!' + @app.route('/webhook', methods=['POST']) + def webhook(): + if request.method == 'POST': + data = request.json + if 'apikey' in data: + con = db.get_db() + cur = con.cursor() + cur.execute("SELECT owner FROM keys WHERE key=?",(data['apikey'],)) + if cur.fetchone() and 'say' in data: + skt = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + try: + skt.connect(addr) + skt.send(bytes(data['say'], 'UTF-8')) + r = skt.recv(16) + if r == "NACK": + abort(451) + else: + pass + + except Exception as e: + print(e) + abort(500) + finally: + skt.close() + + + db.close_db() + + else: + abort(403) + else: + abort(404) + + + + return "Webhook received!" + + + return app diff --git a/api/db.py b/api/db.py new file mode 100644 index 0000000..64a0b93 --- /dev/null +++ b/api/db.py @@ -0,0 +1,56 @@ +import sqlite3 +import secrets +import click +from flask import current_app, g +from flask.cli import with_appcontext + + +def get_db(): + if 'db' not in g: + g.db = sqlite3.connect( + current_app.config['DATABASE'], + detect_types=sqlite3.PARSE_DECLTYPES + ) + g.db.row_factory = sqlite3.Row + + return g.db + + +def close_db(e=None): + db = g.pop('db', None) + + if db is not None: + db.close() + +def init_db(): + db = get_db() + + with current_app.open_resource('schema.sql') as f: + db.executescript(f.read().decode('utf8')) + + +def init_app(app): + app.teardown_appcontext(close_db) + app.cli.add_command(init_db_command) + app.cli.add_command(gen_key) + +@click.command('init-db') +@with_appcontext +def init_db_command(): + """Clear the existing data and create new tables.""" + init_db() + click.echo('Initialized the database.') + + +@click.command('gen-key') +@click.argument('ou') +@with_appcontext +def gen_key(ou): + db = get_db() + cur = db.cursor() + nwkey = secrets.token_hex(64) + cur.execute("INSERT INTO keys VALUES (NULL,?,?)", (nwkey, ou,)) + s = f"Owner: {ou}\n Key: {nwkey}\n" + click.echo(s) + db.commit() + close_db() diff --git a/api/schema.sql b/api/schema.sql new file mode 100644 index 0000000..c7a6520 --- /dev/null +++ b/api/schema.sql @@ -0,0 +1,8 @@ +DROP TABLE IF EXISTS keys; + +CREATE TABLE keys ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + key VARCHAR(64) UNIQUE NOT NULL, + owner TEXT NOT NULL + +); \ No newline at end of file |