album .tar

This commit is contained in:
voussoir 2016-11-05 17:58:37 -07:00
parent c493362520
commit 7ad6160d38
8 changed files with 69 additions and 164 deletions

View file

@ -1,114 +0,0 @@
start_time = time.time()
# Raise for cases where the minimum > maximum
for (maxkey, maxval) in maximums.items():
if maxkey not in minimums:
continue
minval = minimums[maxkey]
if minval > maxval:
raise ValueError('Impossible min-max for %s' % maxkey)
conditions = []
minmaxers = {'<=': maximums, '>=': minimums}
# Convert the min-max parameters into query strings
print('Writing minmaxers')
for (comparator, minmaxer) in minmaxers.items():
for (field, value) in minmaxer.items():
if field not in Photo.int_properties:
raise ValueError('Unknown Photo property: %s' % field)
value = str(value)
query = min_max_query_builder(field, comparator, value)
conditions.append(query)
print(conditions)
print('Writing extension rule')
if extension is not None:
if isinstance(extension, str):
extension = [extension]
# Normalize to prevent injections
extension = [normalize_tagname(e) for e in extension]
extension = ['extension == "%s"' % e for e in extension]
extension = ' OR '.join(extension)
extension = '(%s)' % extension
conditions.append(extension)
def setify(l):
if l is None:
return set()
else:
return set(self.get_tag_by_name(t) for t in l)
tag_musts = setify(tag_musts)
tag_mays = setify(tag_mays)
tag_forbids = setify(tag_forbids)
base = '''
{negator} EXISTS(
SELECT 1 FROM photo_tag_rel
WHERE photo_tag_rel.photoid == photos.id
AND photo_tag_rel.tagid {operator} {value}
)'''
print('Writing musts')
for tag in tag_musts:
# tagid == must
query = base.format(
negator='',
operator='==',
value='"%s"' % tag.id,
)
conditions.append(query)
print('Writing mays')
if len(tag_mays) > 0:
# not any(tagid not in mays)
acceptable = tag_mays.union(tag_musts)
acceptable = ['"%s"' % t.id for t in acceptable]
acceptable = ', '.join(acceptable)
query = base.format(
negator='',
operator='IN',
value='(%s)' % acceptable,
)
conditions.append(query)
print('Writing forbids')
if len(tag_forbids) > 0:
# not any(tagid in forbids)
forbids = ['"%s"' % t.id for t in tag_forbids]
forbids = ', '.join(forbids)
query = base.format(
negator='NOT',
operator='IN',
value='(%s)' % forbids
)
conditions.append(query)
if len(conditions) == 0:
raise ValueError('No search query provided')
conditions = [query for query in conditions if query is not None]
conditions = ['(%s)' % c for c in conditions]
conditions = ' AND '.join(conditions)
conditions = 'WHERE %s' % conditions
query = 'SELECT * FROM photos %s' % conditions
query = query.replace('\n', ' ')
while ' ' in query:
query = query.replace(' ', ' ')
print(query)
temp_cur = self.sql.cursor()
temp_cur.execute(query)
for fetch in fetch_generator(temp_cur):
photo = Photo(self, fetch)
yield photo
end_time = time.time()
print(end_time - start_time)

27
etiquette/decorators.py Normal file
View file

@ -0,0 +1,27 @@
from flask import request
import uuid
def _generate_session_token():
token = str(uuid.uuid4())
#print('MAKE SESSION', token)
return token
def give_session_token(function):
@functools.wraps(function)
def wrapped(*args, **kwargs):
# Inject new token so the function doesn't know the difference
token = request.cookies.get('etiquette_session', None)
if not token:
token = _generate_session_token()
request.cookies = dict(request.cookies)
request.cookies['etiquette_session'] = token
ret = function(*args, **kwargs)
# Send the token back to the client
if not isinstance(ret, flask.Response):
ret = flask.Response(ret)
ret.set_cookie('etiquette_session', value=token, max_age=60)
return ret
return wrapped

View file

