Пример #1
0
    def render(self, content, list_mode=False):
        self.handler.display["individual_content"] = type(content) is not list
        self.handler.display["referrer"] = content_remote.sanitize(
            self.handler.get_argument('referrer', ""))

        self.handler.display['favorites'] = []
        self.handler.display['list_mode'] = list_mode

        if not self.handler.display["individual_content"]:
            self.handler.display["feed"] = content
            for item in content:
                if item.is_remote:
                    continue
                item.view = re.sub(r'(<[^<]*class="hw-read-more".*)', \
                                      r'<a class="hw-read-more" href="' \
                                      + self.handler.content_url(item) + r'">' \
                                      + self.locale.translate('read more...') \
                                  + r'</a>', \
                                  item.view)
        else:
            self.handler.display["content"] = content

            if content.favorites:
                self.handler.display['favorites'] = \
                    self.handler.models.content_remote.get(
                      to_username=content.username,
                      local_content_name=content.name,
                      type='favorite')[:]

        return self.render_string("content.html", **self.handler.display)
Пример #2
0
  def render(self, content, list_mode=False):
    self.handler.display["individual_content"] = type(content) is not list
    self.handler.display["referrer"] = content_remote.sanitize(
        self.handler.get_argument('referrer', ""))

    self.handler.display['favorites'] = []
    self.handler.display['list_mode'] = list_mode

    if not self.handler.display["individual_content"]:
      self.handler.display["feed"] = content
      for item in content:
        if item.is_remote:
          continue
        item.view = re.sub(r'(<[^<]*class="hw-read-more".*)', \
                              r'<a class="hw-read-more" href="' \
                              + self.handler.content_url(item) + r'">' \
                              + self.locale.translate('read more...') \
                          + r'</a>', \
                          item.view)
    else:
      self.handler.display["content"] = content

      if content.favorites:
        self.handler.display['favorites'] = \
            self.handler.models.content_remote.get(
              to_username=content.username,
              local_content_name=content.name,
              type='favorite')[:]

    return self.render_string("content.html", **self.handler.display)
Пример #3
0
  def comment(self):
    commented_content = self.models.content.get(
        username=self.get_argument('local_user'),
        name=self.get_argument('local_name'))[0]
    self.display["user"] = commented_user = self.models.users.get(
        username=commented_content.username)[0]
    comment = self.get_argument('comment')
    sanitized_comment = content_remote.sanitize(comment)

    is_spam = spam.guess(comment, self.application.settings["private_path"],
        commented_content.username)

    post_remote = self.models.content_remote()
    post_remote.to_username = commented_content.username
    post_remote.from_user = self.current_user["email"]
    post_remote.username = self.current_user["email"].split('@')[0]
    local_url = ('/' + commented_content.username +
        '/remote-comments/comment-' + str(uuid.uuid4()))
    post_remote.post_id = ('tag:' + self.request.host + ',' +
        self.display["tag_date"] + ':' + local_url)
    post_remote.link = 'http://' + self.request.host + local_url
    from_username = post_remote.username
    if self.current_user["user"]:
      profile = self.get_author_user()
      post_remote.avatar = profile.logo if profile.logo else profile.favicon
    else:
      post_remote.avatar = ('http://www.gravatar.com/avatar/' +
          hashlib.md5(self.current_user["email"].lower()).hexdigest())
    post_remote.date_created = datetime.datetime.utcnow()
    if is_spam:
      post_remote.is_spam = True
    else:
      spam.train_ham(comment, self.application.settings["private_path"],
          commented_content.username)
    post_remote.type = 'comment'
    post_remote.local_content_name = commented_content.name
    post_remote.view = sanitized_comment
    post_remote.save()

    commented_content.comments_count += 1
    commented_content.comments_updated = datetime.datetime.utcnow()
    commented_content.save()

    cache.remove(self, self.content_url(commented_content))
    socialize.socialize(self, commented_content)
    smtp.comment(self, from_username, post_remote.from_user,
        commented_user.email, self.content_url(commented_content, host=True),
        sanitized_comment)
Пример #4
0
    def render(self, content, simple=True, template_type=None, sanitize=False):
        content.restricted = False
        content.is_remote = False

        content.comments_list = []
        if content.comments_count:
            content.comments_list = content_remote.get_comments(
                self.handler, content)
            is_forum = self.handler.display["section_template"] == 'forum'
            content.comments_list.sort(key=lambda x: x.date_created,
                                       reverse=(not is_forum))

        try:
            if not self.handler.authenticate(content=content,
                                             auto_login=(not simple)):
                if simple:
                    content.restricted = True
                    content.view = (
                        '"You need to <a href="' +
                        self.handler.nav_url(host=True, section="login") +
                        '">login</a> to view this content.')
                    return content
                else:
                    raise tornado.web.HTTPError(401)
        except tornado.web.HTTPError as ex:
            if simple:
                content.restricted = True
                content.view = \
                    '<span style="color:red">Sorry, you don\'t have access to view this content.</span>'
                return content
            else:
                # re-raise
                raise ex

        if sanitize:
            content.view = content_remote.sanitize(content.view)

        return content
