Exemple #1
0
def route(source_cls):
    """Registers browser extension URL routes for a given source class.

  ...specifically, with the source's short name as the routes' URL prefix.
  """
    for route, cls in (
        (f'/{source_cls.SHORT_NAME}/browser/status', Status),
        (f'/{source_cls.SHORT_NAME}/browser/homepage', Homepage),
        (f'/{source_cls.SHORT_NAME}/browser/profile', Profile),
        (f'/{source_cls.SHORT_NAME}/browser/feed', Feed),
        (f'/{source_cls.SHORT_NAME}/browser/post', Post),
        (f'/{source_cls.SHORT_NAME}/browser/likes', Reactions),
        (f'/{source_cls.SHORT_NAME}/browser/comments', Comments),
        (f'/{source_cls.SHORT_NAME}/browser/reactions', Reactions),
        (f'/{source_cls.SHORT_NAME}/browser/poll', Poll),
        (f'/{source_cls.SHORT_NAME}/browser/token-domains', TokenDomains),
    ):
        app.add_url_rule(
            route,
            view_func=cls.as_view(route),
            methods=['GET', 'POST'] if cls == Status else ['POST'])
Exemple #2
0
        return render_template('choose_blog.html', **vars)


@app.route('/tumblr/add', methods=['POST'])
def tumblr_add():
    util.maybe_add_or_delete_source(
        Tumblr,
        ndb.Key(urlsafe=request.form['auth_entity_key']).get(),
        request.form['state'],
        blog_name=request.form['blog'],
    )


class SuperfeedrNotify(superfeedr.Notify):
    SOURCE_CLS = Tumblr


# Tumblr doesn't seem to use scope
# http://www.tumblr.com/docs/en/api/v2#oauth
start = util.oauth_starter(oauth_tumblr.Start).as_view('tumblr_start',
                                                       '/tumblr/choose_blog')
app.add_url_rule('/tumblr/start', view_func=start, methods=['POST'])
app.add_url_rule('/tumblr/choose_blog',
                 view_func=ChooseBlog.as_view('tumblr_choose_blog', 'unused'))
app.add_url_rule('/tumblr/delete/finish',
                 view_func=oauth_tumblr.Callback.as_view(
                     'tumblr_delete_finish', '/delete/finish'))
app.add_url_rule('/tumblr/notify/<id>',
                 view_func=SuperfeedrNotify.as_view('tumblr_notify'),
                 methods=['POST'])
Exemple #3
0
    """Custom handler to add Flickr source when auth completes.

  If this account was previously authorized with greater permissions, this will
  trigger another round of auth with elevated permissions.
  """
    def finish(self, auth_entity, state=None):
        logger.debug(f'finish with {auth_entity}, {state}')
        source = util.maybe_add_or_delete_source(Flickr, auth_entity, state)
        feature = util.decode_oauth_state(state).get('feature')
        if source and feature == 'listen' and 'publish' in source.features:
            # we had signed up previously with publish, so we'll reauth to
            # avoid losing that permission
            logger.info('Restarting OAuth flow to get publish permissions.')
            source.features.remove('publish')
            source.put()
            return self.start_oauth_flow('publish')


app.add_url_rule('/flickr/start',
                 view_func=Start.as_view('flickr_start', '/flickr/add'),
                 methods=['POST'])
app.add_url_rule('/flickr/add',
                 view_func=AddFlickr.as_view('flickr_add', 'unused'))
app.add_url_rule('/flickr/delete/finish',
                 view_func=oauth_flickr.Callback.as_view(
                     'flickr_delete_finish', '/delete/finish'))
app.add_url_rule('/flickr/publish/start',
                 view_func=oauth_flickr.Start.as_view(
                     'flickr_publish_start', '/publish/flickr/finish'),
                 methods=['POST'])
Exemple #4
0
          self.entity.type = 'rsvp'
          if not text:
            content['value'] = f'RSVPed {rsvp}.'
        else:
          self.entity.type = {'in-reply-to': 'comment',
                              'like-of': 'like',
                              'repost-of': 'repost',
                              }.get(type, type)
          if not text:
            content['value'] = {'comment': 'replied to this.',
                                'like': 'liked this.',
                                'repost': 'reposted this.',
                                }[self.entity.type]
        return item

      # check children in case this is eg an h-feed
      found = self.find_mention_item(item.get('children', []))
      if found:
        return found

    return None

  def any_target_in(self, haystack):
    """Returns true if any target URL (including redirects) is in haystack."""
    return any(url in haystack
               for url in self.entity.redirected_target_urls + [self.target_url])


