etiquette/etiquette.py

742 lines
23 KiB
Python
Raw Normal View History

2016-09-18 08:33:46 +00:00
import flask
from flask import request
import json
import mimetypes
import os
import random
import urllib.parse
2016-09-18 08:33:46 +00:00
import warnings
import zipstream
2016-09-18 08:33:46 +00:00
2016-11-06 04:24:43 +00:00
import constants
import decorators
import exceptions
2016-11-06 04:24:43 +00:00
import helpers
import jsonify
import objects
2016-10-10 03:50:13 +00:00
import phototagger
import searchhelpers
import sessions
2016-11-06 00:58:37 +00:00
2016-09-18 08:33:46 +00:00
site = flask.Flask(__name__)
site.config.update(
SEND_FILE_MAX_AGE_DEFAULT=180,
TEMPLATES_AUTO_RELOAD=True,
)
2016-10-10 03:50:13 +00:00
site.jinja_env.add_extension('jinja2.ext.do')
site.jinja_env.trim_blocks = True
site.jinja_env.lstrip_blocks = True
2016-11-06 04:24:43 +00:00
site.debug = True
2016-09-18 08:33:46 +00:00
P = phototagger.PhotoDB()
session_manager = sessions.SessionManager()
2016-09-18 08:33:46 +00:00
2016-10-10 03:50:13 +00:00
####################################################################################################
####################################################################################################
####################################################################################################
####################################################################################################
def back_url():
return request.args.get('goto') or request.referrer or '/'
2016-10-18 05:13:12 +00:00
def create_tag(easybake_string):
notes = P.easybake(easybake_string)
notes = [{'action': action, 'tagname': tagname} for (action, tagname) in notes]
return notes
def delete_tag(tag):
tag = tag.split('.')[-1].split('+')[0]
tag = P.get_tag(tag)
tag.delete()
return {'action': 'delete_tag', 'tagname': tag.name}
def delete_synonym(synonym):
synonym = synonym.split('+')[-1].split('.')[-1]
synonym = P.normalize_tagname(synonym)
2016-10-18 05:13:12 +00:00
try:
master_tag = P.get_tag(synonym)
except exceptions.NoSuchTag:
2016-10-18 05:13:12 +00:00
flask.abort(404, 'That synonym doesnt exist')
if synonym not in master_tag.synonyms():
flask.abort(400, 'That name is not a synonym')
master_tag.remove_synonym(synonym)
return {'action':'delete_synonym', 'synonym': synonym}
2016-09-18 08:33:46 +00:00
def P_album(albumid):
try:
return P.get_album(albumid)
except exceptions.NoSuchAlbum:
2016-11-06 00:58:37 +00:00
flask.abort(404, 'That album doesnt exist')
2016-09-18 08:33:46 +00:00
def P_photo(photoid):
try:
return P.get_photo(photoid)
except exceptions.NoSuchPhoto:
2016-09-18 08:33:46 +00:00
flask.abort(404, 'That photo doesnt exist')
def P_tag(tagname):
try:
return P.get_tag(tagname)
except exceptions.NoSuchTag as e:
2016-09-18 08:33:46 +00:00
flask.abort(404, 'That tag doesnt exist: %s' % e)
def P_user(username):
try:
return P.get_user(username=username)
except exceptions.NoSuchUser as e:
flask.abort(404, 'That user doesnt exist: %s' % e)
2016-09-18 08:33:46 +00:00
def send_file(filepath):
'''
Range-enabled file sending.
'''
2016-10-10 03:50:13 +00:00
try:
file_size = os.path.getsize(filepath)
except FileNotFoundError:
flask.abort(404)
2016-09-18 08:33:46 +00:00
outgoing_headers = {}
mimetype = mimetypes.guess_type(filepath)[0]
if mimetype is not None:
if 'text/' in mimetype:
mimetype += '; charset=utf-8'
outgoing_headers['Content-Type'] = mimetype
2016-10-10 03:50:13 +00:00
if 'range' in request.headers:
desired_range = request.headers['range'].lower()
desired_range = desired_range.split('bytes=')[-1]
2016-09-18 08:33:46 +00:00
2016-10-10 03:50:13 +00:00
int_helper = lambda x: int(x) if x.isdigit() else None
if '-' in desired_range:
(desired_min, desired_max) = desired_range.split('-')
range_min = int_helper(desired_min)
range_max = int_helper(desired_max)
else:
range_min = int_helper(desired_range)
if range_min is None:
range_min = 0
if range_max is None:
range_max = file_size
# because ranges are 0-indexed
range_max = min(range_max, file_size - 1)
range_min = max(range_min, 0)
range_header = 'bytes {min}-{max}/{outof}'.format(
min=range_min,
max=range_max,
outof=file_size,
)
outgoing_headers['Content-Range'] = range_header
status = 206
2016-09-18 08:33:46 +00:00
else:
2016-10-10 03:50:13 +00:00
range_max = file_size - 1
2016-09-18 08:33:46 +00:00
range_min = 0
2016-10-10 03:50:13 +00:00
status = 200
2016-09-18 08:33:46 +00:00
outgoing_headers['Accept-Ranges'] = 'bytes'
outgoing_headers['Content-Length'] = (range_max - range_min) + 1
2016-10-10 03:50:13 +00:00
if request.method == 'HEAD':
outgoing_data = bytes()
else:
outgoing_data = helpers.read_filebytes(
filepath,
range_min=range_min,
range_max=range_max,
chunk_size=P.config['file_read_chunk'],
)
2016-10-10 03:50:13 +00:00
2016-09-18 08:33:46 +00:00
response = flask.Response(
outgoing_data,
2016-10-10 03:50:13 +00:00
status=status,
2016-09-18 08:33:46 +00:00
headers=outgoing_headers,
)
return response
2016-10-10 03:50:13 +00:00
####################################################################################################
####################################################################################################
####################################################################################################
####################################################################################################
2016-09-18 08:33:46 +00:00
2016-09-18 08:33:46 +00:00
@site.route('/')
@session_manager.give_token
2016-09-18 08:33:46 +00:00
def root():
motd = random.choice(P.config['motd_strings'])
session = session_manager.get(request)
return flask.render_template('root.html', motd=motd, session=session)
@site.route('/login', methods=['GET'])
@session_manager.give_token
def get_login():
session = session_manager.get(request)
return flask.render_template('login.html', session=session)
@site.route('/register', methods=['GET'])
def get_register():
return flask.redirect('/login')
@site.route('/login', methods=['POST'])
@session_manager.give_token
@decorators.required_fields(['username', 'password'])
def post_login():
if session_manager.get(request):
return jsonify.make_json_response({'error': 'You\'re already signed in'}, status=403)
username = request.form['username']
password = request.form['password']
try:
user = P.get_user(username=username)
user = P.login(user.id, password)
except (exceptions.NoSuchUser, exceptions.WrongLogin):
return jsonify.make_json_response({'error': 'Wrong login'}, status=422)
session = sessions.Session(request, user)
session_manager.add(session)
return jsonify.make_json_response({})
@site.route('/register', methods=['POST'])
@session_manager.give_token
@decorators.required_fields(['username', 'password_1', 'password_2'])
def post_register():
if session_manager.get(request):
return jsonify.make_json_response({'error': 'You\'re already signed in'}, status=403)
username = request.form['username']
password_1 = request.form['password_1']
password_2 = request.form['password_2']
if password_1 != password_2:
return jsonify.make_json_response({'error': 'Passwords do not match'}, status=422)
try:
user = P.register_user(username, password_1)
except exceptions.UsernameTooShort as e:
error = 'Username shorter than minimum of %d' % P.config['min_username_length']
except exceptions.UsernameTooLong as e:
error = 'Username longer than maximum of %d' % P.config['max_username_length']
except exceptions.InvalidUsernameChars as e:
error = 'Username contains invalid characters %s' % e.args[0]
except exceptions.PasswordTooShort as e:
error = 'Password is shorter than minimum of %d' % P.config['min_password_length']
except exceptions.UserExists as e:
error = 'User %s already exists' % e.args[0]
else:
error = None
if error is not None:
return jsonify.make_json_response({'error': error}, status=422)
session = sessions.Session(request, user)
session_manager.add(session)
return jsonify.make_json_response({})
@site.route('/logout', methods=['GET', 'POST'])
@session_manager.give_token
def logout():
session_manager.remove(request)
response = flask.Response('redirect', status=302, headers={'Location': back_url()})
return response
2016-09-18 08:33:46 +00:00
2016-11-06 04:24:43 +00:00
2016-10-10 03:50:13 +00:00
@site.route('/favicon.ico')
@site.route('/favicon.png')
def favicon():
filename = os.path.join('static', 'favicon.png')
return flask.send_file(filename)
2016-11-06 04:24:43 +00:00
2016-10-10 03:50:13 +00:00
def get_album_core(albumid):
2016-09-18 08:33:46 +00:00
album = P_album(albumid)
2016-10-10 03:50:13 +00:00
return album
@site.route('/album/<albumid>')
@session_manager.give_token
2016-10-10 03:50:13 +00:00
def get_album_html(albumid):
album = get_album_core(albumid)
session = session_manager.get(request)
2016-09-18 08:33:46 +00:00
response = flask.render_template(
'album.html',
album=album,
session=session,
2016-11-27 09:06:11 +00:00
view=request.args.get('view', 'grid'),
2016-09-18 08:33:46 +00:00
)
return response
2016-10-21 03:15:24 +00:00
@site.route('/album/<albumid>.json')
@session_manager.give_token
2016-10-10 03:50:13 +00:00
def get_album_json(albumid):
album = get_album_core(albumid)
album = jsonify.album(album)
album['sub_albums'] = [P_album(x) for x in album['sub_albums']]
album['sub_albums'].sort(key=lambda x: (x.title or x.id).lower())
album['sub_albums'] = [jsonify.album(x, minimal=True) for x in album['sub_albums']]
return jsonify.make_json_response(album)
2016-10-10 03:50:13 +00:00
2016-11-06 04:24:43 +00:00
@site.route('/album/<albumid>.zip')
def get_album_zip(albumid):
2016-11-06 00:58:37 +00:00
album = P_album(albumid)
recursive = request.args.get('recursive', True)
recursive = helpers.truthystring(recursive)
arcnames = helpers.album_zip_filenames(album, recursive=recursive)
streamed_zip = zipstream.ZipFile()
for (real_filepath, arcname) in arcnames.items():
streamed_zip.write(real_filepath, arcname=arcname)
# Add the album metadata as an {id}.txt file within each directory.
directories = helpers.album_zip_directories(album, recursive=recursive)
for (inner_album, directory) in directories.items():
text = []
if inner_album.title:
text.append(inner_album.title)
if inner_album.description:
text.append(inner_album.description)
if not text:
continue
text = '\r\n\r\n'.join(text)
streamed_zip.writestr(
arcname=os.path.join(directory, '%s.txt' % inner_album.id),
data=text.encode('utf-8'),
)
if album.title:
download_as = '%s - %s.zip' % (album.id, album.title)
else:
download_as = '%s.zip' % album.id
download_as = urllib.parse.quote(download_as)
outgoing_headers = {
'Content-Type': 'application/octet-stream',
'Content-Disposition': 'attachment; filename*=UTF-8\'\'%s' % download_as,
}
2016-11-06 00:58:37 +00:00
return flask.Response(streamed_zip, headers=outgoing_headers)
2016-11-06 04:24:43 +00:00
def get_albums_core():
2016-10-10 03:50:13 +00:00
albums = P.get_albums()
albums = [a for a in albums if a.parent() is None]
2016-11-06 04:24:43 +00:00
return albums
@site.route('/albums')
@session_manager.give_token
2016-11-06 04:24:43 +00:00
def get_albums_html():
albums = get_albums_core()
session = session_manager.get(request)
return flask.render_template('albums.html', albums=albums, session=session)
2016-10-10 03:50:13 +00:00
2016-10-21 03:15:24 +00:00
@site.route('/albums.json')
@session_manager.give_token
2016-10-21 03:15:24 +00:00
def get_albums_json():
2016-11-06 04:24:43 +00:00
albums = get_albums_core()
albums = [jsonify.album(album, minimal=True) for album in albums]
return jsonify.make_json_response(albums)
2016-10-21 03:15:24 +00:00
2016-11-06 04:24:43 +00:00
2016-11-29 04:18:44 +00:00
@site.route('/bookmarks')
@session_manager.give_token
2016-11-29 04:18:44 +00:00
def get_bookmarks():
session = session_manager.get(request)
bookmarks = list(P.get_bookmarks())
return flask.render_template('bookmarks.html', bookmarks=bookmarks, session=session)
2016-11-29 04:18:44 +00:00
2016-09-18 08:33:46 +00:00
@site.route('/file/<photoid>')
def get_file(photoid):
photoid = photoid.split('.')[0]
photo = P.get_photo(photoid)
do_download = request.args.get('download', False)
2016-11-06 04:24:43 +00:00
do_download = helpers.truthystring(do_download)
2016-09-18 08:33:46 +00:00
use_original_filename = request.args.get('original_filename', False)
2016-11-06 04:24:43 +00:00
use_original_filename = helpers.truthystring(use_original_filename)
2016-09-18 08:33:46 +00:00
if do_download:
if use_original_filename:
download_as = photo.basename
else:
download_as = photo.id + photo.dot_extension
2016-09-18 08:33:46 +00:00
download_as = urllib.parse.quote(download_as)
2016-09-18 08:33:46 +00:00
response = flask.make_response(send_file(photo.real_filepath))
response.headers['Content-Disposition'] = 'attachment; filename*=UTF-8\'\'%s' % download_as
2016-09-18 08:33:46 +00:00
return response
else:
return send_file(photo.real_filepath)
2016-11-06 04:24:43 +00:00
2016-10-10 03:50:13 +00:00
def get_photo_core(photoid):
2016-09-18 08:33:46 +00:00
photo = P_photo(photoid)
2016-10-10 03:50:13 +00:00
return photo
2016-09-18 08:33:46 +00:00
2016-10-10 03:50:13 +00:00
@site.route('/photo/<photoid>', methods=['GET'])
@session_manager.give_token
2016-10-10 03:50:13 +00:00
def get_photo_html(photoid):
photo = get_photo_core(photoid)
session = session_manager.get(request)
return flask.render_template('photo.html', photo=photo, session=session)
2016-10-10 03:50:13 +00:00
@site.route('/photo/<photoid>.json', methods=['GET'])
@session_manager.give_token
2016-10-10 03:50:13 +00:00
def get_photo_json(photoid):
photo = get_photo_core(photoid)
photo = jsonify.photo(photo)
photo = jsonify.make_json_response(photo)
2016-10-10 03:50:13 +00:00
return photo
def get_search_core():
warning_bag = objects.WarningBag()
2016-09-18 08:33:46 +00:00
has_tags = request.args.get('has_tags')
tag_musts = request.args.get('tag_musts')
tag_mays = request.args.get('tag_mays')
tag_forbids = request.args.get('tag_forbids')
tag_expression = request.args.get('tag_expression')
2016-09-18 08:33:46 +00:00
filename_terms = request.args.get('filename')
extension = request.args.get('extension')
extension_not = request.args.get('extension_not')
mimetype = request.args.get('mimetype')
limit = request.args.get('limit')
# This is being pre-processed because the site enforces a maximum value
# which the PhotoDB api does not.
limit = searchhelpers.normalize_limit(limit, warning_bag=warning_bag)
2016-09-18 08:33:46 +00:00
if limit is None:
limit = 50
else:
limit = min(limit, 100)
offset = request.args.get('offset')
authors = request.args.get('author')
2016-09-18 08:33:46 +00:00
orderby = request.args.get('orderby')
area = request.args.get('area')
width = request.args.get('width')
height = request.args.get('height')
ratio = request.args.get('ratio')
bytes = request.args.get('bytes')
duration = request.args.get('duration')
created = request.args.get('created')
2016-09-18 08:33:46 +00:00
# These are in a dictionary so I can pass them to the page template.
search_kwargs = {
'area': area,
'width': width,
'height': height,
'ratio': ratio,
'bytes': bytes,
2016-10-10 03:50:13 +00:00
'duration': duration,
2016-09-18 08:33:46 +00:00
'authors': authors,
2016-09-18 08:33:46 +00:00
'created': created,
'extension': extension,
'extension_not': extension_not,
2016-10-30 01:46:23 +00:00
'filename': filename_terms,
2016-09-18 08:33:46 +00:00
'has_tags': has_tags,
'mimetype': mimetype,
2016-09-18 08:33:46 +00:00
'tag_musts': tag_musts,
'tag_mays': tag_mays,
'tag_forbids': tag_forbids,
'tag_expression': tag_expression,
'limit': limit,
'offset': offset,
'orderby': orderby,
'warning_bag': warning_bag,
'give_back_parameters': True
2016-09-18 08:33:46 +00:00
}
2016-11-06 00:58:37 +00:00
#print(search_kwargs)
search_generator = P.search(**search_kwargs)
# Because of the giveback, first element is cleaned up kwargs
search_kwargs = next(search_generator)
# The search has converted many arguments into sets or other types.
# Convert them back into something that will display nicely on the search form.
join_helper = lambda x: ', '.join(x) if x else None
tagname_helper = lambda tags: [tag.qualified_name() for tag in tags] if tags else None
filename_helper = lambda fn: ' '.join('"%s"' % part if ' ' in part else part for part in fn) if fn else None
search_kwargs['extension'] = join_helper(search_kwargs['extension'])
search_kwargs['extension_not'] = join_helper(search_kwargs['extension_not'])
search_kwargs['mimetype'] = join_helper(search_kwargs['mimetype'])
search_kwargs['filename'] = filename_helper(search_kwargs['filename'])
search_kwargs['tag_musts'] = tagname_helper(search_kwargs['tag_musts'])
search_kwargs['tag_mays'] = tagname_helper(search_kwargs['tag_mays'])
search_kwargs['tag_forbids'] = tagname_helper(search_kwargs['tag_forbids'])
search_results = list(search_generator)
warnings = set()
photos = []
for item in search_results:
if isinstance(item, objects.WarningBag):
warnings.update(item.warnings)
else:
photos.append(item)
2016-10-10 03:50:13 +00:00
# TAGS ON THIS PAGE
2016-09-18 08:33:46 +00:00
total_tags = set()
for photo in photos:
for tag in photo.tags():
total_tags.add(tag.qualified_name())
2016-10-10 03:50:13 +00:00
total_tags = sorted(total_tags)
2016-09-18 08:33:46 +00:00
# PREV-NEXT PAGE URLS
offset = search_kwargs['offset'] or 0
2016-11-06 04:24:43 +00:00
original_params = request.args.to_dict()
2016-09-18 08:33:46 +00:00
if len(photos) == limit:
2016-11-06 04:24:43 +00:00
next_params = helpers.edit_params(original_params, {'offset': offset + limit})
2016-09-18 08:33:46 +00:00
next_page_url = '/search' + next_params
else:
next_page_url = None
if offset > 0:
2016-11-06 04:24:43 +00:00
prev_params = helpers.edit_params(original_params, {'offset': max(0, offset - limit)})
2016-09-18 08:33:46 +00:00
prev_page_url = '/search' + prev_params
else:
prev_page_url = None
2016-11-07 02:00:30 +00:00
view = request.args.get('view', 'grid')
search_kwargs['view'] = view
2016-10-10 03:50:13 +00:00
final_results = {
'next_page_url': next_page_url,
'prev_page_url': prev_page_url,
'photos': photos,
'total_tags': total_tags,
'warnings': list(warnings),
2016-10-10 03:50:13 +00:00
'search_kwargs': search_kwargs,
}
return final_results
@site.route('/search')
@session_manager.give_token
2016-10-10 03:50:13 +00:00
def get_search_html():
search_results = get_search_core()
search_kwargs = search_results['search_kwargs']
qualname_map = P.export_tags(exporter=phototagger.tag_export_qualname_map)
session = session_manager.get(request)
2016-09-18 08:33:46 +00:00
response = flask.render_template(
'search.html',
2016-10-10 03:50:13 +00:00
next_page_url=search_results['next_page_url'],
prev_page_url=search_results['prev_page_url'],
photos=search_results['photos'],
2016-09-18 08:33:46 +00:00
qualname_map=json.dumps(qualname_map),
2016-10-10 03:50:13 +00:00
search_kwargs=search_kwargs,
session=session,
2016-10-10 03:50:13 +00:00
total_tags=search_results['total_tags'],
warnings=search_results['warnings'],
2016-09-18 08:33:46 +00:00
)
return response
2016-10-10 03:50:13 +00:00
@site.route('/search.json')
@session_manager.give_token
2016-10-10 03:50:13 +00:00
def get_search_json():
search_results = get_search_core()
search_results['photos'] = [jsonify.photo(photo, include_albums=False) for photo in search_results['photos']]
return jsonify.make_json_response(search_results)
2016-11-06 04:24:43 +00:00
2016-10-10 03:50:13 +00:00
2016-09-18 08:33:46 +00:00
@site.route('/static/<filename>')
def geft_static(filename):
2016-10-10 03:50:13 +00:00
filename = filename.replace('\\', os.sep)
filename = filename.replace('/', os.sep)
filename = os.path.join('static', filename)
return flask.send_file(filename)
2016-11-06 04:24:43 +00:00
def get_tags_core(specific_tag=None):
2016-10-10 03:50:13 +00:00
try:
tags = P.export_tags(phototagger.tag_export_easybake, specific_tag=specific_tag)
except exceptions.NoSuchTag:
2016-10-10 03:50:13 +00:00
flask.abort(404, 'That tag doesnt exist')
tags = tags.split('\n')
tags = [t for t in tags if t != '']
tags = [(t, t.split('.')[-1].split('+')[0]) for t in tags]
2016-11-06 04:24:43 +00:00
return tags
2016-11-06 04:24:43 +00:00
@site.route('/tags')
@site.route('/tags/<specific_tag>')
@session_manager.give_token
2016-11-06 04:24:43 +00:00
def get_tags_html(specific_tag=None):
tags = get_tags_core(specific_tag)
session = session_manager.get(request)
return flask.render_template('tags.html', tags=tags, session=session)
2016-10-10 03:50:13 +00:00
2016-11-06 04:24:43 +00:00
@site.route('/tags.json')
@site.route('/tags/<specific_tag>.json')
@session_manager.give_token
2016-11-06 04:24:43 +00:00
def get_tags_json(specific_tag=None):
tags = get_tags_core(specific_tag)
tags = [t[0] for t in tags]
return jsonify.make_json_response(tags)
2016-11-06 04:24:43 +00:00
2016-10-10 03:50:13 +00:00
@site.route('/thumbnail/<photoid>')
def get_thumbnail(photoid):
photoid = photoid.split('.')[0]
photo = P_photo(photoid)
if photo.thumbnail:
path = photo.thumbnail
else:
flask.abort(404, 'That file doesnt have a thumbnail')
return send_file(path)
2016-11-06 04:24:43 +00:00
def get_user_core(username):
user = P_user(username)
return user
@site.route('/user/<username>', methods=['GET'])
@session_manager.give_token
def get_user_html(username):
user = get_user_core(username)
session = session_manager.get(request)
return flask.render_template('user.html', user=user, session=session)
@site.route('/user/<username>.json', methods=['GET'])
@session_manager.give_token
def get_user_json(username):
user = get_user_core(username)
user = jsonify.user(user)
user = jsonify.make_json_response(user)
return user
2016-10-18 05:13:12 +00:00
@site.route('/album/<albumid>', methods=['POST'])
2016-10-21 03:15:24 +00:00
@site.route('/album/<albumid>.json', methods=['POST'])
@session_manager.give_token
2016-10-18 05:13:12 +00:00
def post_edit_album(albumid):
'''
Edit the album's title and description.
Apply a tag to every photo in the album.
'''
2016-10-21 03:15:24 +00:00
response = {}
album = P_album(albumid)
if 'add_tag' in request.form:
action = 'add_tag'
tag = request.form[action].strip()
try:
tag = P_tag(tag)
except exceptions.NoSuchTag:
2016-10-21 03:15:24 +00:00
response = {'error': 'That tag doesnt exist', 'tagname': tag}
return jsonify.make_json_response(response, status=404)
2016-10-21 03:15:24 +00:00
recursive = request.form.get('recursive', False)
2016-11-06 04:24:43 +00:00
recursive = helpers.truthystring(recursive)
2016-10-21 03:15:24 +00:00
album.add_tag_to_all(tag, nested_children=recursive)
response['action'] = action
response['tagname'] = tag.name
return jsonify.make_json_response(response)
2016-10-18 05:13:12 +00:00
2016-11-06 04:24:43 +00:00
2016-10-10 03:50:13 +00:00
@site.route('/photo/<photoid>', methods=['POST'])
2016-10-21 03:15:24 +00:00
@site.route('/photo/<photoid>.json', methods=['POST'])
@session_manager.give_token
2016-10-10 03:50:13 +00:00
def post_edit_photo(photoid):
2016-10-18 05:13:12 +00:00
'''
Add and remove tags from photos.
'''
2016-10-10 03:50:13 +00:00
response = {}
photo = P_photo(photoid)
if 'add_tag' in request.form:
action = 'add_tag'
method = photo.add_tag
elif 'remove_tag' in request.form:
action = 'remove_tag'
method = photo.remove_tag
else:
flask.abort(400, 'Invalid action')
tag = request.form[action].strip()
if tag == '':
flask.abort(400, 'No tag supplied')
try:
tag = P.get_tag(tag)
except exceptions.NoSuchTag:
2016-10-18 05:13:12 +00:00
response = {'error': 'That tag doesnt exist', 'tagname': tag}
return jsonify.make_json_response(response, status=404)
2016-10-10 03:50:13 +00:00
method(tag)
response['action'] = action
2016-10-18 05:13:12 +00:00
#response['tagid'] = tag.id
2016-10-10 03:50:13 +00:00
response['tagname'] = tag.name
return jsonify.make_json_response(response)
2016-10-10 03:50:13 +00:00
2016-11-06 04:24:43 +00:00
2016-10-10 03:50:13 +00:00
@site.route('/tags', methods=['POST'])
@session_manager.give_token
2016-10-10 03:50:13 +00:00
def post_edit_tags():
2016-10-18 05:13:12 +00:00
'''
Create and delete tags and synonyms.
'''
#print(request.form)
2016-10-10 03:50:13 +00:00
status = 200
if 'create_tag' in request.form:
action = 'create_tag'
method = create_tag
elif 'delete_tag_synonym' in request.form:
action = 'delete_tag_synonym'
method = delete_synonym
elif 'delete_tag' in request.form:
action = 'delete_tag'
method = delete_tag
else:
2016-10-18 05:13:12 +00:00
status = 400
2016-11-06 04:24:43 +00:00
response = {'error': constants.ERROR_INVALID_ACTION}
2016-10-10 03:50:13 +00:00
if status == 200:
tag = request.form[action].strip()
if tag == '':
2016-11-06 04:24:43 +00:00
response = {'error': constants.ERROR_NO_TAG_GIVEN}
2016-10-18 05:13:12 +00:00
status = 400
if status == 200:
# expect the worst
status = 400
2016-10-10 03:50:13 +00:00
try:
response = method(tag)
except exceptions.TagTooShort:
2016-11-06 04:24:43 +00:00
response = {'error': constants.ERROR_TAG_TOO_SHORT, 'tagname': tag}
except exceptions.CantSynonymSelf:
2016-11-06 04:24:43 +00:00
response = {'error': constants.ERROR_SYNONYM_ITSELF, 'tagname': tag}
except exceptions.NoSuchTag as e:
2016-11-06 04:24:43 +00:00
response = {'error': constants.ERROR_NO_SUCH_TAG, 'tagname': tag}
except exceptions.RecursiveGrouping as e:
response = {'error': constants.ERROR_RECURSIVE_GROUPING, 'tagname': tag}
2016-10-10 03:50:13 +00:00
except ValueError as e:
response = {'error': e.args[0], 'tagname': tag}
else:
status = 200
response = json.dumps(response)
response = flask.Response(response, status=status)
return response
2016-09-18 08:33:46 +00:00
@site.route('/apitest')
@session_manager.give_token
def apitest():
response = flask.Response('testing')
response.set_cookie('etiquette_session', 'don\'t overwrite me')
return response
2016-09-18 08:33:46 +00:00
if __name__ == '__main__':
2016-11-27 09:06:11 +00:00
#site.run(threaded=True)
pass