Пример #5
0
  def render(self, content, simple=True, template_type=None, sanitize=False):
    content.restricted = False
    content.is_remote = False

    content.comments_list = []
    if content.comments_count:
      content.comments_list = content_remote.get_comments(
          self.handler, content)
      is_forum = self.handler.display["section_template"] == 'forum'
      content.comments_list.sort(key=lambda x: x.date_created, reverse=(
          not is_forum))

    try:
      if not self.handler.authenticate(content=content,
          auto_login=(not simple)):
        if simple:
          content.restricted = True
          content.view = ('"You need to <a href="' +
              self.handler.nav_url(host=True, section="login") +
              '">login</a> to view this content.')
          return content
        else:
          raise tornado.web.HTTPError(401)
    except tornado.web.HTTPError as ex:
      if simple:
        content.restricted = True
        content.view = \
            '<span style="color:red">Sorry, you don\'t have access to view this content.</span>'
        return content
      else:
        # re-raise
        raise ex

    if sanitize:
      content.view = content_remote.sanitize(content.view)

    return content
Пример #6
0
  def timeline_result(self, response):
    # Check if our OAuth key has expired
    if (response.has_key('error') and response['error']['type']
        == 'OAuthException'):
      self.delete()
      return

    posts = response['data']
    for post in posts:
      exists = self.models.content_remote.get(to_username=self.user.username,
          type='facebook', post_id=post['id'])[0]

      date_updated = None
      if post.has_key('updated_time'):
        date_updated = datetime.datetime.strptime(post['updated_time'][:-5],
            '%Y-%m-%dT%H:%M:%S')

      if exists:
        if date_updated and date_updated != exists.date_updated \
            or post['comments']['count'] != exists.comments_count:
          new_post = exists
        else:
          continue
      else:
        new_post = self.models.content_remote()

      new_post.to_username = self.user.username
      new_post.username = post['from']['name']
      if post.has_key('actions'):
        new_post.from_user = post['actions'][0]['link']
      #new_post.avatar = tweet['user']['profile_image_url']

      parsed_date = datetime.datetime.strptime(post['created_time'][:-5],
          '%Y-%m-%dT%H:%M:%S')

      # we don't keep items that are over 30 days old
      if parsed_date < datetime.datetime.utcnow() - datetime.timedelta(
          days=self.constants['feed_max_days_old']):
        continue

      new_post.date_created = parsed_date
      new_post.date_updated = date_updated
      new_post.comments_count = 0
      new_post.comments_updated = None
      new_post.type = 'facebook'
      new_post.title = ''
      new_post.post_id = post['id']
      new_post.comments_count = post['comments']['count']
      if post['comments']['count'] and post['comments']['data']:
        last_updated = post['comments']['data'][len(
            post['comments']['data']) - 1]['created_time']
        new_post.comments_updated = datetime.datetime.strptime(
            last_updated[:-5], '%Y-%m-%dT%H:%M:%S')
      if post.has_key('actions'):
        new_post.link = post['actions'][0]['link']
      elif post.has_key('link'):
        new_post.link = post['link']
      view = ""
      if post.has_key('message'):
        view += post['message'] + "<br>"
      if post.has_key('caption'):
        view += post['caption'] + "<br>"
      if post.has_key('description'):
        view += post['description'] + "<br>"
      if post.has_key('story'):
        view += post['story'] + "<br>"
      view = tornado.escape.linkify(view)
      if post.has_key('picture'):
        view = '<img src="' + post['picture'] + '">' + view
      new_post.view = content_remote.sanitize(tornado.escape.xhtml_unescape(
          view))
      new_post.save()

      # comments
      if post['comments']['count']:
        for comment in post['comments']['data']:
          exists = self.models.content_remote.get(
              to_username=self.user.username, post_id=comment['id'])[0]
          if exists:
            continue
          else:
            new_comment = self.models.content_remote()

          new_comment.to_username = self.user.username
          new_comment.username = comment['from']['name']
          new_comment.from_user = ('http://facebook.com/' +
              comment['from']['id'])
          date_created = datetime.datetime.strptime(
              comment['created_time'][:-5], '%Y-%m-%dT%H:%M:%S')
          new_comment.date_created = date_created
          new_comment.type = 'remote-comment'
          new_comment.thread = post['id']
          new_comment.post_id = comment['id']
          if post.has_key('actions'):
            new_comment.link = post['actions'][0]['link']
          new_comment.view = comment['message']
          new_comment.save()

    count = self.models.content_remote.get(to_username=self.user.username,
        type='facebook', deleted=False).count()
    self.write(json.dumps({ 'count': count }))