@ -11,11 +11,20 @@ import re
import requests import requests
import sys import sys
import time import time
import uuid
import warnings import warnings
import phototagger import phototagger
sys.path.append('C:\\git\\else\\Bytestring'); import bytestring
try:
sys.path.append('C:\\git\\else\\Bytestring')
sys.path.append('C:\\git\\else\\WebstreamZip')
import bytestring
import webstreamzip
except ImportError:
# pip install
# https://raw.githubusercontent.com/voussoir/else/master/_voussoirkit/voussoirkit.zip
from vousoirkit import bytestring
from vousoirkit import webstreamzip
site = flask.Flask(__name__) site = flask.Flask(__name__)
site.config.update( site.config.update(
@ -23,6 +32,7 @@ site.config.update(
TEMPLATES_AUTO_RELOAD=True, TEMPLATES_AUTO_RELOAD=True,
) )
site.jinja_env.add_extension('jinja2.ext.do') site.jinja_env.add_extension('jinja2.ext.do')
#site.debug = True
P = phototagger.PhotoDB() P = phototagger.PhotoDB()
@ -45,25 +55,7 @@ ERROR_NO_SUCH_TAG = 'Doesn\'t exist'
#################################################################################################### ####################################################################################################
#################################################################################################### ####################################################################################################
def give_session_token(function):
@functools.wraps(function)
def wrapped(*args, **kwargs):
# Inject new token so the function doesn't know the difference
token = request.cookies.get('etiquette_session', None)
if not token:
token = generate_session_token()
request.cookies = dict(request.cookies)
request.cookies['etiquette_session'] = token
ret = function(*args, **kwargs)
# Send the token back to the client
if not isinstance(ret, flask.Response):
ret = flask.Response(ret)
ret.set_cookie('etiquette_session', value=token, max_age=60)
return ret
return wrapped
def _helper_comma_split(s): def _helper_comma_split(s):
if s is None: if s is None:
@ -109,11 +101,6 @@ def edit_params(original, modifications):
new_params = '?' + new_params new_params = '?' + new_params
return new_params return new_params
def generate_session_token():
token = str(uuid.uuid4())
#print('MAKE SESSION', token)
return token
def make_json_response(j, *args, **kwargs): def make_json_response(j, *args, **kwargs):
dumped = json.dumps(j) dumped = json.dumps(j)
response = flask.Response(dumped, *args, **kwargs) response = flask.Response(dumped, *args, **kwargs)
@ -124,7 +111,7 @@ def P_album(albumid):
try: try:
return P.get_album(albumid) return P.get_album(albumid)
except phototagger.NoSuchAlbum: except phototagger.NoSuchAlbum:
flask.abort(404, 'That tag doesnt exist') flask.abort(404, 'That album doesnt exist')
def P_photo(photoid): def P_photo(photoid):
try: try:
@ -329,6 +316,16 @@ def get_album_json(albumid):
album = get_album_core(albumid) album = get_album_core(albumid)
return make_json_response(album) return make_json_response(album)
@site.route('/album/<albumid>.tar')
def get_album_tar(albumid):
album = P_album(albumid)
photos = list(album.walk_photos())
zipname_map = {p.real_filepath: '%s - %s' % (p.id, p.basename) for p in photos}
streamed_zip = webstreamzip.stream_tar(zipname_map)
content_length = sum(p.bytes for p in photos)
outgoing_headers = {'Content-Type': 'application/octet-stream'}
return flask.Response(streamed_zip, headers=outgoing_headers)
@site.route('/albums') @site.route('/albums')
@give_session_token @give_session_token
def get_albums_html(): def get_albums_html():
@ -391,7 +388,7 @@ def get_photo_json(photoid):
return photo return photo
def get_search_core(): def get_search_core():
print(request.args) #print(request.args)
# FILENAME & EXTENSION # FILENAME & EXTENSION
filename_terms = request.args.get('filename', None) filename_terms = request.args.get('filename', None)
@ -480,7 +477,7 @@ def get_search_core():
'warn_bad_tags': True, 'warn_bad_tags': True,
} }
print(search_kwargs) #print(search_kwargs)
with warnings.catch_warnings(record=True) as catcher: with warnings.catch_warnings(record=True) as catcher:
photos = list(P.search(**search_kwargs)) photos = list(P.search(**search_kwargs))
photos = [jsonify_photo(photo) for photo in photos] photos = [jsonify_photo(photo) for photo in photos]

View file

@ -15,8 +15,8 @@ if port == 443:
http = gevent.pywsgi.WSGIServer( http = gevent.pywsgi.WSGIServer(
('', port), ('', port),
etiquette.site, etiquette.site,
keyfile='etiquette.key', keyfile='https\\etiquette.key',
certfile='etiquette.crt', certfile='https\\etiquette.crt',
) )
else: else:
http = gevent.wsgi.WSGIServer(('', port), etiquette.site) http = gevent.wsgi.WSGIServer(('', port), etiquette.site)

View file

