summaryrefslogtreecommitdiff
path: root/slideapi.py
diff options
context:
space:
mode:
Diffstat (limited to 'slideapi.py')
-rwxr-xr-xslideapi.py250
1 files changed, 182 insertions, 68 deletions
diff --git a/slideapi.py b/slideapi.py
index bc26c83..b212fdd 100755
--- a/slideapi.py
+++ b/slideapi.py
@@ -7,47 +7,20 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
-import os, json
-from bottle import get, post, auth_basic, run, static_file, request, debug
+import os, json, time
+from bottle import get, post, auth_basic, run, static_file, request, debug, view, HTTPError
from subprocess import call
-
-# -----
-
-@get('/api/users/')
-def users():
- return "<a href='test/'>User Test</a>"
-
-@get('/api/topics/')
-def topics():
- return "<a href='test/'>Topic Test</a>"
-
-@get('/api/users/test/')
-def test():
- return "<a href='deck1/'>deck1</a><br/><a href='deck2/'>deck2</a>"
-
-@get('/api/users/test/deck1/')
-def deck1():
- return "<a href='1/'>revision 1</a><br/><a href='2/'>revision 2</a>"
-
-@get('/api/users/test/<deck>/<rev:int>/')
-def list_deck(deck, rev):
- return "<a href='checkinDate'>checkin data</a><br/><a href='checkinComment'>checkin comment</a><br/><a href='deck.fodp'>deck.fodp</a><br/><a href='1/'>slide 1</a>"
-
-@get('/api/users/test/<deck>/<rev:int>/checkinDate')
-def send_checkinDate(deck,rev):
- return '2013-04-01 for '+deck+', rev '+str(rev)
-
-@get('/api/users/test/<deck>/<rev:int>/checkinComment')
-def send_checkinComment(deck,rev):
- return 'Riiiiight on for '+deck+', rev '+str(rev)
-
-@get('/api/users/test/<deck>/<rev:int>/<slide:int>/keywords.json')
-def send_keywords(deck, rev, slide):
- return {'Author': 'Joe User',
- 'Title': 'The great slideshow'}
-
+# config
+#
+# we understand:
+# local_conf["users"], yielding {<username>: {"password": <password>, "description": <description>}, ... }
+# local_conf["thumbnails"], yielding {"soffice": <path>, "convert": <path>, "thumbnail_size": <128x128>}
+# local_conf["tags"], yielding [ <tagname>, ... ]
+#
local_conf=json.loads(open('local.json').read()) if os.path.exists('local.json') else {}
+root='filestore'
+
def validate_auth(user, password):
if "users" in local_conf:
user_dict = local_conf["users"]
@@ -55,55 +28,196 @@ def validate_auth(user, password):
return password == user_dict[user]['password']
return False
+# -------------------------------------------------------------------
+
+def get_users():
+ return {user: data['description'] for user, data in local_conf["users"].items()}
+
+@get('/api/users/')
+def users():
+ return get_users()
+
+@get('/users/')
+@view('users')
+def users():
+ return dict(users=get_users())
+
+# -------------------------------------------------------------------
+
+def get_tags():
+ return local_conf["tags"]
+
+@get('/api/tags/')
+def tags():
+ return json.dumps(get_tags())
+
+@get('/tags/')
+@view('tags')
+def tags():
+ return dict(tags=get_tags())
+
+# -------------------------------------------------------------------
+
+def get_decks(user):
+ path = "%s/%s/" % (root,user)
+ if not os.path.isdir(path):
+ return []
+ return [deck for deck in os.listdir(path) if os.path.isdir(path+deck)]
+
+def get_lastrev(user,deck):
+ path = "%s/%s/%s/" % (root,user,deck)
+ if not os.path.isdir(path):
+ return 0
+ # get last revision
+ return int(sorted([rev for rev in os.listdir(path) if os.path.isdir(path+rev)], key=int)[-1])
+
+@get('/api/users/<user>/')
+def list_decks(user):
+ return json.dumps(get_decks(user))
+
+@get('/users/<user>/')
+@view('decks')
+def list_decks(user):
+ return dict(decks=get_decks(user))
+
+@get('/users/<user>/<deck>/thumbnail.png')
+@get('/api/users/<user>/<deck>/thumbnail.png')
+def get_thumbnail(user, deck):
+ path = "%s/%s/%s/" % (root,user,deck)
+ last_rev = get_lastrev(user,deck)
+ # serve thumbnail from that rev, first slide
+ return static_file('0.png', root=path+str(last_rev)+'/0/', mimetype='image/png')
+
+# -------------------------------------------------------------------
+
+def get_revs(user,deck):
+ path = "%s/%s/%s/" % (root,user,deck)
+ if not os.path.isdir(path):
+ return []
+ return sorted([rev for rev in os.listdir(path) if os.path.isdir(path+rev)], key=int)
+
+@get('/api/users/<user>/<deck>/')
+def list_revs(user,deck):
+ return json.dumps(get_revs(user,deck))
+
+@get('/users/<user>/<deck>/')
+@view('revs')
+def list_revs(user,deck):
+ return dict(revs=get_revs(user,deck))
+
# eventually use ssl here - http://dgtool.blogspot.de/2011/12/ssl-encryption-in-python-bottle.html
-@post('/api/upload')
+@post('/users/<user>/<deck>')
+@post('/api/users/<user>/<deck>')
@auth_basic(validate_auth, realm='upload')
-def upload_file():
- upload_path = '/tmp'
- soffice = 'soffice'
- convert = 'convert'
- thumbnail_size = '128x128'
+def upload_deck(user,deck):
+ path = "%s/%s/%s/" % (root,user,deck)
+ new_rev = get_lastrev(user,deck) + 1
+ new_path = path+str(new_rev)
- # override defaults by config
- if "thumbnails" in local_conf:
- thumbnails_dict = local_conf["thumbnails"]
- upload_path = thumbnails_dict['upload_path'] if 'upload_path' in thumbnails_dict else upload_path
- soffice = thumbnails_dict['soffice'] if 'soffice' in thumbnails_dict else soffice
- convert = thumbnails_dict['convert'] if 'convert' in thumbnails_dict else convert
- thumbnail_size = thumbnails_dict['thumbnail_size'] if 'thumbnail_size' in thumbnails_dict else thumbnail_size
+ if os.path.isdir(new_path):
+ raise HTTPError(body='inconsistent repo, bailing out')
+
+ if request.auth[0] != user:
+ raise HTTPError(body='invalid user or insufficient rights, bailing out')
+
+ os.makedirs(new_path)
+ upload_path = new_path
# TODO: Add all required parameters here
tag = request.forms.get('tag')
content = request.files.get('file')
# TODO: Create proper paths for uploads & Check for upload errors
- out = open(upload_path+'/'+content.filename, 'wb')
+ out = open(upload_path+'/deck.odp', 'wb')
while True:
bits = content.file.read(10240)
if not bits:
break
out.write(bits)
out.close()
- call([soffice, '--headless', '--convert-to', 'pdf', '--outdir', upload_path, upload_path+'/'+content.filename])
- call([convert, '-resize', thumbnail_size, upload_path+'/'+os.path.splitext(content.filename)[0]+'.pdf', upload_path+'/'+os.path.splitext(content.filename)[0]+'.png'])
- return 'Success:'+tag+':'+content.filename
-#-----
+ out = open(upload_path+'/meta.json', 'wb')
+ json.dump({'tag': tag,
+ 'server_version': '1',
+ 'upload_filename': content.filename},
+ out)
-@get('/api/users/test/<deck>/<rev:int>/deck.fodp')
-def send_deck(deck, rev):
- return static_file(deck+'.fodp', root='decks/'+deck+'/'+str(rev), mimetype='text/xml')
+ thumbnail_size = '128x128'
-@get('/api/users/test/<deck>/<rev:int>/<slide:int>/')
-def list_slide(deck,rev,slide):
- return "<a href='thumbnail.png'>thumbnail</a><br/><a href='slide.fodp'>slide "+str(slide)+"</a><br/><a href='keywords.json'>keywords</a>"
+ # override defaults by config
+ if "thumbnails" in local_conf:
+ thumbnails_dict = local_conf["thumbnails"]
+ thumbnail_size = thumbnails_dict['thumbnail_size'] if 'thumbnail_size' in thumbnails_dict else thumbnail_size
+
+ os.system('./convert_deck.sh '+upload_path+' '+thumbnail_size)
+ return 'Success:'+tag+':'+content.filename
-@get('/api/users/test/<deck>/<rev:int>/<slide:int>/slide.fodp')
-def send_slide(deck, rev, slide):
- return static_file(str(slide)+'.fodp', root='decks/'+deck+'/'+str(rev), mimetype='text/xml')
-@get('/api/users/test/<deck>/<rev:int>/<slide:int>/thumbnail.png')
-def send_thumbnail(deck, rev, slide):
- return static_file(str(slide)+'.png', root='decks/'+deck+'/'+str(rev), mimetype='image/png')
+@get('/users/<user>/<deck>/<rev:int>/thumbnail.png')
+@get('/api/users/<user>/<deck>/<rev:int>/thumbnail.png')
+def get_thumbnail(user, deck, rev):
+ path = "%s/%s/%s/%d/" % (root,user,deck,rev)
+ # serve thumbnail from that rev, first slide
+ return static_file('0.png', root=path+'/0/', mimetype='image/png')
+
+@get('/users/<user>/<deck>/<rev:int>/deck.odp')
+@get('/api/users/<user>/<deck>/<rev:int>/deck.odp')
+def send_deck(user, deck, rev):
+ path = "%s/%s/%s/%d/" % (root,user,deck,rev)
+ return static_file(deck+'.odp', root=path, mimetype='text/xml')
+
+# -------------------------------------------------------------------
+
+def get_slides(user,deck,rev):
+ path = "%s/%s/%s/%d/" % (root,user,deck,rev)
+ if not os.path.isdir(path):
+ return []
+ return sorted([slide for slide in os.listdir(path) if os.path.isdir(path+slide)], key=int)
+
+def get_revmeta(user,deck,rev):
+ path = "%s/%s/%s/%d/" % (root,user,deck,rev)
+ comment = open(path+'comment').read() if os.path.exists(path+'comment') else ''
+ meta = json.loads(open(path+'meta.json').read()) if os.path.exists(path+'meta.json') else {}
+ return {'CreationDate': time.strftime("%a, %d %b %Y %H:%M:%S GMT",
+ time.gmtime(os.stat(path).st_ctime)),
+ 'CommitComment': comment,
+ 'Meta': meta}
+
+@get('/api/users/<user>/<deck>/<rev:int>/')
+def list_slides(user, deck, rev):
+ return json.dumps(get_slides(user,deck,rev))
+
+@get('/users/<user>/<deck>/<rev:int>/')
+@view('slides')
+def list_slides(user, deck, rev):
+ return dict(slides=get_slides(user,deck,rev), revmeta=get_revmeta(user,deck,rev))
+
+@get('/users/<user>/<deck>/<rev:int>/<slide:int>/thumbnail.png')
+@get('/api/users/<user>/<deck>/<rev:int>/<slide:int>/thumbnail.png')
+def get_thumbnail(user, deck, rev, slide):
+ path = "%s/%s/%s/%d/%d/" % (root,user,deck,rev,slide)
+ return static_file(str(slide)+'.png', root=path, mimetype='image/png')
+
+@get('/api/users/<user>/<deck>/<rev:int>/meta.json')
+def list_revmeta(user,deck,rev):
+ return get_revmeta(user,deck,rev)
+
+# -------------------------------------------------------------------
+
+def get_slidemeta(user,deck,rev,slide):
+ path = "%s/%s/%s/%d/%d/" % (root,user,deck,rev,slide)
+ return json.loads(open(path+'meta.json').read()) if os.path.exists(path+'meta.json') else {}
+
+@get('/api/users/<user>/<deck>/<rev:int>/<slide:int>/meta.json')
+def list_slidemeta(user, deck, rev, slide):
+ return get_slidemeta(user, deck, rev, slide)
+
+@get('/users/<user>/<deck>/<rev:int>/<slide:int>/slide.odp')
+@get('/api/users/<user>/<deck>/<rev:int>/<slide:int>/slide.odp')
+def send_slide(user, deck, rev, slide):
+ path = "%s/%s/%s/%d/%d/" % (root,user,deck,rev,slide)
+ return static_file(str(slide)+'.odp', root=path, mimetype='text/xml')
+
+# -------------------------------------------------------------------
def main():
debug(True)