Пример #7
0
    def timeline_result(self, response):
        posts = response['response']['posts']
        for post in posts:
            exists = self.models.content_remote.get(
                to_username=self.user.username,
                type='tumblr',
                post_id=str(post['id']))[0]

            if exists:
                continue
            else:
                new_post = self.models.content_remote()

            new_post.to_username = self.user.username
            new_post.username = post['blog_name']
            new_post.from_user = '******' + post['blog_name']
            #new_post.avatar = post['user']['profile_image_url']

            parsed_date = datetime.datetime.utcfromtimestamp(post['timestamp'])

            # we don't keep items that are over 30 days old
            if parsed_date < datetime.datetime.utcnow() - datetime.timedelta(
                    days=self.constants['feed_max_days_old']):
                continue

            new_post.date_created = parsed_date
            new_post.date_updated = None
            new_post.comments_count = post['note_count']
            new_post.comments_updated = None
            new_post.type = 'tumblr'
            new_post.post_id = str(post['id'])
            new_post.link = post['post_url']
            if post['type'] == 'text':
                new_post.title = post['title']
                new_post.view = content_remote.sanitize(
                    tornado.escape.xhtml_unescape(post['body']))
            elif post['type'] == 'photo':
                html = ""
                for photo in post['photos']:
                    chosen_photo = None
                    for size in photo['alt_sizes']:
                        if (not chosen_photo or
                            (size['width'] <= 720
                             and chosen_photo['width'] < size['width'])):
                            chosen_photo = size
                    html += '<img src="' + content_remote.sanitize(
                        tornado.escape.xhtml_unescape(
                            chosen_photo['url'])) + '">'
                html += content_remote.sanitize(
                    tornado.escape.xhtml_unescape(post['caption']))
                new_post.view = html
            elif post['type'] == 'quote':
                new_post.view = content_remote.sanitize(
                    tornado.escape.xhtml_unescape(post['text'] + '<br>' +
                                                  post['source']))
            elif post['type'] == 'link':
                new_post.title = post['title']
                new_post.view = content_remote.sanitize(
                    tornado.escape.xhtml_unescape('<a href="' + post['url'] +
                                                  '">' + post['url'] +
                                                  '</a><br>' +
                                                  post['description']))
            elif post['type'] == 'chat':
                new_post.title = post['title']
                new_post.view = content_remote.sanitize(
                    tornado.escape.xhtml_unescape(post['body'].replace(
                        '\r\n', '<br>')))
            elif post['type'] == 'audio':
                html = ""
                html += content_remote.sanitize(
                    tornado.escape.xhtml_unescape(post['player']))
                html += content_remote.sanitize(
                    tornado.escape.xhtml_unescape(post['caption']))
                new_post.view = html
            elif post['type'] == 'video':
                chosen_video = None
                for video in post['player']:
                    if (not chosen_video
                            or (video['width'] <= 720
                                and chosen_video['width'] < video['width'])):
                        chosen_video = video
                html = ""
                html += content_remote.sanitize(
                    tornado.escape.xhtml_unescape(chosen_video['embed_code']))
                html += content_remote.sanitize(
                    tornado.escape.xhtml_unescape(post['caption']))
                new_post.view = html
            elif post['type'] == 'answer':
                new_post.title = post['question']
                new_post.view = content_remote.sanitize(
                    tornado.escape.xhtml_unescape(post['answer']))
            new_post.save()

        count = self.models.content_remote.get(to_username=self.user.username,
                                               type='tumblr',
                                               deleted=False).count()
        self.write(json.dumps({'count': count}))
Пример #8
0
    def timeline_result(self, tweets):
        for tweet in tweets:
            exists = self.models.content_remote.get(
                to_username=self.user.username,
                type='twitter',
                post_id=str(tweet['id']))[0]

            if exists:
                continue
            else:
                new_tweet = self.models.content_remote()

            new_tweet.to_username = self.user.username
            new_tweet.username = tweet['user']['screen_name']
            new_tweet.from_user = ('http://twitter.com/' +
                                   tweet['user']['screen_name'])
            new_tweet.avatar = tweet['user']['profile_image_url']

            parsed_date = re.compile(r'\+.....').sub('', tweet['created_at'])
            parsed_date = datetime.datetime.strptime(parsed_date,
                                                     '%a %b %d %H:%M:%S %Y')

            # we don't keep items that are over 30 days old
            if parsed_date < datetime.datetime.utcnow() - datetime.timedelta(
                    days=self.constants['feed_max_days_old']):
                continue

            new_tweet.date_created = parsed_date
            new_tweet.date_updated = None
            new_tweet.comments_count = 0
            new_tweet.comments_updated = None
            new_tweet.type = 'twitter'
            new_tweet.title = ''
            new_tweet.post_id = str(tweet['id'])
            new_tweet.link = ('http://twitter.com/' +
                              tweet['user']['screen_name'] + '/status/' +
                              str(tweet['id']))
            if tweet.has_key('retweeted_status'):
                text = tornado.escape.linkify(
                    tweet['retweeted_status']['text'])
                text += (
                    '<br><span class="hw-retweeted-by">' +
                    self.locale.translate(
                        'retweeted by <a href="%(link)s">%(tweeter)s</a>') %
                    {
                        'link':
                        'http://twitter.com/' + tweet['user']['screen_name'],
                        'tweeter':
                        tweet['user']['screen_name']
                    } + '</span>')
                new_tweet.username = tweet['retweeted_status']['user'][
                    'screen_name']
                new_tweet.from_user = (
                    'http://twitter.com/' +
                    tweet['retweeted_status']['user']['screen_name'])
                new_tweet.avatar = \
                    tweet['retweeted_status']['user']['profile_image_url']
            else:
                text = tornado.escape.linkify(tweet['text'])
            text = re.compile(r'#(\w+)', re.M | re.U).sub(
                r'<a href="https://twitter.com/#!/search/%23\1" rel="tag">#\1</a>',
                text)
            text = re.compile(r'@(\w+)', re.M | re.U).sub(
                r'<a href="https://twitter.com/#!/\1">@\1</a>', text)
            new_tweet.view = content_remote.sanitize(
                tornado.escape.xhtml_unescape(text))
            new_tweet.save()

        count = self.models.content_remote.get(to_username=self.user.username,
                                               type='twitter',
                                               deleted=False).count()
        self.write(json.dumps({'count': count}))