@ -220,6 +220,8 @@ def _helper_extension(ext):
def _helper_filenamefilter(subject, terms): def _helper_filenamefilter(subject, terms):
basename = subject.lower() basename = subject.lower()
#print(basename)
#print(terms)
return all(term in basename for term in terms) return all(term in basename for term in terms)
def _helper_minmax(key, value, minimums, maximums): def _helper_minmax(key, value, minimums, maximums):
@ -320,6 +322,8 @@ def _helper_unitconvert(value):
return None return None
if ':' in value: if ':' in value:
return hms_to_seconds(value) return hms_to_seconds(value)
elif all(c in '0123456789.' for c in value):
return float(value)
else: else:
return bytestring.parsebytes(value) return bytestring.parsebytes(value)
@ -1638,10 +1642,10 @@ class Album(ObjectBase, GroupableMixin):
return 'Album:{id}'.format(id=self.id) return 'Album:{id}'.format(id=self.id)
def add_photo(self, photo, commit=True): def add_photo(self, photo, commit=True):
if self.has_photo(photo):
return
if self.photodb != photo.photodb: if self.photodb != photo.photodb:
raise ValueError('Not the same PhotoDB') raise ValueError('Not the same PhotoDB')
if self.has_photo(photo):
return
self.photodb.cur.execute('INSERT INTO album_photo_rel VALUES(?, ?)', [self.id, photo.id]) self.photodb.cur.execute('INSERT INTO album_photo_rel VALUES(?, ?)', [self.id, photo.id])
if commit: if commit:
log.debug('Committing - add photo to album') log.debug('Committing - add photo to album')
@ -1687,6 +1691,7 @@ class Album(ObjectBase, GroupableMixin):
'SELECT * FROM album_photo_rel WHERE albumid == ? AND photoid == ?', 'SELECT * FROM album_photo_rel WHERE albumid == ? AND photoid == ?',
[self.id, photo.id] [self.id, photo.id]
) )
return self.photodb.cur.fetchone() is not None
def photos(self): def photos(self):
photos = [] photos = []
@ -1832,7 +1837,7 @@ class Photo(ObjectBase):
return_filepath = hopeful_filepath return_filepath = hopeful_filepath
elif mime == 'video' and ffmpeg: elif mime == 'video' and ffmpeg:
print('video') #print('video')
probe = ffmpeg.probe(self.real_filepath) probe = ffmpeg.probe(self.real_filepath)
try: try:
if probe.video: if probe.video:

View file

@ -1,16 +0,0 @@
for p in P.get_photos():
g=P.cur.execute('UPDATE photos SET id==? WHERE id==?', [p.id[-12:], p.id])
g=P.cur.execute('UPDATE photo_tag_rel SET photoid==? WHERE photoid==?', [p.id[-12:], p.id])
g=P.cur.execute('UPDATE album_photo_rel SET photoid==? WHERE photoid==?', [p.id[-12:], p.id])
for t in P.get_tags():
g=P.cur.execute('UPDATE tags SET id==? WHERE id==?', [t.id[-12:], t.id])
g=P.cur.execute('UPDATE photo_tag_rel SET tagid==? WHERE tagid==?', [t.id[-12:], t.id])
g=P.cur.execute('UPDATE tag_group_rel SET parentid==? WHERE parentid==?', [t.id[-12:], t.id])
g=P.cur.execute('UPDATE tag_group_rel SET memberid==? WHERE memberid==?', [t.id[-12:], t.id])
for a in P.get_albums():
g=P.cur.execute('UPDATE albums SET id==? WHERE id==?', [a.id[-12:], a.id])
g=P.cur.execute('UPDATE tag_group_rel SET parentid==? WHERE parentid==?', [a.id[-12:], a.id])
g=P.cur.execute('UPDATE tag_group_rel SET memberid==? WHERE memberid==?', [a.id[-12:], a.id])
g=P.cur.execute('UPDATE album_photo_rel SET albumid==? WHERE albumid==?', [a.id[-12:], a.id])

View file

@ -22,6 +22,8 @@
{% set parent=album["parent"] %} {% set parent=album["parent"] %}
{% if parent %} {% if parent %}
<h3>Parent: <a href="/album/{{parent["id"]}}">{{parent.title}}</a></h3> <h3>Parent: <a href="/album/{{parent["id"]}}">{{parent.title}}</a></h3>
{% else %}
<h3>Parent: <a href="/albums">Albums</a></h3>
{% endif %} {% endif %}
{% if child_albums %} {% if child_albums %}
<h3>Sub-albums</h3> <h3>Sub-albums</h3>
@ -37,6 +39,7 @@
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %} {% endif %}
<span><a href="/album/{{album["id"]}}.tar">(download .tar)</a></span>
{% if photos %} {% if photos %}
<h3>Photos</h3> <h3>Photos</h3>
<ul> <ul>

View file

@ -389,6 +389,8 @@ function submit_search()
var boxname = basic_inputs[index].name; var boxname = basic_inputs[index].name;
var box = document.getElementsByName(boxname)[0]; var box = document.getElementsByName(boxname)[0];
var value = box.value; var value = box.value;
value = value.split("&").join("%26");
console.log(value);
if (boxname == "has_tags" && has_tag_params && value == "no") if (boxname == "has_tags" && has_tag_params && value == "no")
{ {
/* /*
@ -401,7 +403,7 @@ function submit_search()
{ {
continue; continue;
} }
parameters.push(boxname + "=" + box.value); parameters.push(boxname + "=" + value);
} }
orderby_rows = document.getElementsByClassName("search_builder_orderby_li"); orderby_rows = document.getElementsByClassName("search_builder_orderby_li");
@ -425,6 +427,7 @@ function submit_search()
parameters = "?" + parameters; parameters = "?" + parameters;
url = url + parameters; url = url + parameters;
} }
console.log(url);
window.location.href = url; window.location.href = url;
return false; return false;
} }