Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
232 lines (197 sloc) 9.12 KB
# -*- coding: utf-8 -*-
from flask import Blueprint, render_template, redirect, url_for, make_response, request, flash, jsonify, current_app
from flask_login import login_required, current_user
from sqlalchemy import or_
from ..extensions import db
from ..utils import timesince
from ..user.models import Event, Project, Category, Activity
from ..aggregation import GetProjectData
from datetime import datetime
from flask import Response, stream_with_context
import io, csv, json, sys
PY3 = sys.version_info[0] == 3
blueprint = Blueprint('api', __name__, url_prefix='/api')
def get_projects_by_event(event_id):
return Project.query.filter_by(event_id=event_id, is_hidden=False)
def get_project_summaries(projects):
summaries = [ for p in projects ]
summaries.sort(key=lambda x: x['score'], reverse=True)
return summaries
# Collect all projects for an event
def project_list(event_id):
projects = get_projects_by_event(event_id).filter(Project.progress >= 0)
return get_project_summaries(projects)
# Collect all challenges for an event
def challenges_list(event_id):
projects = get_projects_by_event(event_id).filter(Project.progress < 0)
return get_project_summaries(projects)
# Generate a CSV file
def gen_csv(csvdata):
headerline = csvdata[0].keys()
if PY3:
output = io.StringIO()
output = io.BytesIO()
headerline = [l.encode('utf-8') for l in headerline]
writer = csv.writer(output, quoting=csv.QUOTE_NONNUMERIC)
for rk in csvdata:
rkline = []
for l in rk.values():
if l is None:
elif isinstance(l, (int, float, datetime)):
return output.getvalue()
# ------ EVENT INFORMATION ---------
# API: Outputs JSON about the current event
def info_current_event_json():
event = Event.query.filter_by(is_current=True).first()
return jsonify(, timeuntil=timesince(event.countdown, until=True))
# API: Outputs JSON about an event
def info_event_json(event_id):
event = Event.query.filter_by(id=event_id).first_or_404()
return jsonify(, timeuntil=timesince(event.countdown, until=True))
# API: Outputs JSON-LD about an Event according to specification
def info_event_hackathon_json(event_id):
event = Event.query.filter_by(id=event_id).first_or_404()
return jsonify(event.get_schema(request.host_url))
# ------ EVENT PROJECTS ---------
# API: Outputs JSON of projects in the current event, along with its info
def project_list_current_json():
event = Event.query.filter_by(is_current=True).first()
return jsonify(projects=project_list(,
# API: Outputs JSON of all projects at a specific event
def project_list_json(event_id):
return jsonify(projects=project_list(event_id))
# API: Outputs CSV of all projects in an event
def project_list_csv(event_id):
return Response(stream_with_context(gen_csv(project_list(event_id))),
headers={'Content-Disposition': 'attachment; filename=project_list.csv'})
# API: Outputs JSON of ideas/challenges in the current event, along with its info
def challenges_list_current_json():
event = Event.query.filter_by(is_current=True).first()
return jsonify(challenges=challenges_list(,
# API: Outputs JSON of categories in the current event
def categories_list_current_json():
event = Event.query.filter_by(is_current=True).first()
return jsonify(categories=[ for c in event.categories_for_event() ],
# ------ ACTIVITY FEEDS ---------
def get_event_activities(event_id):
event = Event.query.filter_by(id=event_id).first_or_404()
return [ for a in Activity.query
# API: Outputs JSON of recent activity in an event
def event_activity_json(event_id):
return jsonify(activities=get_event_activities(event_id))
# API: Outputs CSV of an event activity
def event_activity_csv(event_id):
return Response(stream_with_context(gen_csv(get_event_activities(event_id))),
headers={'Content-Disposition': 'attachment; filename=activity_list.csv'})
# API: Outputs JSON of recent activity
def projects_activity_json():
activities = [ for a in Activity.query.order_by(]
return jsonify(activities=activities)
# API: Outputs JSON of recent activity of a project
def project_activity_json(project_id):
project = Project.query.filter_by(id=project_id).first_or_404()
query = Activity.query.filter_by(
activities = [ for a in query]
return jsonify(, activities=activities)
# API: Outputs JSON info for a specific project
def project_info_json(project_id):
project = Project.query.filter_by(id=project_id).first_or_404()
return jsonify(,
# ------ SEARCH ---------
# API: Full text search projects
def project_search_json():
q = request.args.get('q')
if q is None or len(q) < 3: return jsonify(projects=[])
q = "%%%s%%" % q
projects = Project.query.filter(or_(,,,
return jsonify(projects=[ for p in projects])
# ------ UPDATE ---------
# API: Pushes data into a project
@blueprint.route('/project/push.json', methods=["PUT", "POST"])
def project_push_json():
data = request.get_json(force=True)
if not 'key' in data or data['key'] != current_app.config['DRIBDAT_APIKEY']:
return jsonify(error='Invalid key')
project = Project.query.filter_by(hashtag=data['hashtag']).first()
if not project:
project = Project()
project.user_id = 1
project.progress = 0
project.is_autoupdate = True
project.event = Event.query.filter_by(is_current=True).first()
elif project.user_id != 1 or project.is_hidden or not project.is_autoupdate:
return jsonify(error='Access denied')
project.hashtag = data['hashtag']
if 'name' in data and len(data['name']) > 0: = data['name']
else: = project.hashtag.replace('-', ' ')
if 'summary' in data and len(data['summary']) > 0:
project.summary = data['summary']
hasLongtext = 'longtext' in data and len(data['longtext']) > 0
if hasLongtext:
project.longtext = data['longtext']
if 'autotext_url' in data and data['autotext_url'].startswith('http'):
project.autotext_url = data['autotext_url']
if not project.source_url or project.source_url is '':
project.source_url = data['autotext_url']
if 'levelup' in data and 0 < project.progress + data['levelup'] * 10 < 50: # MAX progress
project.progress = project.progress + data['levelup'] * 10
# return jsonify(data=data)
if project.autotext_url is not None and not hasLongtext:
# Now try to autosync
data = GetProjectData(project.autotext_url)
if 'name' in data:
if len(data['name']) > 0: = data['name']
if 'summary' in data and len(data['summary']) > 0:
project.summary = data['summary']
if 'description' in data and len(data['description']) > 0:
project.longtext = data['description']
if 'homepage_url' in data and len(data['homepage_url']) > 0:
project.webpage_url = data['homepage_url']
if 'source_url' in data and len(data['source_url']) > 0:
project.source_url = data['source_url']
if 'image_url' in data and len(data['image_url']) > 0:
project.image_url = data['image_url']
return jsonify(success='Updated',
# ------ FRONTEND -------
# API routine used to sync project data
@blueprint.route('/project/autofill', methods=['GET', 'POST'])
def project_autofill():
url = request.args.get('url')
data = GetProjectData(url)
return jsonify(data)