summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitignore155
-rw-r--r--api/__init__.py74
-rw-r--r--api/db.py56
-rw-r--r--api/schema.sql8
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