commit e07a749e4ac2f5ac7b87c0935aab5e6ffc0f1b04 Author: Benjamin Bouvier Date: Fri Dec 29 13:10:25 2017 +0100 Initial commit; diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0a5f25d --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +venv +__pycache__ +db.sqlite diff --git a/main.py b/main.py new file mode 100644 index 0000000..6f69e32 --- /dev/null +++ b/main.py @@ -0,0 +1,121 @@ +import json +import dateutil +from datetime import datetime, timezone + +from flask import Flask, request, abort +from feedgen.feed import FeedGenerator + +from pony import orm +from pony.orm import Required, Optional, Set + +app = Flask(__name__) + +SITE_URL = 'http://localhost:5000/feeds/' + +db = orm.Database() + +class Feed(db.Entity): + slug = Required(str, unique=True) + admin_token = Required(str) + title = Required(str) + atom_id = Required(str) # also link + description = Required(str) + login = Optional(str) + password = Optional(str) + items = Set('Item') + +class Item(db.Entity): + feed = Required(Feed) + atom_id = Required(str) + title = Required(str) + content = Required(str) + date = Required(datetime) + +db.bind(provider='sqlite', filename='db.sqlite', create_db=True) +db.generate_mapping(create_tables=True) +orm.set_sql_debug(True) + +def does_slug_exist(slug): + with orm.db_session: + return len(orm.select(f for f in Feed if f.slug == slug)[:1]) + +@app.route('/feeds', methods=['POST']) +def add_feed(): + data = request.get_json(silent=True) + + if 'slug' not in data: + abort(400, 'missing slug') + + slug = data['slug'] + + if does_slug_exist(slug): + abort(400, "feed with this slug already exists") + + if 'title' not in data or 'description' not in data or 'admin_token' not in data: + abort(400, "missing title or description or admin_token") + + url = SITE_URL + slug + + with orm.db_session: + feed = Feed(slug=slug, + admin_token=data['admin_token'], + title=data['title'], + atom_id=url, + description=data['description']) + + if 'login' in data and 'password' in data: + feed.login = data['login'] + feed.password = data['password'] + + return "OK" + +@app.route('/feeds/', methods=['GET', 'POST']) +@orm.db_session +def by_feed_name(slug): + if not does_slug_exist(slug): + abort(404, "unknown slug") + + feed = orm.select(f for f in Feed if f.slug == slug)[:1][0] + + if feed.password is not '': + auth = request.authorization + if not auth or auth.username != feed.login or auth.password != feed.password: + abort(401, "missing or incorrect password") + + if request.method == 'POST': + data = request.get_json(silent=True) + + if 'title' not in data or 'content' not in data or 'admin_token' not in data: + abort(400, "missing title or content") + + if data['admin_token'] != feed.admin_token: + abort(401, "incorrect admin_token") + + item_id = feed.atom_id + '/' + str(len(feed.items)) + date = datetime.now(dateutil.tz.tzutc()) + + with orm.db_session: + item = Item(feed=feed, + atom_id=item_id, + title=data['title'], + content=data['content'], + date=date) + + return "OK" + + gen = FeedGenerator() + gen.title(feed.title) + gen.id(feed.atom_id) + gen.link(href=feed.atom_id) + gen.description(feed.description) + + for item in feed.items: + fe = gen.add_entry() + fe.id(item.atom_id) + fe.title(item.title) + fe.content(item.content) + + date = item.date.replace(tzinfo=timezone.utc) + fe.updated(date) + + return gen.atom_str(pretty=True).decode('utf8') diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7e19f8b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +Flask +feedgen +pony