diff --git a/.env b/.env deleted file mode 100644 index e69de29..0000000 diff --git a/.gitignore b/.gitignore index f7275bb..71d4498 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ venv/ +__pycache__/ +pip-selfcheck.json diff --git a/README.md b/README.md new file mode 100644 index 0000000..3fe0930 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# API endpoints: + +Base url = `https://corder.tech` + + +| Endpoint | Return | Implemented? | +| ---------------------------------- | ------------------------------- | ------------ | +| `/mocha/users/{user_id}` | row with the given user | Yes | +| `/mocha/users/*` | all rows | Yes | +| `/mocha/top/{n}` | users with the n highest scores | No | +| `/mocha/set/{user_id}/{num_steps}` | 200 OK if successful | No | diff --git a/RUN_THIS_TO_SETUP_VENV.sh b/RUN_THIS_TO_SETUP_VENV.sh deleted file mode 100755 index 06ecb8f..0000000 --- a/RUN_THIS_TO_SETUP_VENV.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/bash - -set -e -source "./venv/bin/activate" -pip install -Ur ./requirements.txt diff --git "a/\\" "b/\\" deleted file mode 100644 index fd0ee7e..0000000 --- "a/\\" +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/env python3 -""" -Handle API requests to the database -""" -import json -import sqlite3 - - -# DATABASE = '/usr/local/www/mocha-server/mocha.db' -DATABASE = 'mocha.db' - -conn = sqlite3.connect(DATABASE) -conn.row_factory = sqlite3.Row -cursor = conn.cursor() - - - -# TODO: Add fetching of list of users -# TODO: Add fetching of top N users by score -# TODO: Add ability to store and retrieve avatars (as image files?) - -def get_top_N(search_parameter, N): - """ - - """ - cursor.execute("select * from users order by p0 desc limit p1", {'p0':search_parameter, 'p1':N}) - conn.commit() - conn.close() - - -# add new parameters as needed -def update_row(user_id, updated_username): - print() - -def insert_row(user_id, username): - """ - Inserts a row for a NEW user with given parameters - This may work better with AUTOINCREMENT to avoid arbitrary ids and duplicates - """ - - cursor.execute("insert into users values (?,?)", (user_id, username)) - conn.commit() - conn.close() - - -def fetch_user(user_id): - """ - Returns a JSON object containing the requested user - Also can return a list of all users if user_id == "*" - """ - - if user_id != '*': # must use (?), (item,) format - cursor.execute("SELECT * FROM users WHERE user_id=(?)", (user_id,)) - else: - cursor.execute("SELECT * FROM users") - - output = cursor.fetchall() - output = json.dumps([dict(row) for row in output]) - conn.close() - - if output == '[]': - output = None - - return output - - -def process_request(uri): - """ - Handles the API endpoint. - Currently supports: - - /mocha/users/"user_id" Returns JSON of the specified user - - /mocha/users/* Returns JSON list of all users - """ - parts = uri.split('/')[1:] - assert parts[0] == 'mocha' - - output = None - - if parts[1] == 'users': - output = fetch_user(parts[2]) - - return output - - - -def application(environ, start_response): - """ - mod_wsgi entry point - """ - status = '200 OK' - output = process_request(environ['REQUEST_URI']) - - if output is None: - status = '404 Not Found' - output = '' - - output = output.encode('UTF-8') - - response_headers = [('Content-type', 'application/json'), - ('Content-Length', str(len(output)))] - - start_response(status, response_headers) - - return [output] diff --git a/__pycache__/mocha.cpython-36.pyc b/__pycache__/mocha.cpython-36.pyc deleted file mode 100644 index 402920d..0000000 Binary files a/__pycache__/mocha.cpython-36.pyc and /dev/null differ diff --git a/manage.py b/manage.py deleted file mode 100755 index 72b3b98..0000000 --- a/manage.py +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env python -import os -import sys - -if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mochaserver.settings") - try: - from django.core.management import execute_from_command_line - except ImportError as exc: - raise ImportError( - "Couldn't import Django. Are you sure it's installed and " - "available on your PYTHONPATH environment variable? Did you " - "forget to activate a virtual environment?" - ) from exc - execute_from_command_line(sys.argv) diff --git a/mocha.db b/mocha.db deleted file mode 100644 index 0a4abfe..0000000 Binary files a/mocha.db and /dev/null differ diff --git a/mocha_server.py b/mocha_server.py index 2a2f009..a61f8cd 100755 --- a/mocha_server.py +++ b/mocha_server.py @@ -1,46 +1,35 @@ #!/usr/bin/env python3 -""" +''' Handle API requests to the database -""" +''' + import json import sqlite3 +from os import path -# NOTE: closing a database makes the next query in a script not work +DATABASE = '/usr/local/www/mocha-server/mocha.db' +if not path.exists(DATABASE): + DATABASE = 'mocha.db' -# DATABASE = '/usr/local/www/mocha-server/mocha.db' -DATABASE = 'mocha.db' - -conn = sqlite3.connect(DATABASE) -conn.row_factory = sqlite3.Row -cursor = conn.cursor() - - -# TODO: Add fetching of list of users # TODO: Add fetching of top N users by score # TODO: Add ability to store and retrieve avatars (as image files?) -def update_steps(user_id, steps): - """ - Overwrites the old raw_steps value. - This can be changed to increment it if needed. - """ - cursor.execute("update users set raw_steps=? where user_id=?", (steps, user_id)) - conn.commit() - - -def get_users(username_list): - """ - Gets a list of users searching by name. - This can also easily be done by user_id. - """ +def fetch_users(user_ids): + ''' + Gets a list of users searching by name. + This can also easily be done by user_id. + ''' + conn = sqlite3.connect(DATABASE) + conn.row_factory = sqlite3.Row + cursor = conn.cursor() output = [] - for usr in username_list: - cursor.execute("select * from users where username=(?)", (usr,)) + for user_id in user_ids: + cursor.execute('select * from users where user_id=(?)', (user_id, )) output += cursor.fetchall() output = json.dumps([dict(row) for row in output]) conn.commit() - #conn.close() + conn.close() if output == '[]': output = None @@ -48,24 +37,32 @@ def get_users(username_list): return output -def get_top_N(search_parameter, desc, N): - """ +def get_top_n(search_parameter, desc, num): + ''' In progress. - Currently the query seems to work, but returning a dict does not preserve order. + Currently the query seems to work, but returning a dict does not + preserve order. - Store an orderd id list and put that in the json? - """ - if desc == True: - cursor.execute("select * from users order by ? desc limit ?", (search_parameter, N)) + Store an orderd id list and put that in the json? + + Alternatively, sort on the client-side. + ''' + conn = sqlite3.connect(DATABASE) + conn.row_factory = sqlite3.Row + cursor = conn.cursor() + if desc: + cursor.execute('select * from users order by ? desc limit ?', + (search_parameter, num)) else: - cursor.execute("select * from users order by ? asc limit ?", (search_parameter, N)) + cursor.execute('select * from users order by ? asc limit ?', + (search_parameter, num)) output = cursor.fetchall() - #print(output) + # print(output) output = json.dumps([dict(row) for row in output]) conn.commit() - #conn.close() + conn.close() if output == '[]': output = None @@ -74,35 +71,48 @@ def get_top_N(search_parameter, desc, N): # add new parameters as needed -def update_row(user_id, updated_username): +def update_row(_user_id, _updated_username): + ''' + WIP. + Will add a new user. + ''' print() def insert_row(user_id, username): - """ - Inserts a row for a NEW user with given parameters - This may work better with AUTOINCREMENT to avoid arbitrary ids and duplicates - """ - cursor.execute("insert into users values (?,?)", (user_id, username)) + ''' + Inserts a row for a NEW user with given parameters + This may work better with AUTOINCREMENT to avoid arbitrary ids and + duplicates. + + Alternatively, use randomized unique IDs. + ''' + + conn = sqlite3.connect(DATABASE) + conn.row_factory = sqlite3.Row + cursor = conn.cursor() + cursor.execute('insert into users values (?,?)', (user_id, username)) conn.commit() - #conn.close() + conn.close() def fetch_user(user_id): - """ + ''' Returns a JSON object containing the requested user - Also can return a list of all users if user_id == "*" - """ - - if user_id != '*': # must use (?), (item,) format - cursor.execute("SELECT * FROM users WHERE user_id=(?)", (user_id,)) + Also can return a list of all users if user_id == '*' + ''' + conn = sqlite3.connect(DATABASE) + conn.row_factory = sqlite3.Row + cursor = conn.cursor() + if user_id != '*': # must use (?), (item,) format + cursor.execute('SELECT * FROM users WHERE user_id=(?)', (user_id, )) else: - cursor.execute("SELECT * FROM users") + cursor.execute('SELECT * FROM users') output = cursor.fetchall() output = json.dumps([dict(row) for row in output]) conn.commit() - #conn.close() + conn.close() if output == '[]': output = None @@ -110,28 +120,43 @@ def fetch_user(user_id): return output +def fetch_top_n(num): + ''' + Retrieves the top n users by score. + ''' + output = get_top_n('score', True, num) + return output + + def process_request(uri): - """ + ''' Handles the API endpoint. Currently supports: - - /mocha/users/"user_id" Returns JSON of the specified user + - /mocha/users/{user_id} Returns JSON of the specified user - /mocha/users/* Returns JSON list of all users - """ + ''' parts = uri.split('/')[1:] assert parts[0] == 'mocha' output = None - if parts[1] == 'users': - output = fetch_user(parts[2]) + if parts[1] == 'users' and len(parts) > 2: + if ',' in parts[2]: + output = fetch_users(parts[2].split(',')) + else: + output = fetch_user(parts[2]) + elif parts[1] == 'top' and len(parts) > 2: + output = fetch_top_n(parts[2]) + else: + output = None return output def application(environ, start_response): - """ + ''' mod_wsgi entry point - """ + ''' status = '200 OK' output = process_request(environ['REQUEST_URI']) @@ -147,3 +172,11 @@ def application(environ, start_response): start_response(status, response_headers) return [output] + + +if __name__ == '__main__': + USERNAMES = ['andrew', 'Corder'] + print(fetch_users(USERNAMES)) + + +# vim: tabstop=4 shiftwidth=4 softtabstop=4 expandtab diff --git a/mochaserver/__init__.py b/mochaserver/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/mochaserver/__pycache__/__init__.cpython-36.pyc b/mochaserver/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index 741e871..0000000 Binary files a/mochaserver/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/mochaserver/__pycache__/settings.cpython-36.pyc b/mochaserver/__pycache__/settings.cpython-36.pyc deleted file mode 100644 index 9262b49..0000000 Binary files a/mochaserver/__pycache__/settings.cpython-36.pyc and /dev/null differ diff --git a/mochaserver/__pycache__/urls.cpython-36.pyc b/mochaserver/__pycache__/urls.cpython-36.pyc deleted file mode 100644 index 6eff192..0000000 Binary files a/mochaserver/__pycache__/urls.cpython-36.pyc and /dev/null differ diff --git a/mochaserver/__pycache__/wsgi.cpython-36.pyc b/mochaserver/__pycache__/wsgi.cpython-36.pyc deleted file mode 100644 index 911b8d1..0000000 Binary files a/mochaserver/__pycache__/wsgi.cpython-36.pyc and /dev/null differ diff --git a/mochaserver/settings.py b/mochaserver/settings.py deleted file mode 100644 index 8a83eec..0000000 --- a/mochaserver/settings.py +++ /dev/null @@ -1,120 +0,0 @@ -""" -Django settings for mochaserver project. - -Generated by 'django-admin startproject' using Django 2.0.4. - -For more information on this file, see -https://docs.djangoproject.com/en/2.0/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/2.0/ref/settings/ -""" - -import os - -# Build paths inside the project like this: os.path.join(BASE_DIR, ...) -BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - - -# Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/ - -# SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = '(vy6o!asl(q@de1ee9#cy7fdw@4$!cn^j84pg97gai8nj$4h4i' - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True - -ALLOWED_HOSTS = [] - - -# Application definition - -INSTALLED_APPS = [ - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', -] - -MIDDLEWARE = [ - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', -] - -ROOT_URLCONF = 'mochaserver.urls' - -TEMPLATES = [ - { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', - ], - }, - }, -] - -WSGI_APPLICATION = 'mochaserver.wsgi.application' - - -# Database -# https://docs.djangoproject.com/en/2.0/ref/settings/#databases - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), - } -} - - -# Password validation -# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators - -AUTH_PASSWORD_VALIDATORS = [ - { - 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', - }, -] - - -# Internationalization -# https://docs.djangoproject.com/en/2.0/topics/i18n/ - -LANGUAGE_CODE = 'en-us' - -TIME_ZONE = 'UTC' - -USE_I18N = True - -USE_L10N = True - -USE_TZ = True - - -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/2.0/howto/static-files/ - -STATIC_URL = '/static/' diff --git a/mochaserver/urls.py b/mochaserver/urls.py deleted file mode 100644 index 4ea6928..0000000 --- a/mochaserver/urls.py +++ /dev/null @@ -1,21 +0,0 @@ -"""mochaserver URL Configuration - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/2.0/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: path('', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.urls import include, path - 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) -""" -from django.contrib import admin -from django.urls import path - -urlpatterns = [ - path('admin/', admin.site.urls), -] diff --git a/mochaserver/wsgi.py b/mochaserver/wsgi.py deleted file mode 100644 index e092bf0..0000000 --- a/mochaserver/wsgi.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -WSGI config for mochaserver project. - -It exposes the WSGI callable as a module-level variable named ``application``. - -For more information on this file, see -https://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/ -""" - -import os - -from django.core.wsgi import get_wsgi_application - -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mochaserver.settings") - -application = get_wsgi_application() diff --git a/pip-selfcheck.json b/pip-selfcheck.json deleted file mode 100644 index 72a077b..0000000 --- a/pip-selfcheck.json +++ /dev/null @@ -1 +0,0 @@ -{"last_check":"2018-04-06T05:49:45Z","pypi_version":"9.0.3"} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index e7042e2..e69de29 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +0,0 @@ -Django==2.0.4 -django-environ==0.4.4 -pytz==2018.3 -six==1.11.0