Пример #9
0
  def timeline_result(self, tweets):
    for tweet in tweets:
      exists = self.models.content_remote.get(to_username=self.user.username,
          type='twitter', post_id=str(tweet['id']))[0]

      if exists:
        continue
      else:
        new_tweet = self.models.content_remote()

      new_tweet.to_username = self.user.username
      new_tweet.username = tweet['user']['screen_name']
      new_tweet.from_user = ('http://twitter.com/' +
          tweet['user']['screen_name'])
      new_tweet.avatar = tweet['user']['profile_image_url']

      parsed_date = re.compile(r'\+.....').sub('', tweet['created_at'])
      parsed_date = datetime.datetime.strptime(parsed_date,
          '%a %b %d %H:%M:%S %Y')

      # we don't keep items that are over 30 days old
      if parsed_date < datetime.datetime.utcnow() - datetime.timedelta(
          days=self.constants['feed_max_days_old']):
        continue

      new_tweet.date_created = parsed_date
      new_tweet.date_updated = None
      new_tweet.comments_count = 0
      new_tweet.comments_updated = None
      new_tweet.type = 'twitter'
      new_tweet.title = ''
      new_tweet.post_id = str(tweet['id'])
      new_tweet.link = ('http://twitter.com/' + tweet['user']['screen_name'] +
          '/status/' + str(tweet['id']))
      if tweet.has_key('retweeted_status'):
        text = tornado.escape.linkify(tweet['retweeted_status']['text'])
        text += ('<br><span class="hw-retweeted-by">'
            + self.locale.translate(
              'retweeted by <a href="%(link)s">%(tweeter)s</a>')
            % { 'link': 'http://twitter.com/' + tweet['user']['screen_name'],
                'tweeter': tweet['user']['screen_name'] }
            + '</span>')
        new_tweet.username = tweet['retweeted_status']['user']['screen_name']
        new_tweet.from_user = ('http://twitter.com/' +
            tweet['retweeted_status']['user']['screen_name'])
        new_tweet.avatar = \
            tweet['retweeted_status']['user']['profile_image_url']
      else:
        text = tornado.escape.linkify(tweet['text'])
      text = re.compile(r'#(\w+)', re.M | re.U).sub(
          r'<a href="https://twitter.com/#!/search/%23\1" rel="tag">#\1</a>',
          text)
      text = re.compile(r'@(\w+)', re.M | re.U).sub(
          r'<a href="https://twitter.com/#!/\1">@\1</a>', text)
      new_tweet.view = content_remote.sanitize(
          tornado.escape.xhtml_unescape(text))
      new_tweet.save()

    count = self.models.content_remote.get(to_username=self.user.username,
        type='twitter', deleted=False).count()
    self.write(json.dumps({ 'count': count }))
Пример #10
0
  def handle_mention(self, local_content_url, local_content,
      target_url, source_url):
    source_html = urllib2.urlopen(source_url)
    source_html = content_remote.sanitize(
        tornado.escape.xhtml_unescape(source_html.read()))
    source_doc = BeautifulSoup(source_html)

    hEntry = source_doc.find(attrs={'class':re.compile(r'\bh-entry\b')})
    if not hEntry:
      return

    remote_content = hEntry.find(
        attrs={'class':re.compile(r'\be-content\b')})

    existing_content = self.models.content_remote.get(
        to_username=self.display["user"].username,
        from_user=source_url,
        view=remote_content)[0]

    import logging
    logging.error(remote_content)
    # TODO(mime): source_url should actually point to the user's url
    # Should look at webfinger for url.
    this_user_url = self.nav_url(host=True,
        username=self.display["user"].username)
    thread = target_url != this_user_url

    if thread:
      try:
        local_content.comments_count += 1
        local_content.comments_updated = datetime.datetime.utcnow()
        local_content.save()
      except Exception as ex:
        import logging
        logging.error("something wrong with thread")
        logging.error(ex)

    is_spam = False # TODO(mime): spam.guess(remote_content,
        #self.application.settings["private_path"],
        #self.display["user"].username)

    if existing_content:
      # possible that it's picked up via feed, before we get the salmon call
      post_remote = existing_content
    else:
      post_remote = self.models.content_remote()
    post_remote.to_username = self.display["user"].username
    post_remote.from_user = source_url
    post_remote.username = '******'
    post_remote.avatar = '' # TODO(mime): user_remote.avatar
    current_datetime = datetime.datetime.utcnow()
    published = hEntry.find(
        attrs={'class':re.compile(r'\bdt-published\b'), 'datetime':re.compile('.+')})
    if published:
      post_remote.date_created = datetime.datetime.strptime(
          published['datetime'].string[:-6], '%Y-%m-%dT%H:%M:%S')
    else:
      post_remote.date_created = current_datetime
    updated = hEntry.find(
        attrs={'class':re.compile(r'\bdt-updated\b'), 'datetime':re.compile('.+')})
    if updated:
      post_remote.date_updated = datetime.datetime.strptime(
          updated['datetime'].string[:-6], '%Y-%m-%dT%H:%M:%S')
    else:
      post_remote.date_updated = current_datetime
    #if is_spam:
    #  post_remote.is_spam = True
    #else:
    #  spam.train_ham(remote_content, self.application.settings["private_path"],
    #      self.display["user"].username)
    post_remote.type = 'comment' if thread or (existing_content and
        existing_content.type == 'comment') else 'post'
    title = hEntry.find(
        attrs={'class':re.compile(r'\bp-summary\b')})
    if title:
      post_remote.title = title.string
    post_remote.post_id = source_url
    post_remote.link = source_url
    post_remote.local_content_name = local_content.name if thread else ''
    post_remote.view = remote_content
    post_remote.save()

    if thread:
      smtp.comment(self, post_remote.username, post_remote.from_user,
          self.display["user"].email, self.content_url(local_content, host=True),
          remote_content)
    else:
      smtp.comment(self, post_remote.username, post_remote.from_user,
          self.display["user"].email, post_remote.link,
          remote_content, this_user_mentioned=True)