app.add_url_rule('/webmention/<any(blogger,fake,tumblr,wordpress):site>',
                 view_func=BlogWebmentionView.as_view('blog_wm'), methods=['POST'])
Exemple #5
0
            self.merge_urls(repost, 'object', originals)
        return repost


class Rsvp(Item):
    def get_item(self, event_id, user_id):
        event = self.source.gr_source.get_event(event_id)
        rsvp = self.source.gr_source.get_rsvp(self.source.key_id(),
                                              event_id,
                                              user_id,
                                              event=event)
        if event:
            originals, mentions = original_post_discovery.discover(
                self.source, event, fetch_hfeed=False)
            self.merge_urls(rsvp, 'inReplyTo', originals)
        return rsvp


app.add_url_rule('/post/<site>/<key_id>/<post_id>',
                 view_func=Post.as_view('post'))
app.add_url_rule('/comment/<site>/<key_id>/<post_id>/<comment_id>',
                 view_func=Comment.as_view('comment'))
app.add_url_rule('/like/<site>/<key_id>/<post_id>/<user_id>',
                 view_func=Like.as_view('like'))
app.add_url_rule('/react/<site>/<key_id>/<post_id>/<user_id>/<reaction_id>',
                 view_func=Reaction.as_view('react'))
app.add_url_rule('/repost/<site>/<key_id>/<post_id>/<share_id>',
                 view_func=Repost.as_view('repost'))
app.add_url_rule('/rsvp/<site>/<key_id>/<event_id>/<user_id>',
                 view_func=Rsvp.as_view('rsvp'))
Exemple #6
0
class Start(View):
    def dispatch_request(self):
        features = request.form['feature']
        scopes = PUBLISH_SCOPES if 'publish' in features else LISTEN_SCOPES
        starter = util.oauth_starter(oauth_github.Start,
                                     feature=features)('/github/add',
                                                       scopes=scopes)
        return starter.dispatch_request()


class AddGitHub(oauth_github.Callback):
    def finish(self, auth_entity, state=None):
        logger.debug(f'finish with {auth_entity}, {state}')
        util.maybe_add_or_delete_source(GitHub, auth_entity, state)


app.add_url_rule('/github/start',
                 view_func=Start.as_view('github_start'),
                 methods=['POST'])
app.add_url_rule('/github/add',
                 view_func=AddGitHub.as_view('github_add', 'unused'))
app.add_url_rule('/github/delete/finish',
                 view_func=oauth_github.Callback.as_view(
                     'github_delete_finish', '/delete/finish'))
app.add_url_rule('/github/publish/start',
                 view_func=oauth_github.Start.as_view('github_publish_start',
                                                      '/publish/github/finish',
                                                      scopes=PUBLISH_SCOPES),
                 methods=['POST'])
Exemple #7
0
class Callback(indieauth.Callback):
    """IndieAuth callback handler."""
    def finish(self, auth_entity, state=None):
        if not auth_entity:
            return

        assert state

        @ndb.transactional()
        def add_or_update_domain():
            domain = Domain.get_or_insert(
                util.domain_from_link(
                    util.replace_test_domains_with_localhost(
                        auth_entity.key.id())))
            domain.auth = auth_entity.key
            if state not in domain.tokens:
                domain.tokens.append(state)
            domain.put()
            flash(f'Authorized you for {domain.key.id()}.')

        add_or_update_domain()
        return redirect('/')


app.add_url_rule('/indieauth/start',
                 view_func=Start.as_view('indieauth_start',
                                         '/indieauth/callback'),
                 methods=['POST'])
app.add_url_rule('/indieauth/callback',
                 view_func=Callback.as_view('indieauth_callback', 'unused'))
Exemple #8
0
                               current_image_size=current_image_size,
                               current_version=current_version)

    def post(self):
        """
        Receive the image file and save it in temporary folder
        :return: web-page for successful image sending
        """
        if 'image' not in request.files:
            return "No file sent!"

        file = request.files['image']

        self.image_file = secure_filename(file.filename)

        os.makedirs(self.image_path, exist_ok=True)
        file.save(os.path.join(self.image_path, self.image_file))

        self.notify()

        return "Update image sent!"

    def get(self):
        return self.poll()


# NOTE: Tried to use a blueprint here, doesn't work for some reason
app.add_url_rule("/update/", view_func=WebInput.as_view("web_input"))
app.add_url_rule("/update/send_image/",
                 view_func=WebInput.as_view("send_image"))
Exemple #9
0
        if self.entity.html:
            for url in expected:
                if url in self.entity.html or urllib.parse.quote(
                        url, safe='') in self.entity.html:
                    return True

        self.error(f"Couldn't find link to {expected[0]}")
        return False

    def error(self, error, **kwargs):
        logging.info(f'publish: {error}')
        return super().error(error, **kwargs)


