FitTrackee/mpwo_api/mpwo_api/activities/activities.py

305 lines
9.0 KiB
Python
Raw Normal View History

2018-05-01 17:51:38 +02:00
import json
2018-05-09 18:54:30 +02:00
import os
2018-01-21 17:43:13 +01:00
2018-05-09 18:23:17 +02:00
from flask import Blueprint, jsonify, request
2018-05-01 17:51:38 +02:00
from mpwo_api import appLog, db
from sqlalchemy import exc
from ..users.utils import authenticate, verify_extension
2018-05-01 16:17:12 +02:00
from .models import Activity
2018-05-09 18:23:17 +02:00
from .utils import (
2018-05-10 10:21:58 +02:00
create_activity, edit_activity_wo_gpx, get_file_path, get_gpx_info
2018-05-09 18:23:17 +02:00
)
2018-01-21 17:43:13 +01:00
activities_blueprint = Blueprint('activities', __name__)
@activities_blueprint.route('/activities', methods=['GET'])
@authenticate
def get_activities(auth_user_id):
"""Get all activities for authenticated user"""
try:
params = request.args.copy()
page = 1 if len(params) == 0 else int(params.pop('page'))
activities = Activity.query.filter_by(user_id=auth_user_id)\
.order_by(Activity.activity_date.desc()).paginate(
page, 5, False).items
activities_list = []
for activity in activities:
activities_list.append(activity.serialize())
response_object = {
'status': 'success',
'data': {
'activities': activities_list
}
2018-01-21 17:43:13 +01:00
}
code = 200
except Exception as e:
appLog.error(e)
response_object = {
'status': 'error',
'message': 'Error. Please try again or contact the administrator.'
}
code = 500
return jsonify(response_object), code
2018-05-01 17:51:38 +02:00
2018-05-01 21:26:17 +02:00
@activities_blueprint.route('/activities/<int:activity_id>', methods=['GET'])
@authenticate
def get_activity(auth_user_id, activity_id):
"""Get an activity"""
activity = Activity.query.filter_by(id=activity_id).first()
activities_list = []
if activity:
activities_list.append(activity.serialize())
2018-05-02 17:01:31 +02:00
status = 'success'
2018-05-01 21:26:17 +02:00
code = 200
else:
2018-05-02 17:01:31 +02:00
status = 'not found'
2018-05-01 21:26:17 +02:00
code = 404
2018-05-02 17:01:31 +02:00
response_object = {
'status': status,
'data': {
'activities': activities_list
}
}
2018-05-01 21:26:17 +02:00
return jsonify(response_object), code
2018-05-03 21:42:54 +02:00
@activities_blueprint.route(
2018-05-09 18:54:30 +02:00
'/activities/<int:activity_id>/gpx', methods=['GET']
2018-05-03 21:42:54 +02:00
)
@authenticate
def get_activity_gpx(auth_user_id, activity_id):
"""Get gpx file for an activity"""
activity = Activity.query.filter_by(id=activity_id).first()
if activity:
if not activity.gpx or activity.gpx == '':
response_object = {
'status': 'fail',
'message': 'No gpx file for this activity (id: {})'.format(
activity_id
)
}
2018-05-09 16:32:06 +02:00
return jsonify(response_object), 400
2018-05-03 21:42:54 +02:00
try:
with open(activity.gpx, encoding='utf-8') as f:
2018-05-09 16:32:06 +02:00
gpx_content = f.read()
2018-05-03 21:42:54 +02:00
except Exception as e:
appLog.error(e)
2018-05-09 16:32:06 +02:00
response_object = {
'status': 'error',
'message': 'internal error',
'data': {
'gpx': ''
}
}
return jsonify(response_object), 500
2018-05-03 21:42:54 +02:00
status = 'success'
2018-05-09 16:32:06 +02:00
message = ''
2018-05-03 21:42:54 +02:00
code = 200
else:
2018-05-09 16:32:06 +02:00
gpx_content = ''
2018-05-03 21:42:54 +02:00
status = 'not found'
message = 'Activity not found (id: {})'.format(activity_id)
code = 404
response_object = {
'status': status,
'message': message,
'data': {
'gpx': gpx_content
}
}
return jsonify(response_object), code
2018-05-01 17:51:38 +02:00
@activities_blueprint.route('/activities', methods=['POST'])
@authenticate
def post_activity(auth_user_id):
"""Post an activity"""
response_object = verify_extension('activity', request)
if response_object['status'] != 'success':
2018-05-09 16:32:06 +02:00
return jsonify(response_object), 400
2018-05-01 17:51:38 +02:00
activity_data = json.loads(request.form["data"])
if not activity_data or activity_data.get('sport_id') is None:
response_object = {
'status': 'error',
'message': 'Invalid payload.'
}
return jsonify(response_object), 400
activity_file = request.files['file']
2018-05-09 16:32:06 +02:00
file_path = get_file_path(auth_user_id, activity_file)
2018-05-01 17:51:38 +02:00
try:
2018-05-09 16:32:06 +02:00
activity_file.save(file_path)
gpx_data = get_gpx_info(file_path)
2018-05-01 17:51:38 +02:00
except Exception as e:
appLog.error(e)
response_object = {
'status': 'error',
'message': 'Error during activity file save.'
}
return jsonify(response_object), 500
try:
2018-05-10 10:21:58 +02:00
new_activity = create_activity(
auth_user_id, activity_data, gpx_data, file_path)
2018-05-01 19:29:21 +02:00
db.session.add(new_activity)
2018-05-01 17:51:38 +02:00
db.session.commit()
response_object = {
'status': 'created',
2018-05-02 17:01:31 +02:00
'data': {
'activities': [new_activity.serialize()]
}
2018-05-01 17:51:38 +02:00
}
return jsonify(response_object), 201
except (exc.IntegrityError, ValueError) as e:
db.session.rollback()
appLog.error(e)
response_object = {
'status': 'fail',
'message': 'Error during activity save.'
}
return jsonify(response_object), 500
2018-05-08 15:46:54 +02:00
@activities_blueprint.route('/activities/no_gpx', methods=['POST'])
@authenticate
def post_activity_no_gpx(auth_user_id):
"""Post an activity without gpx file"""
activity_data = request.get_json()
if not activity_data or activity_data.get('sport_id') is None \
or activity_data.get('duration') is None \
or activity_data.get('distance') is None \
or activity_data.get('activity_date') is None:
response_object = {
'status': 'error',
'message': 'Invalid payload.'
}
return jsonify(response_object), 400
try:
2018-05-10 10:21:58 +02:00
new_activity = create_activity(auth_user_id, activity_data)
2018-05-08 15:46:54 +02:00
db.session.add(new_activity)
db.session.commit()
response_object = {
'status': 'created',
'data': {
'activities': [new_activity.serialize()]
}
}
return jsonify(response_object), 201
except (exc.IntegrityError, ValueError) as e:
db.session.rollback()
appLog.error(e)
response_object = {
'status': 'fail',
'message': 'Error during activity save.'
}
return jsonify(response_object), 500
2018-05-09 18:54:30 +02:00
2018-05-09 20:45:01 +02:00
@activities_blueprint.route('/activities/<int:activity_id>', methods=['PATCH'])
@authenticate
def update_activity(auth_user_id, activity_id):
"""Update an activity"""
activity_data = request.get_json()
if not activity_data or activity_data.get('sport_id') is None \
or activity_data.get('duration') is None \
or activity_data.get('distance') is None \
or activity_data.get('activity_date') is None:
response_object = {
'status': 'error',
'message': 'Invalid payload.'
}
return jsonify(response_object), 400
try:
activity = Activity.query.filter_by(id=activity_id).first()
if activity:
if activity.gpx:
response_object = {
'status': 'error',
'message': 'You can not modify an activity with gpx file. '
'Please delete and re-import the gpx file.'
}
code = 500
return jsonify(response_object), code
activity = edit_activity_wo_gpx(activity, activity_data)
db.session.commit()
response_object = {
'status': 'success',
'data': {
'activities': [activity.serialize()]
}
}
code = 200
else:
response_object = {
'status': 'not found',
'data': {
'activities': []
}
}
code = 404
except (exc.IntegrityError, exc.OperationalError, ValueError) as e:
db.session.rollback()
appLog.error(e)
response_object = {
'status': 'error',
'message': 'Error. Please try again or contact the administrator.'
}
code = 500
return jsonify(response_object), code
2018-05-09 18:54:30 +02:00
@activities_blueprint.route(
'/activities/<int:activity_id>', methods=['DELETE']
)
@authenticate
def delete_activity(auth_user_id, activity_id):
"""Delete an activity"""
try:
activity = Activity.query.filter_by(id=activity_id).first()
if activity:
gpx_filepath = activity.gpx
db.session.delete(activity)
db.session.commit()
if gpx_filepath:
os.remove(gpx_filepath)
response_object = {
'status': 'no content'
}
code = 204
else:
response_object = {
'status': 'not found',
'data': {
'activities': []
}
}
code = 404
except (exc.IntegrityError, exc.OperationalError, ValueError, OSError) \
as e:
db.session.rollback()
appLog.error(e)
response_object = {
'status': 'error',
'message': 'Error. Please try again or contact the administrator.'
}
code = 500
return jsonify(response_object), code