Пример #11
0
    def handle_activity_verb(self, env, signer_uri):
        salmon_doc = BeautifulSoup(env)
        activity_verb = salmon_doc.find(re.compile('.+:verb$')).string
        user_remote = self.models.users_remote.get(
            local_username=self.display["user"].username,
            profile_url=signer_uri)[0]

        if (activity_verb == 'http://activitystrea.ms/schema/1.0/follow'):
            user = users.get_remote_user_info(self, signer_uri,
                                              user_remote.local_username)
            user.follower = 1
            user.save()
            smtp.follow(self, user.username, self.display["user"].email,
                        user.profile_url)
        elif (activity_verb == 'http://ostatus.org/schema/1.0/unfollow'
              or activity_verb
              == 'http://activitystrea.ms/schema/1.0/stop-following'):
            user_remote.follower = 0
            user_remote.save()
        elif (activity_verb == 'http://activitystrea.ms/schema/1.0/favorite'):
            activity_object = salmon_doc.find(re.compile('.+:object$'))
            atom_id = activity_object.find('atom:id').string
            local_url = atom_id.split(':')[2]
            content_url = url_factory.load_basic_parameters(self,
                                                            url=local_url)

            already_favorited = self.models.content_remote.get(
                to_username=self.display["user"].username,
                from_user=signer_uri,
                type='favorite',
                local_content_name=content_url['name'])[0]
            if already_favorited:
                return

            content = self.models.content.get(
                username=self.display["user"].username,
                name=content_url['name'])[0]
            if not content:
                raise tornado.web.HTTPError(400)
            content.favorites += 1
            content.save()

            favorite_record = self.models.content_remote()
            favorite_record.to_username = self.display["user"].username
            favorite_record.from_user = signer_uri
            favorite_record.username = user_remote.username
            favorite_record.date_created = datetime.datetime.strptime(
                salmon_doc.find('atom:updated').string[:-6],
                '%Y-%m-%dT%H:%M:%S')
            favorite_record.type = 'favorite'
            favorite_record.local_content_name = content.name
            favorite_record.save()
        elif (activity_verb == 'http://activitystrea.ms/schema/1.0/unfavorite'
              or activity_verb == 'http://ostatus.org/schema/1.0/unfavorite'):
            # TODO no activity object at least with ostatus??
            pass
        elif (activity_verb == 'http://activitystrea.ms/schema/1.0/share'):
            # TODO
            pass
        elif (activity_verb == 'http://activitystrea.ms/schema/1.0/post'):
            atom_content = salmon_doc.find('atom:content').string
            sanitized_atom_content = content_remote.sanitize(
                tornado.escape.xhtml_unescape(atom_content))

            existing_content = self.models.content_remote.get(
                to_username=self.display["user"].username,
                from_user=signer_uri,
                view=sanitized_atom_content)[0]

            thread = salmon_doc.find('thr:in-reply-to')
            ref = ''
            if thread:
                try:
                    local_url = thread['ref'].split(':')[2]
                    content_url = url_factory.load_basic_parameters(
                        self, url=local_url)
                    content = self.models.content.get(
                        username=self.display["user"].username,
                        name=content_url['name'])[0]
                    if not content:
                        raise tornado.web.HTTPError(400)
                    ref = content_url['name']
                    content.comments_count += 1
                    content.comments_updated = datetime.datetime.utcnow()
                    content.save()
                except Exception as ex:
                    import logging
                    logging.error("something wrong with thread")
                    logging.error(ex)

            replies = salmon_doc.find('thr:replies')
            comments_count = 0
            comments_updated = None
            if replies:
                if replies.has_key('count'):
                    comments_count = int(replies['count'])
                if replies.has_key('updated'):
                    comments_updated = replies['updated']
                comments_response = urllib2.urlopen(replies['href'])
                content_remote.parse_feed(self.models,
                                          user_remote,
                                          comments_response.read(),
                                          remote_comments=True)

            mentioned = salmon_doc.findAll('atom:link', rel='mentioned')
            if not mentioned:
                mentioned = salmon_doc.findAll('atom:link',
                                               rel='ostatus:attention')

            this_user_mentioned = False
            if mentioned:
                this_user_url = self.nav_url(
                    host=True, username=self.display["user"].username)
                for mentions in mentioned:
                    if mentions['href'] == this_user_url:
                        # hey, you've been mentioned. cool.
                        this_user_mentioned = True
                        break

            is_spam = spam.guess(atom_content,
                                 self.application.settings["private_path"],
                                 self.display["user"].username)

            if existing_content:
                # possible that it's picked up via feed, before we get the salmon call
                post_remote = existing_content
            else:
                post_remote = self.models.content_remote()
            post_remote.to_username = self.display["user"].username
            post_remote.from_user = signer_uri
            post_remote.username = user_remote.username
            post_remote.avatar = user_remote.avatar
            post_remote.date_created = datetime.datetime.strptime(
                salmon_doc.find('atom:published').string[:-6],
                '%Y-%m-%dT%H:%M:%S')
            post_remote.date_updated = datetime.datetime.strptime(
                salmon_doc.find('atom:updated').string[:-6],
                '%Y-%m-%dT%H:%M:%S')
            post_remote.comments_count = comments_count
            if comments_updated:
                post_remote.comments_updated = datetime.datetime.strptime(
                    comments_updated[:-6], '%Y-%m-%dT%H:%M:%S')
            else:
                post_remote.comments_updated = None
            if is_spam:
                post_remote.is_spam = True
            else:
                spam.train_ham(atom_content,
                               self.application.settings["private_path"],
                               self.display["user"].username)
            post_remote.type = 'comment' if ref or (
                existing_content
                and existing_content.type == 'comment') else 'post'
            post_remote.title = salmon_doc.find('atom:title').string
            post_remote.post_id = salmon_doc.find('atom:id').string
            post_remote.link = salmon_doc.find('atom:link',
                                               rel='alternate')['href']
            post_remote.local_content_name = content.name if ref else ''
            post_remote.view = sanitized_atom_content
            post_remote.save()

            if ref:
                socialize.socialize(self, content)

            if ref:
                smtp.comment(self, post_remote.username, post_remote.from_user,
                             self.display["user"].email,
                             self.content_url(content, host=True),
                             sanitized_atom_content)
            elif this_user_mentioned:
                smtp.comment(self,
                             post_remote.username,
                             post_remote.from_user,
                             self.display["user"].email,
                             post_remote.link,
                             sanitized_atom_content,
                             this_user_mentioned=True)