app.add_url_rule('/publish/preview',
                 view_func=Preview.as_view('publish_preview'),
                 methods=['POST'])
app.add_url_rule('/publish/webmention',
                 view_func=Webmention.as_view('publish_webmention'),
                 methods=['POST'])
app.add_url_rule('/publish/flickr/finish',
                 view_func=FlickrSend.as_view('publish_flickr_finish',
                                              'unused'))
app.add_url_rule('/publish/github/finish',
                 view_func=GitHubSend.as_view('publish_github_finish',
                                              'unused'))
app.add_url_rule('/publish/mastodon/finish',
                 view_func=MastodonSend.as_view('publish_mastodon_finish',
                                                'unused'))
app.add_url_rule('/publish/twitter/finish',
                 view_func=TwitterSend.as_view('publish_twitter_finish',
Exemple #10
0
      raise models.DisableSource()

  def search_for_links(self):
    """Searches for activities with links to any of this source's web sites.

    Returns:
      sequence of ActivityStreams activity dicts
    """
    urls = {util.schemeless(util.fragmentless(url), slashes=False)
            for url in self.domain_urls
            if not util.in_webmention_blocklist(util.domain_from_link(url))}
    if not urls:
      return []

    # Search syntax: https://www.reddit.com/wiki/search
    url_query = ' OR '.join(f'site:"{u}" OR selftext:"{u}"' for u in urls)
    return self.get_activities(
      search_query=url_query, group_id=gr_source.SEARCH, etag=self.last_activities_etag,
      fetch_replies=False, fetch_likes=False, fetch_shares=False, count=50)


class Callback(oauth_reddit.Callback):
  def finish(self, auth_entity, state=None):
    util.maybe_add_or_delete_source(Reddit, auth_entity, state)


app.add_url_rule('/reddit/start',
                 view_func=util.oauth_starter(oauth_reddit.Start).as_view('reddit_start', '/reddit/callback'), methods=['POST'])
app.add_url_rule('/reddit/callback',
                 view_func=Callback.as_view('reddit_callback', 'unused to_path'))
Exemple #11
0
            redirect(request.path)


class Callback(oauth_dropins.mastodon.Callback):
    def finish(self, auth_entity, state=None):
        source = util.maybe_add_or_delete_source(Mastodon, auth_entity, state)

        features = util.decode_oauth_state(state).get('feature', '').split(',')
        if set(features) != set(source.features):
            # override features with whatever we requested scopes for just now, since
            # scopes are per access token. background:
            # https://github.com/snarfed/bridgy/issues/1015
            source.features = features
            source.put()


app.add_url_rule('/mastodon/start',
                 view_func=Start.as_view('mastodon_start',
                                         '/mastodon/callback'),
                 methods=['POST'])
app.add_url_rule('/mastodon/callback',
                 view_func=Callback.as_view('mastodon_callback', 'unused'))
app.add_url_rule('/mastodon/delete/finish',
                 view_func=oauth_dropins.mastodon.Callback.as_view(
                     'mastodon_delete_finish', '/delete/finish'))
app.add_url_rule('/mastodon/publish/start',
                 view_func=StartBase.as_view('mastodon_publish_finish',
                                             '/publish/mastodon/finish',
                                             scopes=PUBLISH_SCOPES),
                 methods=['POST'])
Exemple #12
0
                'title': p.get('name', ''),
                'url': p.get('url', ''),
                'pretty_url': util.pretty_link(str(p.get('url', ''))),
                'image': p.get('imageUrl', ''),
            } for p in pubs if p.get('id')],
        }
        logger.info(f'Rendering choose_blog.html with {vars}')
        return render_template('choose_blog.html', **vars)


class SuperfeedrNotify(superfeedr.Notify):
    SOURCE_CLS = Medium


# https://github.com/Medium/medium-api-docs#user-content-21-browser-based-authentication
start = util.oauth_starter(oauth_medium.Start).as_view(
    'medium_start',
    '/medium/choose_blog',
    scopes=('basicProfile', 'listPublications'))
app.add_url_rule('/medium/start', view_func=start, methods=['POST'])
app.add_url_rule('/medium/choose_blog',
                 view_func=ChooseBlog.as_view('medium_choose_blog',
                                              'unused to_path'),
                 methods=['GET'])
app.add_url_rule('/medium/delete/finish',
                 view_func=oauth_medium.Callback.as_view(
                     'medium_delete', '/delete/finish')),
app.add_url_rule('/medium/notify/<id>',
                 view_func=SuperfeedrNotify.as_view('medium_notify'),
                 methods=['POST'])
