def delete_by_id(): id = request.args.get('id') post = Post.load_by_id(id) if not post: abort(404) post.deleted = True db.session.commit() hooks.fire('post-deleted', post, request.args) redirect_url = request.args.get('redirect') or url_for('views.index') current_app.logger.debug('redirecting to {}'.format(redirect_url)) return redirect(redirect_url)
def save_venue(venue): venue.name = request.form.get('name') venue.location = { 'latitude': float(request.form.get('latitude')), 'longitude': float(request.form.get('longitude')), } venue.update_slug(request.form.get('geocode')) if not venue.id: db.session.add(venue) db.session.commit() hooks.fire('venue-saved', venue, request.form) return redirect(url_for('venue_by_slug', slug=venue.slug))
def save_venue(venue): venue.name = request.form.get('name') venue.location = { 'latitude': float(request.form.get('latitude')), 'longitude': float(request.form.get('longitude')), } venue.update_slug(request.form.get('geocode')) if not venue.id: db.session.add(venue) db.session.commit() hooks.fire('venue-saved', venue, request.form) return redirect(url_for('.venue_by_slug', slug=venue.slug))
def save_post(post): was_draft = post.draft pub_str = request.form.get('published') if pub_str: post.published = mf2util.parse_dt(pub_str) start_str = request.form.get('start') if start_str: start = mf2util.parse_dt(start_str) if start: post.start = start post.start_utcoffset = start.utcoffset() end_str = request.form.get('end') if end_str: end = mf2util.parse_dt(end_str) if end: post.end = end post.end_utcoffset = end.utcoffset() now = datetime.datetime.utcnow() if not post.published or was_draft: post.published = now post.updated = now # populate the Post object and save it to the database, # redirect to the view post.title = request.form.get('title', '') post.content = request.form.get('content') post.draft = request.form.get('action') == 'save_draft' post.hidden = request.form.get('hidden', 'false') == 'true' venue_name = request.form.get('new_venue_name') venue_lat = request.form.get('new_venue_latitude') venue_lng = request.form.get('new_venue_longitude') if venue_name and venue_lat and venue_lng: venue = Venue() venue.name = venue_name venue.location = { 'latitude': float(venue_lat), 'longitude': float(venue_lng), } venue.update_slug('{}-{}'.format(venue_lat, venue_lng)) db.session.add(venue) db.session.commit() hooks.fire('venue-saved', venue, request.form) post.venue = venue else: venue_id = request.form.get('venue') if venue_id: post.venue = Venue.query.get(venue_id) lat = request.form.get('latitude') lon = request.form.get('longitude') if lat and lon: if post.location is None: post.location = {} post.location['latitude'] = float(lat) post.location['longitude'] = float(lon) loc_name = request.form.get('location_name') if loc_name is not None: post.location['name'] = loc_name else: post.location = None for url_attr, context_attr in (('in_reply_to', 'reply_contexts'), ('repost_of', 'repost_contexts'), ('like_of', 'like_contexts'), ('bookmark_of', 'bookmark_contexts')): url_str = request.form.get(url_attr) if url_str is not None: urls = util.multiline_string_to_list(url_str) setattr(post, url_attr, urls) # fetch contexts before generating a slug contexts.fetch_contexts(post) syndication = request.form.get('syndication') if syndication is not None: post.syndication = util.multiline_string_to_list(syndication) audience = request.form.get('audience') if audience is not None: post.audience = util.multiline_string_to_list(audience) tags = request.form.getlist('tags') if post.post_type != 'article' and post.content: # parse out hashtags as tag links from note-like posts tags += util.find_hashtags(post.content) tags = list(filter(None, map(util.normalize_tag, tags))) post.tags = [Tag.query.filter_by(name=tag).first() or Tag(tag) for tag in tags] slug = request.form.get('slug') if slug: post.slug = util.slugify(slug) elif not post.slug or was_draft: post.slug = post.generate_slug() # events should use their start date for permalinks path_date = post.start or post.published if post.draft: m = hashlib.md5() m.update(bytes(path_date.isoformat() + '|' + post.slug, 'utf-8')) post.path = 'drafts/{}'.format(m.hexdigest()) elif not post.path or was_draft: base_path = '{}/{:02d}/{}'.format( path_date.year, path_date.month, post.slug) # generate a unique path unique_path = base_path idx = 1 while Post.load_by_path(unique_path): unique_path = '{}-{}'.format(base_path, idx) idx += 1 post.path = unique_path # generate short path if not post.short_path: short_base = '{}/{}'.format( util.tag_for_post_type(post.post_type), util.base60_encode(util.date_to_ordinal(path_date))) short_paths = set( row[0] for row in db.session.query(Post.short_path).filter( Post.short_path.startswith(short_base)).all()) for idx in itertools.count(1): post.short_path = short_base + util.base60_encode(idx) if post.short_path not in short_paths: break infiles = request.files.getlist('files') + request.files.getlist('photo') current_app.logger.debug('infiles: %s', infiles) for infile in infiles: if infile and infile.filename: current_app.logger.debug('receiving uploaded file %s', infile) attachment = create_attachment_from_file(post, infile) os.makedirs(os.path.dirname(attachment.disk_path), exist_ok=True) infile.save(attachment.disk_path) post.attachments.append(attachment) # pre-render the post html html = util.markdown_filter(post.content, img_path=post.get_image_path()) html = util.autolink(html) if post.post_type == 'article': html = util.process_people_to_microcards(html) else: html = util.process_people_to_at_names(html) post.content_html = html if not post.id: db.session.add(post) db.session.commit() current_app.logger.debug('saved post %d %s', post.id, post.permalink) redirect_url = post.permalink hooks.fire('post-saved', post, request.form) return redirect(redirect_url)
def do_process_webmention(source, target, callback, app_config): def call_callback(result): if callback: requests.post(callback, data=result) with async_app_context(app_config): try: result = interpret_mention(source, target) if result.error: current_app.logger.warn("Failed to process webmention: %s", result.error) response = { "source": source, "target": target, "response_code": 400, "status": "error", "reason": result.error, } call_callback(response) return response if result.post and result.delete: result.post.mentions = [m for m in result.post.mentions if m.url != source] elif result.post: result.post.mentions.extend(result.mentions) db.session.commit() current_app.logger.debug("saved mentions to %s", result.post.path) hooks.fire("mention-received", post=result.post) if result.post: for mres in result.mention_results: if mres.create: send_push_notification(result.post, mres.mention, app_config) response = { "source": source, "target": target, "response_code": 200, "status": "success", "reason": "Deleted" if result.delete else "Created" if any(mres.create for mres in result.mention_results) else "Updated", } call_callback(response) return response except Exception as e: current_app.logger.exception("exception while processing webmention") response = { "source": source, "target": target, "response_code": 400, "status": "error", "reason": "exception while processing webmention {}".format(e), } call_callback(response) return response
def do_process_webmention(source, target, callback, app_config): def call_callback(result): if callback: requests.post(callback, data=result) with async_app_context(app_config): try: result = interpret_mention(source, target) if result.error: current_app.logger.warn( 'Failed to process webmention: %s', result.error) response = { 'source': source, 'target': target, 'response_code': 400, 'status': 'error', 'reason': result.error } call_callback(response) return response if result.post and result.delete: result.post.mentions = [m for m in result.post.mentions if m.url != source] elif result.post: result.post.mentions.extend(result.mentions) elif result.is_person_mention: db.session.add_all(result.mentions) db.session.commit() current_app.logger.debug("saved mentions to %s", result.post.path if result.post else '/') hooks.fire('mention-received', post=result.post) for mres in result.mention_results: if mres.create: send_push_notification(result.post, result.is_person_mention, mres.mention, app_config) response = { 'source': source, 'target': target, 'response_code': 200, 'status': 'success', 'reason': 'Deleted' if result.delete else 'Created' if any(mres.create for mres in result.mention_results) else 'Updated' } call_callback(response) return response except Exception as e: current_app.logger.exception( "exception while processing webmention") response = { 'source': source, 'target': target, 'response_code': 400, 'status': 'error', 'reason': "exception while processing webmention {}".format(e) } call_callback(response) return response
def do_process_webmention(source, target, callback, app_config): def call_callback(result): if callback: requests.post(callback, data=result) with async_app_context(app_config): try: result = interpret_mention(source, target) if result.error: current_app.logger.warn('Failed to process webmention: %s', result.error) response = { 'source': source, 'target': target, 'response_code': 400, 'status': 'error', 'reason': result.error } call_callback(response) return response if result.post and result.delete: result.post.mentions = [ m for m in result.post.mentions if m.url != source ] elif result.post: result.post.mentions.extend(result.mentions) elif result.is_person_mention: db.session.add_all(result.mentions) db.session.commit() current_app.logger.debug("saved mentions to %s", result.post.path if result.post else '/') hooks.fire('mention-received', post=result.post) for mres in result.mention_results: if mres.create: send_push_notification(result.post, result.is_person_mention, mres.mention, app_config) response = { 'source': source, 'target': target, 'response_code': 200, 'status': 'success', 'reason': 'Deleted' if result.delete else 'Created' if any( mres.create for mres in result.mention_results) else 'Updated' } call_callback(response) return response except Exception as e: current_app.logger.exception( "exception while processing webmention") response = { 'source': source, 'target': target, 'response_code': 400, 'status': 'error', 'reason': "exception while processing webmention {}".format(e) } call_callback(response) return response
def save_post(post): was_draft = post.draft pub_str = request.form.get('published') if pub_str: post.published = mf2util.parse_dt(pub_str) if post.published.tzinfo: post.published = post.published.astimezone(datetime.timezone.utc)\ .replace(tzinfo=None) if 'post_type' in request.form: post.post_type = request.form.get('post_type') start_str = request.form.get('start') if start_str: start = mf2util.parse_dt(start_str) if start: post.start = start post.start_utcoffset = start.utcoffset() end_str = request.form.get('end') if end_str: end = mf2util.parse_dt(end_str) if end: post.end = end post.end_utcoffset = end.utcoffset() now = datetime.datetime.utcnow() if not post.published or was_draft: post.published = now post.updated = now # populate the Post object and save it to the database, # redirect to the view post.title = request.form.get('title', '') post.content = request.form.get('content') post.draft = request.form.get('action') == 'save_draft' post.hidden = request.form.get('hidden', 'false') == 'true' post.friends_only = request.form.get('friends_only', 'false') == 'true' venue_name = request.form.get('new_venue_name') venue_lat = request.form.get('new_venue_latitude') venue_lng = request.form.get('new_venue_longitude') if venue_name and venue_lat and venue_lng: venue = Venue() venue.name = venue_name venue.location = { 'latitude': float(venue_lat), 'longitude': float(venue_lng), } venue.update_slug('{}-{}'.format(venue_lat, venue_lng)) db.session.add(venue) db.session.commit() hooks.fire('venue-saved', venue, request.form) post.venue = venue else: venue_id = request.form.get('venue') if venue_id: post.venue = Venue.query.get(venue_id) lat = request.form.get('latitude') lon = request.form.get('longitude') if lat and lon: if post.location is None: post.location = {} post.location['latitude'] = float(lat) post.location['longitude'] = float(lon) loc_name = request.form.get('location_name') if loc_name is not None: post.location['name'] = loc_name else: post.location = None for url_attr, context_attr in (('in_reply_to', 'reply_contexts'), ('repost_of', 'repost_contexts'), ('like_of', 'like_contexts'), ('bookmark_of', 'bookmark_contexts')): url_str = request.form.get(url_attr) if url_str is not None: urls = util.multiline_string_to_list(url_str) setattr(post, url_attr, urls) # fetch contexts before generating a slug contexts.fetch_contexts(post) if 'item-name' in request.form: post.item = util.trim_nulls({ 'name': request.form.get('item-name'), 'author': request.form.get('item-author'), 'photo': request.form.get('item-photo'), }) if 'rating' in request.form: rating = request.form.get('rating') post.rating = int(rating) if rating else None syndication = request.form.get('syndication') if syndication is not None: post.syndication = util.multiline_string_to_list(syndication) audience = request.form.get('audience') if audience is not None: post.audience = util.multiline_string_to_list(audience) tags = request.form.getlist('tags') if post.post_type != 'article' and post.content: # parse out hashtags as tag links from note-like posts tags += util.find_hashtags(post.content) tags = list(filter(None, map(util.normalize_tag, tags))) post.tags = [Tag.query.filter_by(name=tag).first() or Tag(tag) for tag in tags] post.people = [] people = request.form.getlist('people') for person in people: nick = Nick.query.filter_by(name=person).first() if nick: post.people.append(nick.contact) slug = request.form.get('slug') if slug: post.slug = util.slugify(slug) elif not post.slug or was_draft: post.slug = post.generate_slug() # events should use their start date for permalinks path_date = post.start or post.published if post.draft: m = hashlib.md5() m.update(bytes(path_date.isoformat() + '|' + post.slug, 'utf-8')) post.path = 'drafts/{}'.format(m.hexdigest()) elif not post.path or was_draft: base_path = '{}/{:02d}/{}'.format( path_date.year, path_date.month, post.slug) # generate a unique path unique_path = base_path idx = 1 while Post.load_by_path(unique_path): unique_path = '{}-{}'.format(base_path, idx) idx += 1 post.path = unique_path # generate short path if not post.short_path: short_base = '{}/{}'.format( util.tag_for_post_type(post.post_type), util.base60_encode(util.date_to_ordinal(path_date))) short_paths = set( row[0] for row in db.session.query(Post.short_path).filter( Post.short_path.startswith(short_base)).all()) for idx in itertools.count(1): post.short_path = short_base + util.base60_encode(idx) if post.short_path not in short_paths: break infiles = request.files.getlist('files') + request.files.getlist('photo') current_app.logger.debug('infiles: %s', infiles) for infile in infiles: if infile and infile.filename: current_app.logger.debug('receiving uploaded file %s', infile) attachment = create_attachment_from_file(post, infile) os.makedirs(os.path.dirname(attachment.disk_path), exist_ok=True) infile.save(attachment.disk_path) post.attachments.append(attachment) photo_url = request.form.get('photo') if photo_url: current_app.logger.debug('downloading photo from url %s', photo_url) temp_filename, headers = urllib.request.urlretrieve(photo_url) content_type = headers.get('content-type', '') mimetype = content_type and content_type.split(';')[0].strip() filename = os.path.basename(urllib.parse.urlparse(photo_url).path) attachment = create_attachment(post, filename, mimetype) os.makedirs(os.path.dirname(attachment.disk_path), exist_ok=True) shutil.copyfile(temp_filename, attachment.disk_path) urllib.request.urlcleanup() post.attachments.append(attachment) # pre-render the post html html = util.markdown_filter(post.content, img_path=post.get_image_path()) html = util.autolink(html) if post.post_type == 'article': html = util.process_people_to_microcards(html) else: html = util.process_people_to_at_names(html) post.content_html = html if not post.id: db.session.add(post) db.session.commit() current_app.logger.debug('saved post %d %s', post.id, post.permalink) redirect_url = post.permalink hooks.fire('post-saved', post, request.form) return redirect(redirect_url)