Пример #12
0
    def timeline_result(self, response):
        # Check if our OAuth key has expired
        if (response.has_key('error')
                and response['error']['type'] == 'OAuthException'):
            self.delete()
            return

        posts = response['data']
        for post in posts:
            exists = self.models.content_remote.get(
                to_username=self.user.username,
                type='facebook',
                post_id=post['id'])[0]

            date_updated = None
            if post.has_key('updated_time'):
                date_updated = datetime.datetime.strptime(
                    post['updated_time'][:-5], '%Y-%m-%dT%H:%M:%S')

            if exists:
                if date_updated and date_updated != exists.date_updated \
                    or post['comments']['count'] != exists.comments_count:
                    new_post = exists
                else:
                    continue
            else:
                new_post = self.models.content_remote()

            new_post.to_username = self.user.username
            new_post.username = post['from']['name']
            if post.has_key('actions'):
                new_post.from_user = post['actions'][0]['link']
            #new_post.avatar = tweet['user']['profile_image_url']

            parsed_date = datetime.datetime.strptime(post['created_time'][:-5],
                                                     '%Y-%m-%dT%H:%M:%S')

            # we don't keep items that are over 30 days old
            if parsed_date < datetime.datetime.utcnow() - datetime.timedelta(
                    days=self.constants['feed_max_days_old']):
                continue

            new_post.date_created = parsed_date
            new_post.date_updated = date_updated
            new_post.comments_count = 0
            new_post.comments_updated = None
            new_post.type = 'facebook'
            new_post.title = ''
            new_post.post_id = post['id']
            new_post.comments_count = post['comments']['count']
            if post['comments']['count'] and post['comments']['data']:
                last_updated = post['comments']['data'][
                    len(post['comments']['data']) - 1]['created_time']
                new_post.comments_updated = datetime.datetime.strptime(
                    last_updated[:-5], '%Y-%m-%dT%H:%M:%S')
            if post.has_key('actions'):
                new_post.link = post['actions'][0]['link']
            elif post.has_key('link'):
                new_post.link = post['link']
            view = ""
            if post.has_key('message'):
                view += post['message'] + "<br>"
            if post.has_key('caption'):
                view += post['caption'] + "<br>"
            if post.has_key('description'):
                view += post['description'] + "<br>"
            if post.has_key('story'):
                view += post['story'] + "<br>"
            view = tornado.escape.linkify(view)
            if post.has_key('picture'):
                view = '<img src="' + post['picture'] + '">' + view
            new_post.view = content_remote.sanitize(
                tornado.escape.xhtml_unescape(view))
            new_post.save()

            # comments
            if post['comments']['count']:
                for comment in post['comments']['data']:
                    exists = self.models.content_remote.get(
                        to_username=self.user.username,
                        post_id=comment['id'])[0]
                    if exists:
                        continue
                    else:
                        new_comment = self.models.content_remote()

                    new_comment.to_username = self.user.username
                    new_comment.username = comment['from']['name']
                    new_comment.from_user = ('http://facebook.com/' +
                                             comment['from']['id'])
                    date_created = datetime.datetime.strptime(
                        comment['created_time'][:-5], '%Y-%m-%dT%H:%M:%S')
                    new_comment.date_created = date_created
                    new_comment.type = 'remote-comment'
                    new_comment.thread = post['id']
                    new_comment.post_id = comment['id']
                    if post.has_key('actions'):
                        new_comment.link = post['actions'][0]['link']
                    new_comment.view = comment['message']
                    new_comment.save()

        count = self.models.content_remote.get(to_username=self.user.username,
                                               type='facebook',
                                               deleted=False).count()
        self.write(json.dumps({'count': count}))
