etiquette/etiquette_site.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
2017-02-05 03:55:13 +00:00
from etiquette import constants
from etiquette import decorators
from etiquette import exceptions
from etiquette import helpers
from etiquette import jsonify
from etiquette import objects
from etiquette import phototagger
from etiquette import searchhelpers
from etiquette import sessions
TEMPLATE_DIR = 'C:\\git\\Etiquette\\templates'
STATIC_DIR = 'C:\\git\\Etiquette\\static'
site = flask.Flask(
__name__,
template_folder=TEMPLATE_DIR,
static_folder=STATIC_DIR,
)
2016-09-18 08:33:46 +00:00
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():
2017-02-05 03:55:13 +00:00
filename = os.path.join(STATIC_DIR, 'favicon.png')
2016-10-10 03:50:13 +00:00
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-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