Exemple #13
0
# -*- coding: utf-8 -*-
from flask_app import app
from controllers import * 

app.error_handlers[500] = error_controller.exception 
app.error_handlers[404] = error_controller.not_found 
app.add_url_rule('/sitemap.xml', view_func = robot_controller.sitemap)
app.add_url_rule('/robots.txt', view_func = robot_controller.robots)

# Board
app.add_url_rule('/', 'board.view', view_func = board_controller.view)
app.add_url_rule('/om', 'board.about', view_func = board_controller.about)
app.add_url_rule('/admin', 'board.control_panel', view_func = board_controller.control_panel)

# Job
app.add_url_rule('/stilling/<int:id>/', 'job.view', view_func = job_controller.view)
app.add_url_rule('/stilling/<int:id>/<string:token>', 'job.preview', view_func = job_controller.preview)
app.add_url_rule('/admin/stilling/', 'job.new', view_func = job_controller.new)
app.add_url_rule('/admin/stilling/<int:id>/', 'job.edit', view_func = job_controller.edit)
app.add_url_rule('/admin/stilling/', 'job.create', view_func = job_controller.create, methods = ['POST'])
app.add_url_rule('/admin/stilling/<int:id>/', 'job.update', view_func = job_controller.update, methods = ['POST'])

# Scraped job
app.add_url_rule('/admin/skrapt/<string:guid>/', 'scraped_job.edit', view_func = scraped_job_controller.edit)
app.add_url_rule('/admin/skrapt/<string:guid>/delete', 'scraped_job.delete', view_func = scraped_job_controller.delete, methods = ['GET'])

# Company
app.add_url_rule('/admin/selskap/', 'comapany.new', view_func = company_controller.new)
app.add_url_rule('/admin/selskap/list', 'company.list', view_func = company_controller.list)
app.add_url_rule('/admin/selskap/<int:id>/', 'company.edit', view_func = company_controller.edit)
app.add_url_rule('/admin/selskap/', 'company.create', view_func = company_controller.create, methods = ['POST'])
Exemple #14
0

@app.route('/blogger/add', methods=['POST'])
def blogger_add():
    util.maybe_add_or_delete_source(
        Blogger,
        ndb.Key(urlsafe=request.form['auth_entity_key']).get(),
        request.form['state'],
        blog_id=request.form['blog'],
    )


class SuperfeedrNotify(superfeedr.Notify):
    SOURCE_CLS = Blogger


# Blogger only has one OAuth scope. oauth-dropins fills it in.
# https://developers.google.com/blogger/docs/2.0/developers_guide_protocol#OAuth2Authorizing
start = util.oauth_starter(oauth_blogger.Start).as_view(
    'blogger_start', '/blogger/oauth2callback')
app.add_url_rule('/blogger/start', view_func=start, methods=['POST'])
app.add_url_rule('/blogger/oauth2callback',
                 view_func=oauth_blogger.Callback.as_view(
                     'blogger_oauth2callback', '/blogger/oauth_handler'))
app.add_url_rule('/blogger/delete/start',
                 view_func=oauth_blogger.Start.as_view(
                     'blogger_delete_start', '/blogger/oauth2callback'))
app.add_url_rule('/blogger/notify/<id>',
                 view_func=SuperfeedrNotify.as_view('blogger_notify'),
                 methods=['POST'])
Exemple #15
0
      if site_info is None:
        return
      elif site_info.get('jetpack'):
        logger.info(f'This is a self-hosted WordPress blog! {auth_entity.key_id()} {auth_entity.blog_id}')
        return render_template('confirm_self_hosted_wordpress.html',
                               auth_entity_key=auth_entity.key.urlsafe().decode(),
                               state=state)

    util.maybe_add_or_delete_source(WordPress, auth_entity, state)


@app.route('/wordpress/confirm', methods=['POST'])
def confirm_self_hosted():
  util.maybe_add_or_delete_source(
    WordPress,
    ndb.Key(urlsafe=request.form['auth_entity_key']).get(),
    request.form['state'])


class SuperfeedrNotify(superfeedr.Notify):
  SOURCE_CLS = WordPress


# wordpress.com doesn't seem to use scope
# https://developer.wordpress.com/docs/oauth2/
start = util.oauth_starter(oauth_wordpress.Start).as_view(
  'wordpress_start', '/wordpress/add')
app.add_url_rule('/wordpress/start', view_func=start, methods=['POST'])
app.add_url_rule('/wordpress/add', view_func=Add.as_view('wordpress_add', 'unused'))
app.add_url_rule('/wordpress/notify/<id>', view_func=SuperfeedrNotify.as_view('wordpress_notify'), methods=['POST'])