Пример #13
0
  def handle_activity_verb(self, env, signer_uri):
    salmon_doc = BeautifulSoup(env)
    activity_verb = salmon_doc.find(re.compile('.+:verb$')).string
    user_remote = self.models.users_remote.get(
        local_username=self.display["user"].username,
        profile_url=signer_uri)[0]

    if (activity_verb == 'http://activitystrea.ms/schema/1.0/follow'):
      user = users.get_remote_user_info(self, signer_uri,
          user_remote.local_username)
      user.follower = 1
      user.save()
      smtp.follow(self, user.username, self.display["user"].email,
          user.profile_url)
    elif (activity_verb == 'http://ostatus.org/schema/1.0/unfollow' or
        activity_verb == 'http://activitystrea.ms/schema/1.0/stop-following'):
      user_remote.follower = 0
      user_remote.save()
    elif (activity_verb == 'http://activitystrea.ms/schema/1.0/favorite'):
      activity_object = salmon_doc.find(re.compile('.+:object$'))
      atom_id = activity_object.find('atom:id').string
      local_url = atom_id.split(':')[2]
      content_url = url_factory.load_basic_parameters(self, url=local_url)

      already_favorited = self.models.content_remote.get(
          to_username=self.display["user"].username,
          from_user=signer_uri,
          type='favorite',
          local_content_name=content_url['name'])[0]
      if already_favorited:
        return

      content = self.models.content.get(username=self.display["user"].username,
                                        name=content_url['name'])[0]
      if not content:
        raise tornado.web.HTTPError(400)
      content.favorites += 1
      content.save()

      favorite_record = self.models.content_remote()
      favorite_record.to_username = self.display["user"].username
      favorite_record.from_user = signer_uri
      favorite_record.username = user_remote.username
      favorite_record.date_created = datetime.datetime.strptime(
          salmon_doc.find('atom:updated').string[:-6], '%Y-%m-%dT%H:%M:%S')
      favorite_record.type = 'favorite'
      favorite_record.local_content_name = content.name
      favorite_record.save()
    elif (activity_verb == 'http://activitystrea.ms/schema/1.0/unfavorite' or
        activity_verb == 'http://ostatus.org/schema/1.0/unfavorite'):
      # TODO no activity object at least with ostatus??
      pass
    elif (activity_verb == 'http://activitystrea.ms/schema/1.0/share'):
      # TODO
      pass
    elif (activity_verb == 'http://activitystrea.ms/schema/1.0/post'):
      atom_content = salmon_doc.find('atom:content').string
      sanitized_atom_content = content_remote.sanitize(
          tornado.escape.xhtml_unescape(atom_content))

      existing_content = self.models.content_remote.get(
          to_username=self.display["user"].username,
          from_user=signer_uri,
          view=sanitized_atom_content)[0]

      thread = salmon_doc.find('thr:in-reply-to')
      ref = ''
      if thread:
        try:
          local_url = thread['ref'].split(':')[2]
          content_url = url_factory.load_basic_parameters(self, url=local_url)
          content = self.models.content.get(
              username=self.display["user"].username,
              name=content_url['name'])[0]
          if not content:
            raise tornado.web.HTTPError(400)
          ref = content_url['name']
          content.comments_count += 1
          content.comments_updated = datetime.datetime.utcnow()
          content.save()
        except Exception as ex:
          import logging
          logging.error("something wrong with thread")
          logging.error(ex)

      replies = salmon_doc.find('thr:replies')
      comments_count = 0
      comments_updated = None
      if replies:
        if replies.has_key('count'):
          comments_count = int(replies['count'])
        if replies.has_key('updated'):
          comments_updated = replies['updated']
        comments_response = urllib2.urlopen(replies['href'])
        content_remote.parse_feed(self.models, user_remote,
            comments_response.read(), remote_comments=True)

      mentioned = salmon_doc.findAll('atom:link', rel='mentioned')
      if not mentioned:
        mentioned = salmon_doc.findAll('atom:link', rel='ostatus:attention')

      this_user_mentioned = False
      if mentioned:
        this_user_url = self.nav_url(host=True,
            username=self.display["user"].username)
        for mentions in mentioned:
          if mentions['href'] == this_user_url:
            # hey, you've been mentioned. cool.
            this_user_mentioned = True
            break

      is_spam = spam.guess(atom_content,
          self.application.settings["private_path"],
          self.display["user"].username)

      if existing_content:
        # possible that it's picked up via feed, before we get the salmon call
        post_remote = existing_content
      else:
        post_remote = self.models.content_remote()
      post_remote.to_username = self.display["user"].username
      post_remote.from_user = signer_uri
      post_remote.username = user_remote.username
      post_remote.avatar = user_remote.avatar
      post_remote.date_created = datetime.datetime.strptime(
          salmon_doc.find('atom:published').string[:-6], '%Y-%m-%dT%H:%M:%S')
      post_remote.date_updated = datetime.datetime.strptime(
          salmon_doc.find('atom:updated').string[:-6], '%Y-%m-%dT%H:%M:%S')
      post_remote.comments_count = comments_count
      if comments_updated:
        post_remote.comments_updated = datetime.datetime.strptime(
            comments_updated[:-6], '%Y-%m-%dT%H:%M:%S')
      else:
        post_remote.comments_updated = None
      if is_spam:
        post_remote.is_spam = True
      else:
        spam.train_ham(atom_content, self.application.settings["private_path"],
            self.display["user"].username)
      post_remote.type = 'comment' if ref or (existing_content and
          existing_content.type == 'comment') else 'post'
      post_remote.title = salmon_doc.find('atom:title').string
      post_remote.post_id = salmon_doc.find('atom:id').string
      post_remote.link = salmon_doc.find('atom:link', rel='alternate')['href']
      post_remote.local_content_name = content.name if ref else ''
      post_remote.view = sanitized_atom_content
      post_remote.save()

      if ref:
        socialize.socialize(self, content)

      if ref:
        smtp.comment(self, post_remote.username, post_remote.from_user,
            self.display["user"].email, self.content_url(content, host=True),
            sanitized_atom_content)
      elif this_user_mentioned:
        smtp.comment(self, post_remote.username, post_remote.from_user,
            self.display["user"].email, post_remote.link,
            sanitized_atom_content, this_user_mentioned=True)
