def authorize_facebook(): import urllib.parse import urllib.request redirect_uri = url_for('.authorize_facebook', _external=True) params = { 'client_id': get_settings().facebook_app_id, 'redirect_uri': redirect_uri, 'scope': 'publish_actions,user_photos', } code = request.args.get('code') if code: params['code'] = code params['client_secret'] = get_settings().facebook_app_secret r = urllib.request.urlopen( 'https://graph.facebook.com/oauth/access_token?' + urllib.parse.urlencode(params)) payload = urllib.parse.parse_qs(r.read()) access_token = payload[b'access_token'][0].decode('ascii') Setting.query.get('facebook_access_token').value = access_token db.session.commit() return redirect(url_for('admin.edit_settings')) else: return redirect('https://graph.facebook.com/oauth/authorize?' + urllib.parse.urlencode(params))
def authorize_wordpress(): from redwind.extensions import db redirect_uri = url_for('.authorize_wordpress', _external=True) code = request.args.get('code') if code: r = requests.post(API_TOKEN_URL, data={ 'client_id': get_settings().wordpress_client_id, 'redirect_uri': redirect_uri, 'client_secret': get_settings().wordpress_client_secret, 'code': code, 'grant_type': 'authorization_code', }) if r.status_code // 100 != 2: return make_response( 'Code: {}. Message: {}'.format(r.status_code, r.text), r.status_code) payload = r.json() access_token = payload.get('access_token') Setting.query.get('wordpress_access_token').value = access_token db.session.commit() return redirect(url_for('admin.edit_settings')) else: return redirect(API_AUTHORIZE_URL + '?' + urllib.parse.urlencode({ 'client_id': get_settings().wordpress_client_id, 'redirect_uri': redirect_uri, 'response_type': 'code', 'scope': 'global', }))
def login_facebook(): redirect_uri = url_for('.login_facebook', _external=True) params = { 'client_id': get_settings().facebook_app_id, 'redirect_uri': redirect_uri, } if 'code' not in request.args: return redirect('https://www.facebook.com/dialog/oauth?' + urllib.parse.urlencode(params)) params['code'] = request.args.get('code') params['client_secret'] = get_settings().facebook_app_secret r = requests.get('https://graph.facebook.com/v2.3/oauth/access_token', params=params) access_token = r.json().get('access_token') r = requests.get('https://graph.facebook.com/v2.2/me', params={'access_token': access_token}) user_json = r.json() fbid = user_json.get('id') name = user_json.get('name') cred = Credential.query.get(('facebook', fbid)) if not cred: cred = Credential(type='facebook', value=fbid, display=name) db.session.add(cred) db.session.commit() return do_login(cred, user_json.get('name'))
def share_on_facebook(): from .twitter import collect_images if request.method == "GET": post = Post.load_by_id(request.args.get("id")) message, link, name, picture = guess_content(post) imgs = [urljoin(get_settings().site_url, img) for img in collect_images(post)] albums = [] if imgs: current_app.logger.debug("fetching user albums") resp = requests.get( "https://graph.facebook.com/v2.2/me/albums", params={"access_token": get_settings().facebook_access_token}, ) resp.raise_for_status() current_app.logger.debug("user albums response %s: %s", resp, resp.text) albums = resp.json().get("data", []) return render_template( "admin/share_on_facebook.jinja2", post=post, preview=message, link=link, name=name, picture=picture, imgs=imgs, albums=albums, ) try: post_id = request.form.get("post_id") preview = request.form.get("preview") img_url = request.form.get("img") is_photo = request.form.get("post_type") == "photo" album_id = request.form.get("album") link = request.form.get("link") if album_id == "new": album_id = create_album(request.form.get("new_album_name"), request.form.get("new_album_message")) post = Post.load_by_id(post_id) facebook_url = handle_new_or_edit( post, message=preview, link=link, name=None, picture=img_url, is_photo=is_photo, album_id=album_id ) db.session.commit() if has_request_context(): flash( 'Shared on Facebook: <a href="{}">Original</a>, ' '<a href="{}">On Facebook</a><br/>'.format(post.permalink, facebook_url) ) return redirect(post.permalink) except Exception as e: if has_request_context(): current_app.logger.exception("posting to facebook") flash("Share on Facebook Failed! Exception: {}".format(e)) return redirect(url_for("views.index"))
def login_twitter(): callback_url = url_for('.login_twitter', _external=True) try: oauth_session = OAuth1Session( client_key=get_settings().twitter_api_key, client_secret=get_settings().twitter_api_secret, callback_uri=callback_url) if 'oauth_token' not in request.args: oauth_session.fetch_request_token( 'https://api.twitter.com/oauth/request_token') return redirect(oauth_session.authorization_url( 'https://api.twitter.com/oauth/authenticate')) oauth_session.parse_authorization_response(request.url) oauth_session.fetch_access_token( 'https://api.twitter.com/oauth/access_token') user_response = oauth_session.get( 'https://api.twitter.com/1.1/account/verify_credentials.json') user_json = user_response.json() twid = user_json.get('id_str') screen_name = user_json.get('screen_name') cred = Credential.query.get(('twitter', twid)) if not cred: cred = Credential(type='twitter', value=twid, display=screen_name) db.session.add(cred) db.session.commit() return do_login(cred, user_json.get('name')) except requests.RequestException as e: return make_response(str(e))
def share_on_facebook(): from .twitter import collect_images if request.method == 'GET': post = Post.load_by_id(request.args.get('id')) message, link, name, picture = guess_content(post) imgs = [urljoin(get_settings().site_url, img) for img in collect_images(post)] albums = [] if imgs: current_app.logger.debug('fetching user albums') resp = requests.get( 'https://graph.facebook.com/v2.2/me/albums', params={'access_token': get_settings().facebook_access_token}) resp.raise_for_status() current_app.logger.debug( 'user albums response %s: %s', resp, resp.text) albums = resp.json().get('data', []) return render_template('admin/share_on_facebook.jinja2', post=post, preview=message, link=link, name=name, picture=picture, imgs=imgs, albums=albums) try: post_id = request.form.get('post_id') preview = request.form.get('preview') img_url = request.form.get('img') is_photo = request.form.get('post_type') == 'photo' album_id = request.form.get('album') link = request.form.get('link') if album_id == 'new': album_id = create_album( request.form.get('new_album_name'), request.form.get('new_album_message')) post = Post.load_by_id(post_id) facebook_url = handle_new_or_edit( post, message=preview, link=link, name=None, picture=img_url, is_photo=is_photo, album_id=album_id) db.session.commit() if has_request_context(): flash('Shared on Facebook: <a href="{}">Original</a>, ' '<a href="{}">On Facebook</a><br/>' .format(post.permalink, facebook_url)) return redirect(post.permalink) except Exception as e: if has_request_context(): current_app.logger.exception('posting to facebook') flash('Share on Facebook Failed! Exception: {}'.format(e)) return redirect(url_for('views.index'))
def share_on_facebook(): from .twitter import collect_images if request.method == 'GET': post = Post.load_by_id(request.args.get('id')) message, link, name, picture = guess_content(post) imgs = [urllib.parse.urljoin(get_settings().site_url, img) for img in collect_images(post)] albums = [] if imgs: current_app.logger.debug('fetching user albums') resp = requests.get( 'https://graph.facebook.com/v2.2/me/albums', params={'access_token': get_settings().facebook_access_token}) resp.raise_for_status() current_app.logger.debug( 'user albums response %s: %s', resp, resp.text) albums = resp.json().get('data', []) return render_template('admin/share_on_facebook.jinja2', post=post, preview=message, link=link, name=name, picture=picture, imgs=imgs, albums=albums) try: post_id = request.form.get('post_id') preview = request.form.get('preview') img_url = request.form.get('img') is_photo = request.form.get('post_type') == 'photo' album_id = request.form.get('album') link = request.form.get('link') if album_id == 'new': album_id = create_album( request.form.get('new_album_name'), request.form.get('new_album_message')) post = Post.load_by_id(post_id) facebook_url = handle_new_or_edit( post, message=preview, link=link, name=None, picture=img_url, is_photo=is_photo, album_id=album_id) db.session.commit() if has_request_context(): flash('Shared on Facebook: <a href="{}">Original</a>, ' '<a href="{}">On Facebook</a><br/>' .format(post.permalink, facebook_url)) return redirect(post.permalink) except Exception as e: if has_request_context(): current_app.logger.exception('posting to facebook') flash('Share on Facebook Failed! Exception: {}'.format(e)) return redirect(url_for('views.index'))
def authorize_twitter(): """Get an access token from Twitter and redirect to the authentication page""" callback_url = url_for('.twitter_callback', _external=True) try: oauth = OAuth1Session(client_key=get_settings().twitter_api_key, client_secret=get_settings().twitter_api_secret, callback_uri=callback_url) oauth.fetch_request_token(REQUEST_TOKEN_URL) return redirect(oauth.authorization_url(AUTHORIZE_URL)) except requests.RequestException as e: return make_response(str(e))
def authorize_twitter(): """Get an access token from Twitter and redirect to the authentication page""" callback_url = url_for('.twitter_callback', _external=True) try: oauth = OAuth1Session( client_key=get_settings().twitter_api_key, client_secret=get_settings().twitter_api_secret, callback_uri=callback_url) oauth.fetch_request_token(REQUEST_TOKEN_URL) return redirect(oauth.authorization_url(AUTHORIZE_URL)) except requests.RequestException as e: return make_response(str(e))
def time_filter(thedate): if thedate: if hasattr(thedate, 'tzinfo') and not thedate.tzinfo: tz = pytz.timezone(get_settings().timezone) thedate = pytz.utc.localize(thedate).astimezone(tz) if isinstance(thedate, datetime.datetime): return thedate.strftime('%-I:%M%P %Z')
def index(before_ts=None): post_types = [type[0] for type in POST_TYPES if type[0] != 'event'] posts, older = collect_posts(post_types, before_ts, int(get_settings().posts_per_page), None, include_hidden=False) if request.args.get('feed') == 'atom': return render_posts_atom('Stream', 'index.atom', posts) resp = make_response( render_posts('Stream', posts, older, events=collect_upcoming_events(), template='home.jinja2')) if 'PUSH_HUB' in current_app.config: resp.headers.add( 'Link', '<{}>; rel="hub"'.format(current_app.config['PUSH_HUB'])) resp.headers.add( 'Link', '<{}>; rel="self"'.format(url_for('.index', _external=True))) return resp
def everything(before_ts=None): posts, older = collect_posts( None, before_ts, int(get_settings().posts_per_page), None, include_hidden=True) if request.args.get('feed') == 'atom': return render_posts_atom('Everything', 'everything.atom', posts) return render_posts('Everything', posts, older)
def repl(m): url = m.group(2) # don't proxy images that come from this site if url.startswith(get_settings().site_url): return m.group(0) url = url.replace('&', '&') return '<img{} src="{}"'.format( m.group(1), imageproxy.imageproxy_filter(url, side))
def posts_by_tag(tag, before_ts=None): posts, older = collect_posts( None, before_ts, int(get_settings().posts_per_page), tag, include_hidden=True) title = '#' + tag if request.args.get('feed') == 'atom': return render_posts_atom(title, 'tag-' + tag + '.atom', posts) return render_posts(title, posts, older)
def isotime_filter(thedate): if thedate: thedate = thedate.replace(microsecond=0) if hasattr(thedate, 'tzinfo') and not thedate.tzinfo: tz = pytz.timezone(get_settings().timezone) thedate = pytz.utc.localize(thedate).astimezone(tz) if isinstance(thedate, datetime.datetime): return thedate.isoformat('T') return thedate.isoformat()
def login_callback(): current_app.logger.debug('callback fields: %s', request.args) state = request.args.get('state') next_url = state or url_for('views.index') # TODO rediscover these endpoints based on 'me'. Assuming # they are the same is not totally safe. auth_url, token_url, micropub_url = session['endpoints'] if not auth_url: flash('Login failed: No authorization URL in session') return redirect(next_url) code = request.args.get('code') client_id = get_settings().site_url redirect_uri = url_for('.login_callback', _external=True) current_app.logger.debug('callback with auth endpoint %s', auth_url) response = requests.post(auth_url, data={ 'code': code, 'client_id': client_id, 'redirect_uri': redirect_uri, 'state': state, }) rdata = urllib.parse.parse_qs(response.text) if response.status_code != 200: current_app.logger.debug('call to auth endpoint failed %s', response) flash('Login failed {}: {}'.format(rdata.get('error'), rdata.get('error_description'))) return redirect(next_url) current_app.logger.debug('verify response %s', response.text) if 'me' not in rdata: current_app.logger.debug('Verify response missing required "me" field') flash('Verify response missing required "me" field {}'.format( response.text)) return redirect(next_url) me = rdata.get('me')[0] scopes = rdata.get('scope') try_micropub_config(token_url, micropub_url, scopes, code, me, redirect_uri, client_id, state) cred = Credential.query.get(('indieauth', me)) if not cred: cred = Credential(type='indieauth', value=me, display=me) db.session.add(cred) db.session.commit() # offer to associate credential with existing user or create a new user p = mf2py.parse(url=me) hcard = mf2util.representative_hcard(p, me) author = hcard and mf2util.parse_author(hcard) return do_login(cred, author and author.get('name'), next_url)
def get_taggable_friends(self): if not self.taggable_friends: r = requests.get( "https://graph.facebook.com/v2.0/me/taggable_friends", params={"access_token": get_settings().facebook_access_token}, ) self.taggable_friends = r.json() return self.taggable_friends or {}
def search(before_ts=None): q = request.args.get('q') if not q: abort(404) posts, older = collect_posts( None, before_ts, int(get_settings().posts_per_page), None, include_hidden=True, search=q) return render_posts('Search: ' + q, posts, older)
def interpret_mention(source, target): current_app.logger.debug("processing webmention from %s to %s", source, target) if target and target.strip("/") == get_settings().site_url.strip("/"): # received a domain-level mention current_app.logger.debug("received domain-level webmention from %s", source) target_post = None target_urls = (target,) # TODO save domain-level webmention somewhere return ProcessResult(error="Receiving domain-level webmentions is not yet implemented") else: # confirm that target is a valid link to a post target_post = find_target_post(target) if not target_post: current_app.logger.warn("Webmention could not find target post: %s. Giving up", target) return ProcessResult(error="Webmention could not find target post: {}".format(target)) target_urls = (target, target_post.permalink) if source in target_urls: return ProcessResult(error="{} and {} refer to the same post".format(source, target)) # confirm that source actually refers to the post source_response = util.fetch_html(source) current_app.logger.debug("received response from source %s", source_response) if source_response.status_code == 410: current_app.logger.debug("Webmention indicates original was deleted") return ProcessResult(post=target_post, delete=True) if source_response.status_code // 100 != 2: current_app.logger.warn("Webmention could not read source post: %s. Giving up", source) return ProcessResult( post=target_post, error="Bad response when reading source post: {}, {}".format(source, source_response) ) source_length = source_response.headers.get("Content-Length") if source_length and int(source_length) > 2097152: current_app.logger.warn("Very large source. length=%s", source_length) return ProcessResult(post=target_post, error="Source is very large. Length={}".format(source_length)) link_to_target = find_link_to_target(source, source_response, target_urls) if not link_to_target: current_app.logger.warn( "Webmention source %s does not appear to link to target %s. " "Giving up", source, target ) return ProcessResult(post=target_post, error="Could not find any links from source to target") mentions = create_mentions(target_post, source, source_response) if not mentions: return ProcessResult(post=target_post, error="Could not parse a mention from the source") result = ProcessResult(post=target_post) for mention in mentions: result.add_mention(mention, create=not mention.id) return result
def posts_by_type(plural_type, before_ts=None): post_type, _, title = next(tup for tup in POST_TYPES if tup[1] == plural_type) posts, older = collect_posts( (post_type,), before_ts, int(get_settings().posts_per_page), None, include_hidden=True) if request.args.get('feed') == 'atom': return render_posts_atom(title, plural_type + '.atom', posts) return render_posts(title, posts, older)
def everything(before_ts=None): posts, older = collect_posts(None, before_ts, int(get_settings().posts_per_page), None, include_hidden=True) if request.args.get('feed') == 'atom': return render_posts_atom('Everything', 'everything.atom', posts) return render_posts('Everything', posts, older)
def construct_url(url, size=None, external=False): from redwind.models import get_settings if not url or 'PILBOX_URL' not in current_app.config: return url url = urllib.parse.urljoin(get_settings().site_url, url) query = [('url', url)] if size: query += [('w', size), ('h', size), ('mode', 'clip')] else: query += [('op', 'noop')] querystring = urllib.parse.urlencode(query) if 'PILBOX_KEY' in current_app.config: h = hmac.new(current_app.config['PILBOX_KEY'].encode(), querystring.encode(), hashlib.sha1) querystring += '&sig=' + h.hexdigest() proxy_url = current_app.config['PILBOX_URL'] + '?' + querystring if external: proxy_url = urllib.parse.urljoin(get_settings().site_url, proxy_url) return proxy_url
def get_taggable_friends(self): if not self.taggable_friends: r = requests.get( 'https://graph.facebook.com/v2.0/me/taggable_friends', params={ 'access_token': get_settings().facebook_access_token }) self.taggable_friends = r.json() return self.taggable_friends or {}
def posts_by_tag(tag, before_ts=None): posts, older = collect_posts(None, before_ts, int(get_settings().posts_per_page), tag, include_hidden=True) title = '#' + tag if request.args.get('feed') == 'atom': return render_posts_atom(title, 'tag-' + tag + '.atom', posts) return render_posts(title, posts, older)
def twitter_callback(): """Receive the request token from Twitter and convert it to an access token""" try: oauth = OAuth1Session(client_key=get_settings().twitter_api_key, client_secret=get_settings().twitter_api_secret) oauth.parse_authorization_response(request.url) response = oauth.fetch_access_token(ACCESS_TOKEN_URL) access_token = response.get('oauth_token') access_token_secret = response.get('oauth_token_secret') Setting.query.get('twitter_oauth_token').value = access_token Setting.query.get('twitter_oauth_token_secret').value \ = access_token_secret db.session.commit() return redirect(url_for('admin.edit_settings')) except requests.RequestException as e: return make_response(str(e))
def human_time(thedate, alternate=None): if not thedate: return alternate if hasattr(thedate, 'tzinfo') and not thedate.tzinfo: tz = pytz.timezone(get_settings().timezone) thedate = pytz.utc.localize(thedate).astimezone(tz) if (isinstance(thedate, datetime.datetime)): return thedate.strftime('%B %-d, %Y %-I:%M%P %Z') return thedate.strftime('%B %-d, %Y')
def search(before_ts=None): q = request.args.get('q') if not q: abort(404) posts, older = collect_posts(None, before_ts, int(get_settings().posts_per_page), None, include_hidden=True, search=q) return render_posts('Search: ' + q, posts, older)
def date_filter(thedate, first_only=False): if thedate: if hasattr(thedate, 'tzinfo') and not thedate.tzinfo: tz = pytz.timezone(get_settings().timezone) thedate = pytz.utc.localize(thedate).astimezone(tz) formatted = thedate.strftime('%B %-d, %Y') if first_only: previous = getattr(g, 'previous date', None) setattr(g, 'previous date', formatted) if previous == formatted: return None return formatted
def twitter_callback(): """Receive the request token from Twitter and convert it to an access token""" try: oauth = OAuth1Session( client_key=get_settings().twitter_api_key, client_secret=get_settings().twitter_api_secret) oauth.parse_authorization_response(request.url) response = oauth.fetch_access_token(ACCESS_TOKEN_URL) access_token = response.get('oauth_token') access_token_secret = response.get('oauth_token_secret') Setting.query.get('twitter_oauth_token').value = access_token Setting.query.get('twitter_oauth_token_secret').value \ = access_token_secret db.session.commit() return redirect(url_for('admin.edit_settings')) except requests.RequestException as e: return make_response(str(e))
def login_callback(): current_app.logger.debug('callback fields: %s', request.args) state = request.args.get('state') next_url = state or url_for('views.index') auth_url, token_url, micropub_url = session['endpoints'] if not auth_url: flash('Login failed: No authorization URL in session') return redirect(next_url) code = request.args.get('code') client_id = get_settings().site_url redirect_uri = url_for('.login_callback', _external=True) current_app.logger.debug('callback with auth endpoint %s', auth_url) response = requests.post(auth_url, data={ 'code': code, 'client_id': client_id, 'redirect_uri': redirect_uri, 'state': state, }) rdata = urllib.parse.parse_qs(response.text) if response.status_code != 200: current_app.logger.debug('call to auth endpoint failed %s', response) flash('Login failed {}: {}'.format(rdata.get('error'), rdata.get('error_description'))) return redirect(next_url) current_app.logger.debug('verify response %s', response.text) if 'me' not in rdata: current_app.logger.debug('Verify response missing required "me" field') flash('Verify response missing required "me" field {}'.format( response.text)) return redirect(next_url) me = rdata.get('me')[0] scopes = rdata.get('scope') user = auth.load_user(urllib.parse.urlparse(me).netloc) if not user: flash('No user for domain {}'.format(me)) return redirect(next_url) try_micropub_config(token_url, micropub_url, scopes, code, me, redirect_uri, client_id, state) current_app.logger.debug('Logging in user %s', user) flask_login.login_user(user, remember=True) flash('Logged in with domain {}'.format(me)) current_app.logger.debug('Logged in with domain %s', me) return redirect(next_url)
def posts_by_type(plural_type, before_ts=None): post_type, _, title = next(tup for tup in POST_TYPES if tup[1] == plural_type) posts, older = collect_posts((post_type, ), before_ts, int(get_settings().posts_per_page), None, include_hidden=True) if request.args.get('feed') == 'atom': return render_posts_atom(title, plural_type + '.atom', posts) return render_posts(title, posts, older)
def authorize_facebook(): redirect_uri = url_for(".authorize_facebook", _external=True) params = { "client_id": get_settings().facebook_app_id, "redirect_uri": redirect_uri, "scope": "publish_actions,user_photos", } code = request.args.get("code") if code: params["code"] = code params["client_secret"] = get_settings().facebook_app_secret r = urlopen("https://graph.facebook.com/oauth/access_token?" + urlencode(params)) payload = parse_qs(r.read()) access_token = payload[b"access_token"][0].decode("ascii") Setting.query.get("facebook_access_token").value = access_token db.session.commit() return redirect(url_for("admin.edit_settings")) else: return redirect("https://graph.facebook.com/oauth/authorize?" + urlencode(params))
def handle_new_or_edit(post, message, link, name, picture, is_photo, album_id): current_app.logger.debug("publishing to facebook") # TODO I cannot figure out how to tag people via the FB API post_args = { "access_token": get_settings().facebook_access_token, "message": message.strip(), "privacy": json.dumps({"value": "EVERYONE"}), #'privacy': json.dumps({'value': 'SELF'}), } if is_photo and picture: post_args["url"] = picture current_app.logger.debug("Sending photo %s to album %s", post_args, album_id) response = requests.post( "https://graph.facebook.com/v2.0/{}/photos".format(album_id if album_id else "me"), data=post_args ) else: post_args.update(util.trim_nulls({"link": link, "name": name, "picture": picture})) current_app.logger.debug("Sending post %s", post_args) response = requests.post("https://graph.facebook.com/v2.0/me/feed", data=post_args) response.raise_for_status() current_app.logger.debug("Got response from facebook %s", response) if "json" in response.headers["content-type"]: result = response.json() current_app.logger.debug("published to facebook. response {}".format(result)) if result: if is_photo: facebook_photo_id = result["id"] facebook_post_id = result["post_id"] # actually the album split = facebook_post_id.split("_", 1) if split and len(split) == 2: user_id, post_id = split fb_url = "https://facebook.com/{}/posts/{}".format(user_id, facebook_photo_id) post.add_syndication_url(fb_url) return fb_url else: facebook_post_id = result["id"] split = facebook_post_id.split("_", 1) if split and len(split) == 2: user_id, post_id = split fb_url = "https://facebook.com/{}/posts/{}".format(user_id, post_id) post.add_syndication_url(fb_url) return fb_url
def create_album(name, msg): current_app.logger.debug('creating new facebook album %s', name) resp = requests.post( 'https://graph.facebook.com/v2.0/me/albums', data={ 'access_token': get_settings().facebook_access_token, 'name': name, 'message': msg, 'privacy': json.dumps({'value': 'EVERYONE'}), #'privacy': json.dumps({'value': 'SELF'}), }) resp.raise_for_status() current_app.logger.debug( 'new facebook album response: %s, %s', resp, resp.text) return resp.json()['id']
def human_time(thedate, alternate=None): if not thedate: return alternate if hasattr(thedate, 'tzinfo') and not thedate.tzinfo: tz = pytz.timezone(get_settings().timezone) thedate = pytz.utc.localize(thedate).astimezone(tz) # limit full time to things that happen "today" # and datetime.datetime.now(TIMEZONE) - thedate < datetime.timedelta(days=1)): if (isinstance(thedate, datetime.datetime)): return thedate.strftime('%B %-d, %Y %-I:%M%P %Z') return thedate.strftime('%B %-d, %Y')
def create_album(name, msg): current_app.logger.debug("creating new facebook album %s", name) resp = requests.post( "https://graph.facebook.com/v2.0/me/albums", data={ "access_token": get_settings().facebook_access_token, "name": name, "message": msg, "privacy": json.dumps({"value": "EVERYONE"}), #'privacy': json.dumps({'value': 'SELF'}), }, ) resp.raise_for_status() current_app.logger.debug("new facebook album response: %s, %s", resp, resp.text) return resp.json()["id"]
def authorize_facebook(): redirect_uri = url_for('.authorize_facebook', _external=True) params = { 'client_id': get_settings().facebook_app_id, 'redirect_uri': redirect_uri, 'scope': 'publish_actions,user_photos', } code = request.args.get('code') if code: params['code'] = code params['client_secret'] = get_settings().facebook_app_secret r = urlopen('https://graph.facebook.com/oauth/access_token?' + urlencode(params)) payload = parse_qs(r.read()) access_token = payload[b'access_token'][0].decode('ascii') Setting.query.get('facebook_access_token').value = access_token db.session.commit() return redirect(url_for('admin.edit_settings')) else: return redirect('https://graph.facebook.com/oauth/authorize?' + urlencode(params))
def index(before_ts=None): post_types = [type[0] for type in POST_TYPES if type[0] != 'event'] posts, older = collect_posts( post_types, before_ts, int(get_settings().posts_per_page), None, include_hidden=False) if request.args.get('feed') == 'atom': return render_posts_atom('Stream', 'index.atom', posts) resp = make_response( render_posts('Stream', posts, older, events=collect_upcoming_events(), template='home.jinja2')) if 'PUSH_HUB' in current_app.config: resp.headers.add('Link', '<{}>; rel="hub"'.format( current_app.config['PUSH_HUB'])) resp.headers.add('Link', '<{}>; rel="self"'.format( url_for('.index', _external=True))) return resp
def try_post_like(url, post): current_app.logger.debug('wordpress. posting like to %s', url) myid = find_my_id() siteid, postid = find_post_id(url) current_app.logger.debug( 'wordpress. posting like to site-id %d, post-id %d', siteid, postid) if myid and siteid and postid: endpoint = API_NEW_LIKE_URL.format(siteid, postid) current_app.logger.debug('wordpress: POST to endpoint %s', endpoint) r = requests.post(endpoint, headers={ 'authorization': 'Bearer ' + get_settings().wordpress_access_token, }) r.raise_for_status() if r.json().get('success'): wp_url = '{}#liked-by-{}'.format(url, myid) post.add_syndication_url(wp_url) db.session.commit() return wp_url current_app.logger.error( 'failed to post wordpress like. response: %r: %r', r, r.text)
def login(): me = request.args.get('me') if not me: return render_template('admin/login.jinja2', next=request.args.get('next')) # if current_app.config.get('BYPASS_INDIEAUTH'): # user = auth.load_user(urllib.parse.urlparse(me).netloc) # current_app.logger.debug('Logging in user %s', user) # flask_login.login_user(user, remember=True) # flash('logged in as {}'.format(me)) # current_app.logger.debug('Logged in with domain %s', me) # return redirect(request.args.get('next') or url_for('views.index')) if not me: return make_response('Missing "me" parameter', 400) if not me.startswith('http://') and not me.startswith('https://'): me = 'http://' + me auth_url, token_url, micropub_url = discover_endpoints(me) if not auth_url: auth_url = 'https://indieauth.com/auth' current_app.logger.debug('Found endpoints %s, %s, %s', auth_url, token_url, micropub_url) state = request.args.get('next') session['endpoints'] = (auth_url, token_url, micropub_url) auth_params = { 'me': me, 'client_id': get_settings().site_url, 'redirect_uri': url_for('.login_callback', _external=True), 'state': state, } # if they support micropub try to get read indie-config permission if token_url and micropub_url: auth_params['scope'] = 'config' return redirect('{}?{}'.format( auth_url, urllib.parse.urlencode(auth_params)))
def login(): me = request.args.get('me') if not me: return render_template('admin/login.jinja2', next=request.args.get('next')) if current_app.config.get('BYPASS_INDIEAUTH'): user = auth.load_user(urllib.parse.urlparse(me).netloc) current_app.logger.debug('Logging in user %s', user) flask_login.login_user(user, remember=True) flash('logged in as {}'.format(me)) current_app.logger.debug('Logged in with domain %s', me) return redirect(request.args.get('next') or url_for('views.index')) if not me: return make_response('Missing "me" parameter', 400) if not me.startswith('http://') and not me.startswith('https://'): me = 'http://' + me auth_url, token_url, micropub_url = discover_endpoints(me) if not auth_url: auth_url = 'https://indieauth.com/auth' current_app.logger.debug('Found endpoints %s, %s, %s', auth_url, token_url, micropub_url) state = request.args.get('next') session['endpoints'] = (auth_url, token_url, micropub_url) auth_params = { 'me': me, 'client_id': get_settings().site_url, 'redirect_uri': url_for('.login_callback', _external=True), 'state': state, } # if they support micropub try to get read indie-config permission if token_url and micropub_url: auth_params['scope'] = 'config' return redirect('{}?{}'.format( auth_url, urllib.parse.urlencode(auth_params)))
def collect_images(post): """collect the images (if any) that are in an <img> tag in the rendered post""" if type(post) == Post and post.attachments: for photo in post.attachments: yield photo.url else: if type(post) == Post: html = util.markdown_filter(post.content, img_path=post.get_image_path()) else: html = post.content if html: soup = BeautifulSoup(html) for img in soup.find_all('img'): if not img.find_parent(class_='h-card'): src = img.get('src') if src: yield urljoin(get_settings().site_url, src)
def try_post_reply(url, post): current_app.logger.debug('wordpress. posting reply to %s', url) myid = find_my_id() siteid, postid = find_post_id(url) current_app.logger.debug( 'wordpress. posting reply to site-id %d, post-id %d', siteid, postid) if myid and siteid and postid: endpoint = API_NEW_REPLY_URL.format(siteid, postid) current_app.logger.debug('wordpress: POST to endpoint %s', endpoint) r = requests.post(endpoint, headers={ 'authorization': 'Bearer ' + get_settings().wordpress_access_token, }, data={ 'content': post.content_html, }) r.raise_for_status() wp_url = r.json().get('URL') if wp_url: post.add_syndication_url(wp_url) db.session.commit() return wp_url current_app.logger.error( 'failed to post wordpress reply. response: %r: %r', r, r.text)
def get_auth(): return OAuth1( client_key=get_settings().twitter_api_key, client_secret=get_settings().twitter_api_secret, resource_owner_key=get_settings().twitter_oauth_token, resource_owner_secret=get_settings().twitter_oauth_token_secret)
def is_twitter_authorized(): return (get_settings().twitter_oauth_token and get_settings().twitter_oauth_token_secret)
def handle_new_or_edit(post, message, link, name, picture, is_photo, album_id): current_app.logger.debug('publishing to facebook') # TODO I cannot figure out how to tag people via the FB API post_args = { 'access_token': get_settings().facebook_access_token, 'message': message.strip(), 'privacy': json.dumps({'value': 'EVERYONE'}), #'privacy': json.dumps({'value': 'SELF'}), } if is_photo and picture: post_args['url'] = picture current_app.logger.debug( 'Sending photo %s to album %s', post_args, album_id) response = requests.post( 'https://graph.facebook.com/v2.0/{}/photos'.format( album_id if album_id else 'me'), data=post_args) else: post_args.update(util.trim_nulls({ 'link': link, 'name': name, 'picture': picture, })) current_app.logger.debug('Sending post %s', post_args) response = requests.post('https://graph.facebook.com/v2.0/me/feed', data=post_args) response.raise_for_status() current_app.logger.debug("Got response from facebook %s", response) if 'json' in response.headers['content-type']: result = response.json() current_app.logger.debug( 'published to facebook. response {}'.format(result)) if result: if is_photo: facebook_photo_id = result['id'] facebook_post_id = result['post_id'] # actually the album split = facebook_post_id.split('_', 1) if split and len(split) == 2: user_id, post_id = split fb_url = 'https://facebook.com/{}/posts/{}'.format( user_id, facebook_photo_id) post.add_syndication_url(fb_url) return fb_url else: facebook_post_id = result['id'] split = facebook_post_id.split('_', 1) if split and len(split) == 2: user_id, post_id = split fb_url = 'https://facebook.com/{}/posts/{}'.format( user_id, post_id) post.add_syndication_url(fb_url) return fb_url
def inject_settings_variable(): return { 'settings': get_settings() }
def is_facebook_authorized(): return get_settings().facebook_access_token