def storymap_create(user): """Create a storymap""" try: title, data = _request_get_required('title', 'd') id = _make_storymap_id(user, title) key_prefix = storage.key_prefix(user['uid'], id) content = json.loads(data) storage.save_json(key_prefix+'draft.json', content) user['storymaps'][id] = { 'id': id, 'title': title, 'draft_on': _utc_now(), 'published_on': '' } _user.save(user) _write_embed_draft(key_prefix, user['storymaps'][id]) return jsonify({'id': id}) except Exception, e: traceback.print_exc() return jsonify({'error': str(e)})
def storymap_import(user): try: if 'archive' in request.files: temp_file, temp_path = tempfile.mkstemp() request.files['archive'].save(temp_path) @after_this_request def cleanup_temp_file(response): os.close(temp_file) os.remove(temp_path) return response with ZipFile(temp_path, mode='r') as zip_file: files = zip_file.namelist() if ('metadata.json' not in files) or ('draft.json' not in files) or ('draft.html' not in files): return jsonify({'error': 'This doesn\'t look like a StoryMap exported package.'}) id = _import_metadata(user, json.loads(zip_file.read('metadata.json'))) key_prefix = storage.key_prefix(user['uid'], id) for file_name in files: if file_name != 'metadata.json': key_name = "%s%s" % (key_prefix, file_name) storage.save_from_data(key_name, mimetypes.guess_type(file_name), zip_file.read(file_name)) return jsonify({'id': id}) except Exception, e: traceback.print_exc() return jsonify({'error': str(e)})
def storymap_copy(user, id): """ Copy storymap @id = storymap to copy @title = name of new copy """ try: title = _request_get_required('title') dst_id = _make_storymap_id(user, title) src_key_prefix = storage.key_prefix(user['uid'], id) dst_key_prefix = storage.key_prefix(user['uid'], dst_id) src_re = re.compile(r'%s' % src_key_prefix) src_key_list, more = storage.list_keys(src_key_prefix, 999, '') for src_key in src_key_list: file_name = src_key.name.split(src_key_prefix)[-1] dst_key_name = "%s%s" % (dst_key_prefix, file_name) if file_name.endswith('.json'): json_string = src_key.get_contents_as_string() storage.save_json(dst_key_name, src_re.sub(dst_key_prefix, json_string)) else: storage.copy_key(src_key.name, dst_key_name) # Update meta user['storymaps'][dst_id] = { 'id': dst_id, 'title': title, 'draft_on': user['storymaps'][id]['draft_on'], 'published_on': user['storymaps'][id]['published_on'] } _user.save(user) # Write new embed pages _write_embed_draft(dst_key_prefix, user['storymaps'][dst_id]) if user['storymaps'][dst_id].get('published_on'): _write_embed_published(dst_key_prefix, user['storymaps'][dst_id]) return jsonify(user['storymaps'][dst_id]) except Exception, e: traceback.print_exc() return jsonify({'error': str(e)})
def storymap_copy(user, id): """ Copy storymap @id = storymap to copy @title = name of new copy """ try: title = _request_get_required("title") dst_id = _make_storymap_id(user, title) src_key_prefix = storage.key_prefix(user["uid"], id) dst_key_prefix = storage.key_prefix(user["uid"], dst_id) src_re = re.compile(r"%s" % src_key_prefix) src_key_list, more = storage.list_keys(src_key_prefix, 999, "") for src_key in src_key_list: file_name = src_key.name.split(src_key_prefix)[-1] dst_key_name = "%s%s" % (dst_key_prefix, file_name) if file_name.endswith(".json"): json_string = src_key.get_contents_as_string() storage.save_json(dst_key_name, src_re.sub(dst_key_prefix, json_string)) else: storage.copy_key(src_key.name, dst_key_name) # Update meta user["storymaps"][dst_id] = { "id": dst_id, "title": title, "draft_on": user["storymaps"][id]["draft_on"], "published_on": user["storymaps"][id]["published_on"], } _user.save(user) # Write new embed pages _write_embed_draft(dst_key_prefix, user["storymaps"][dst_id]) if user["storymaps"][dst_id].get("published_on"): _write_embed_published(dst_key_prefix, user["storymaps"][dst_id]) return jsonify(user["storymaps"][dst_id]) except Exception, e: traceback.print_exc() return jsonify({"error": str(e)})
def storymap_image_list(user, id): """List storymap images """ try: key_prefix = storage.key_prefix(user["uid"], id, "_images") key_list, more = storage.list_key_names(key_prefix, 999, "") image_list = [n.split("/")[-1] for n in key_list] return jsonify({"image_list": image_list}) except storage.StorageException, e: traceback.print_exc() return jsonify({"error": str(e), "error_detail": e.detail})
def storymap_migrate(user): """ Migrate a storymap @title = storymap title @url = storymap base url @draft_on = ... @published_on = ... @file_list = json encoded list of file names """ try: title, src_url, draft_on, file_list_json = _request_get_required( 'title', 'url', 'draft_on', 'file_list') published_on = _request_get('published_on') file_list = json.loads(file_list_json) dst_id = _make_storymap_id(user, title) dst_key_prefix = storage.key_prefix(user['uid'], dst_id) dst_url = settings.AWS_STORAGE_BUCKET_URL + dst_key_prefix dst_img_url = dst_url + '_images/' re_img = re.compile(r'.*\.(png|gif|jpg|jpeg)$', re.I) re_src = re.compile(r'%s' % src_url) for file_name in file_list: file_url = "%s%s" % (src_url, file_name) if file_name.endswith('.json'): key_name = storage.key_name(user['uid'], dst_id, file_name) r = requests.get(file_url) storage.save_json(key_name, re_src.sub(dst_img_url, r.text)) elif re_img.match(file_name): key_name = storage.key_name(user['uid'], dst_id, '_images', file_name) storage.save_from_url(key_name, file_url) else: continue # skip user['storymaps'][dst_id] = { 'id': dst_id, 'title': title, 'draft_on': draft_on, 'published_on': published_on } _user.save(user) _write_embed_draft(dst_key_prefix, user['storymaps'][dst_id]) if published_on: _write_embed_published(dst_key_prefix, user['storymaps'][dst_id]) return jsonify(user['storymaps'][dst_id]) except Exception, e: traceback.print_exc() return jsonify({'error': str(e)})
def storymap_image_list(user, id): """List storymap images """ try: key_prefix = storage.key_prefix(user['uid'], id, '_images') key_list, more = storage.list_key_names(key_prefix, 999, '') image_list = [n.split('/')[-1] for n in key_list] return jsonify({'image_list': image_list}) except storage.StorageException, e: traceback.print_exc() return jsonify({'error': str(e), 'error_detail': e.detail})
def storymap_migrate(user): """ Migrate a storymap @title = storymap title @url = storymap base url @draft_on = ... @published_on = ... @file_list = json encoded list of file names """ try: title, src_url, draft_on, file_list_json = _request_get_required( 'title', 'url', 'draft_on', 'file_list') published_on = _request_get('published_on') file_list = json.loads(file_list_json) dst_id = _make_storymap_id(user, title) dst_key_prefix = storage.key_prefix(user['uid'], dst_id) dst_url = settings.AWS_STORAGE_BUCKET_URL+dst_key_prefix dst_img_url = dst_url+'_images/' re_img = re.compile(r'.*\.(png|gif|jpg|jpeg)$', re.I) re_src = re.compile(r'%s' % src_url) for file_name in file_list: file_url = "%s%s" % (src_url, file_name) if file_name.endswith('.json'): key_name = storage.key_name(user['uid'], dst_id, file_name) r = requests.get(file_url) storage.save_json(key_name, re_src.sub(dst_img_url, r.text)) elif re_img.match(file_name): key_name = storage.key_name(user['uid'], dst_id, '_images', file_name) storage.save_from_url(key_name, file_url) else: continue # skip user['storymaps'][dst_id] = { 'id': dst_id, 'title': title, 'draft_on': draft_on, 'published_on': published_on } _user.save(user) _write_embed_draft(dst_key_prefix, user['storymaps'][dst_id]) if published_on: _write_embed_published(dst_key_prefix, user['storymaps'][dst_id]) return jsonify(user['storymaps'][dst_id]) except Exception, e: traceback.print_exc() return jsonify({'error': str(e)})
def storymap_delete(user, id): """Delete storymap""" try: key_prefix = storage.key_prefix(user['uid'], id) key_list, marker = storage.list_keys(key_prefix, 50) for key in key_list: storage.delete(key.name); del user['storymaps'][id] _user.save(user) return jsonify({}) except Exception, e: traceback.print_exc() return jsonify({'error': str(e)})
def storymap_delete(user, id): """Delete storymap""" try: key_prefix = storage.key_prefix(user['uid'], id) key_list, marker = storage.list_keys(key_prefix, 50) for key in key_list: storage.delete(key.name) del user['storymaps'][id] _user.save(user) return jsonify({}) except Exception, e: traceback.print_exc() return jsonify({'error': str(e)})
def storymap_migrate(user): """ Migrate a storymap @title = storymap title @url = storymap base url @draft_on = ... @published_on = ... @file_list = json encoded list of file names """ try: title, src_url, draft_on, file_list_json = _request_get_required("title", "url", "draft_on", "file_list") published_on = _request_get("published_on") file_list = json.loads(file_list_json) dst_id = _make_storymap_id(user, title) dst_key_prefix = storage.key_prefix(user["uid"], dst_id) dst_url = settings.AWS_STORAGE_BUCKET_URL + dst_key_prefix dst_img_url = dst_url + "_images/" re_img = re.compile(r".*\.(png|gif|jpg|jpeg)$", re.I) re_src = re.compile(r"%s" % src_url) for file_name in file_list: file_url = "%s%s" % (src_url, file_name) if file_name.endswith(".json"): key_name = storage.key_name(user["uid"], dst_id, file_name) r = requests.get(file_url) storage.save_json(key_name, re_src.sub(dst_img_url, r.text)) elif re_img.match(file_name): key_name = storage.key_name(user["uid"], dst_id, "_images", file_name) storage.save_from_url(key_name, file_url) else: continue # skip user["storymaps"][dst_id] = {"id": dst_id, "title": title, "draft_on": draft_on, "published_on": published_on} _user.save(user) _write_embed_draft(dst_key_prefix, user["storymaps"][dst_id]) if published_on: _write_embed_published(dst_key_prefix, user["storymaps"][dst_id]) return jsonify(user["storymaps"][dst_id]) except Exception, e: traceback.print_exc() return jsonify({"error": str(e)})
def storymap_publish(user, id): """Save published storymap""" try: data = _request_get_required('d') key_prefix = storage.key_prefix(user['uid'], id) content = json.loads(data) storage.save_json(key_prefix+'published.json', content) user['storymaps'][id]['published_on'] = _utc_now() _user.save(user) _write_embed_published(key_prefix, user['storymaps'][id]) return jsonify({'meta': user['storymaps'][id]}) except storage.StorageException, e: traceback.print_exc() return jsonify({'error': str(e), 'error_detail': e.detail})
def storymap_publish(user, id): """Save published storymap""" try: data = _request_get_required("d") key_prefix = storage.key_prefix(user["uid"], id) content = json.loads(data) storage.save_json(key_prefix + "published.json", content) user["storymaps"][id]["published_on"] = _utc_now() _user.save(user) _write_embed_published(key_prefix, user["storymaps"][id]) return jsonify({"meta": user["storymaps"][id]}) except storage.StorageException, e: traceback.print_exc() return jsonify({"error": str(e), "error_detail": e.detail})
def storymap_update_meta(user, id): """Update storymap meta value""" try: key, value = _request_get_required("key", "value") user["storymaps"][id][key] = value _user.save(user) key_prefix = storage.key_prefix(user["uid"], id) if key in ["title", "description", "image_url"]: _write_embed_draft(key_prefix, user["storymaps"][id]) if user["storymaps"][id].get("published_on"): _write_embed_published(key_prefix, user["storymaps"][id]) return jsonify(user["storymaps"][id]) except Exception, e: traceback.print_exc() return jsonify({"error": str(e)})
def storymap_update_meta(user, id): """Update storymap meta value""" try: key, value = _request_get_required('key', 'value') user['storymaps'][id][key] = value _user.save(user) key_prefix = storage.key_prefix(user['uid'], id) if key in ['title', 'description', 'image_url']: _write_embed_draft(key_prefix, user['storymaps'][id]) if user['storymaps'][id].get('published_on'): _write_embed_published(key_prefix, user['storymaps'][id]) return jsonify(user['storymaps'][id]) except Exception, e: traceback.print_exc() return jsonify({'error': str(e)})
def storymap_create(user): """Create a storymap""" try: title, data = _request_get_required("title", "d") id = _make_storymap_id(user, title) key_prefix = storage.key_prefix(user["uid"], id) content = json.loads(data) storage.save_json(key_prefix + "draft.json", content) user["storymaps"][id] = {"id": id, "title": title, "draft_on": _utc_now(), "published_on": ""} _user.save(user) _write_embed_draft(key_prefix, user["storymaps"][id]) return jsonify({"id": id}) except Exception, e: traceback.print_exc() return jsonify({"error": str(e)})
def _make_storymap_id(user, title): """Get unique storymap id from slugified title""" id_set = set(user['storymaps'].keys()) # Add keys from S3 (in case of db issues) user_key_prefix = storage.key_prefix(user['uid']) regex = re.compile(r'^%s([^/]+).*' % user_key_prefix) name_list, more = storage.list_key_names(user_key_prefix, 999, '') for name in name_list: m = regex.match(name) if m: id_set.add(m.group(1)) id_base = slugify.slugify(title) id = id_base n = 0 while id in id_set: n += 1 id = '%s-%d' % (id_base, n) return id
def storymap_export(user, id): """ Download a zip file of the StoryMap's data, for importing or self-hosting """ key_prefix = storage.key_prefix(user['uid'], id) key_list, _ = storage.list_keys(key_prefix, 999, '') temp_file, temp_path = tempfile.mkstemp() @after_this_request def cleanup_temp_file(response): os.close(temp_file) os.remove(temp_path) return response with ZipFile(temp_path, mode='a') as zip_file: zip_file.writestr('metadata.json', json.dumps(user['storymaps'][id])) for key in key_list: file_name = key.name.split(key_prefix)[-1] zip_file.writestr(file_name, storage.get_contents_as_string(key)) return send_file(temp_path, as_attachment=True, attachment_filename=('storymap-%s.zip' % id))
from storymap import storage from api import app, _write_embed_draft, _write_embed_published from flask import g # Find all storymaps with ids that contain bad chars print 'Examining StoryMaps' regex = re.compile('[^A-Za-z0-9_\-]') skip = 0 limit = 100 n = _user.count() while skip < n: for user in _user.find({}, skip=skip, limit=limit): for id in [id for id in user['storymaps'].keys() if regex.search(id)]: key_prefix = storage.key_prefix(user['uid'], id) with app.test_request_context(): print 'Writing embed draft for %s' % key_prefix _write_embed_draft(key_prefix, user['storymaps'][id]) if user['storymaps'][id].get('published_on'): print 'Writing embed published for %s' % key_prefix _write_embed_published(key_prefix, user['storymaps'][id]) skip += limit sys.exit(0)
from storymap import storage from api import app, _write_embed_draft, _write_embed_published from flask import g # Find all storymaps with ids that contain bad chars print "Examining StoryMaps" regex = re.compile("[^A-Za-z0-9_\-]") skip = 0 limit = 100 n = _user.count() while skip < n: for user in _user.find({}, skip=skip, limit=limit): for id in [id for id in user["storymaps"].keys() if regex.search(id)]: key_prefix = storage.key_prefix(user["uid"], id) with app.test_request_context(): print "Writing embed draft for %s" % key_prefix _write_embed_draft(key_prefix, user["storymaps"][id]) if user["storymaps"][id].get("published_on"): print "Writing embed published for %s" % key_prefix _write_embed_published(key_prefix, user["storymaps"][id]) skip += limit sys.exit(0)