Пример #14
0
  def timeline_result(self, response):
    posts = response['response']['posts']
    for post in posts:
      exists = self.models.content_remote.get(to_username=self.user.username,
          type='tumblr', post_id=str(post['id']))[0]

      if exists:
        continue
      else:
        new_post = self.models.content_remote()

      new_post.to_username = self.user.username
      new_post.username = post['blog_name']
      new_post.from_user = '******' + post['blog_name']
      #new_post.avatar = post['user']['profile_image_url']

      parsed_date = datetime.datetime.utcfromtimestamp(post['timestamp'])

      # we don't keep items that are over 30 days old
      if parsed_date < datetime.datetime.utcnow() - datetime.timedelta(
          days=self.constants['feed_max_days_old']):
        continue

      new_post.date_created = parsed_date
      new_post.date_updated = None
      new_post.comments_count = post['note_count']
      new_post.comments_updated = None
      new_post.type = 'tumblr'
      new_post.post_id = str(post['id'])
      new_post.link = post['post_url']
      if post['type'] == 'text':
        new_post.title = post['title']
        new_post.view = content_remote.sanitize(
            tornado.escape.xhtml_unescape(post['body']))
      elif post['type'] == 'photo':
        html = ""
        for photo in post['photos']:
          chosen_photo = None
          for size in photo['alt_sizes']:
            if (not chosen_photo or (size['width'] <= 720 and
                chosen_photo['width'] < size['width'])):
              chosen_photo = size
          html += '<img src="' + content_remote.sanitize(
              tornado.escape.xhtml_unescape(chosen_photo['url'])) + '">'
        html += content_remote.sanitize(tornado.escape.xhtml_unescape(
            post['caption']))
        new_post.view = html
      elif post['type'] == 'quote':
        new_post.view = content_remote.sanitize(tornado.escape.xhtml_unescape(
            post['text'] + '<br>' + post['source']))
      elif post['type'] == 'link':
        new_post.title = post['title']
        new_post.view = content_remote.sanitize(tornado.escape.xhtml_unescape(
            '<a href="' + post['url'] + '">' + post['url'] + '</a><br>' +
            post['description']))
      elif post['type'] == 'chat':
        new_post.title = post['title']
        new_post.view = content_remote.sanitize(tornado.escape.xhtml_unescape(
            post['body'].replace('\r\n', '<br>')))
      elif post['type'] == 'audio':
        html = ""
        html += content_remote.sanitize(tornado.escape.xhtml_unescape(
            post['player']))
        html += content_remote.sanitize(tornado.escape.xhtml_unescape(
            post['caption']))
        new_post.view = html
      elif post['type'] == 'video':
        chosen_video = None
        for video in post['player']:
          if (not chosen_video or (video['width'] <= 720 and
              chosen_video['width'] < video['width'])):
            chosen_video = video
        html = ""
        html += content_remote.sanitize(tornado.escape.xhtml_unescape(
            chosen_video['embed_code']))
        html += content_remote.sanitize(tornado.escape.xhtml_unescape(
            post['caption']))
        new_post.view = html
      elif post['type'] == 'answer':
        new_post.title = post['question']
        new_post.view = content_remote.sanitize(tornado.escape.xhtml_unescape(
            post['answer']))
      new_post.save()

    count = self.models.content_remote.get(to_username=self.user.username,
        type='tumblr', deleted=False).count()
    self.write(json.dumps({ 'count': count }))