def _publish_comment(self, comment, stream): """Publish a single comment into the Dee.SharedModel.""" message_id = comment.get('id') if message_id is None: return message = comment.get('text', '') person = comment.get('from', {}) sender_nick = person.get('username') timestamp = comment.get('created_time') if timestamp is not None: timestamp = iso8601utc(parsetime(timestamp)) icon_uri = person.get('profile_picture') sender_id = person.get('id') sender = person.get('full_name') args = dict( stream=stream, message_id=message_id, message=message, timestamp=timestamp, sender_nick=sender_nick, icon_uri=icon_uri, sender_id=sender_id, sender=sender, ) self._publish(**args)
def test_identica(self): self.assertEqual(parsetime('Fri, 05 Oct 2012 08:46:39'), 1349426799)
def test_nonstandard_facebook(self): # Sigh. Facebook gets close, but no cigar. self.assertEqual(parsetime('2012-05-10T13:36:45+0000'), 1336657005)
def test_nonstandard_twitter_non_utc(self): # Sigh. Twitter has to be different. self.assertEqual(parsetime('Thu May 10 13:36:45 -0400 2012'), 1336671405)
def test_nonstandard_twitter(self): # Sigh. Twitter has to be different. self.assertEqual(parsetime('Thu May 10 13:36:45 +0000 2012'), 1336657005)
def test_non_utc(self): # Non-UTC timezones are get converted to UTC, before conversion to # epoch seconds. self.assertEqual(parsetime('2012-05-10T13:36:45 -0400'), 1336671405)
def test_parse_utctz_altsep(self): # ISO 8601 alternative format with UTC timezone. self.assertEqual(parsetime('2012-05-10T13:36:45 +0000'), 1336657005)
def test_parse_naive_altsep(self): # ISO 8601 alternative format without timezone. self.assertEqual(parsetime('2012-05-10 13:36:45'), 1336657005)
def test_parse_utctz(self): # ISO 8601 standard format with UTC timezone. self.assertEqual(parsetime('2012-05-10T13:36:45Z'), 1336657005)
def test_parse_naive(self): # ISO 8601 standard format without timezone. self.assertEqual(parsetime('2012-05-10T13:36:45'), 1336657005)
def test_type(self): # parsetime() should always return int seconds since the epoch. self.assertTrue(isinstance(parsetime('2012-05-10T13:36:45Z'), int))
def _publish_entry(self, entry, stream='messages'): message_id = entry.get('id') message_type = entry.get('type') if "reply" in stream: message_type = "reply" if None in (message_id, message_type): # We can't do much with this entry. return if 'to' in entry: # Somebody posted on somebodies wall # This cannot be displayed properly in friends so ignore return place = entry.get('place', {}) location = place.get('location', {}) link_pic = entry.get('picture', '') # Use objectID to get a highres version of the picture # Does not seem to work for links object_id = entry.get('object_id') if object_id and ('photo' in message_type): link_pic = "http://graph.facebook.com/" + object_id + "/picture?type=normal" args = dict( message_id=message_id, stream='images' if ('photo' in message_type) else stream, message=entry.get('message', '') or entry.get('story', ''), icon_uri=entry.get('icon', ''), link_picture=link_pic, link_name=entry.get('name', ''), link_url=entry.get('link', ''), link_desc=entry.get('description', ''), link_caption=entry.get('caption', ''), location=place.get('name', ''), latitude=location.get('latitude', 0.0), longitude=location.get('longitude', 0.0), ) # Posts gives us a likes dict, while replies give us an int. likes = entry.get('likes', 0) if isinstance(likes, dict): likes = likes.get('count', 0) args['likes'] = likes # Fix for LP:1185684 - JPM post_id = message_id.split('_')[1] if '_' in message_id else message_id from_record = entry.get('from') if from_record is not None: args['sender'] = from_record.get('name', '') args['sender_id'] = sender_id = from_record.get('id', '') args['url'] = STORY_PERMALINK.format( id=sender_id, post_id=post_id) args['icon_uri'] = (API_BASE.format(id=sender_id) + '/picture?width=840&height=840') args['sender_nick'] = from_record.get('name', '') args['from_me'] = (sender_id == self._account.user_id) # Normalize the timestamp. timestamp = entry.get('updated_time', entry.get('created_time')) if timestamp is not None: timestamp = args['timestamp'] = iso8601utc(parsetime(timestamp)) # We need to record timestamps for use with since=. Note that # _timestamps is a special dict subclass that only accepts # timestamps that are larger than the existing value, so at any # given time it will map the stream to the most # recent timestamp we've seen for that stream. self._timestamps[stream] = timestamp # Publish this message into the SharedModel. self._publish(**args) # If there are any replies, publish them as well. for comment in entry.get('comments', {}).get('data', []): if comment: self._publish_entry( stream='reply_to/{}'.format(message_id), entry=comment) return args['url']
def receive(self): """Download all of a user's public photos.""" # Trigger loggin in. self._get_access_token() args = dict( api_key=self._account.consumer_key, method='flickr.photos.getContactsPhotos', format='json', nojsoncallback='1', extras='date_upload,owner_name,icon_server,geo', ) response = self._get_url(args) for data in response.get('photos', {}).get('photo', []): # Pre-calculate some values to publish. username = data.get('username', '') ownername = data.get('ownername', '') photo_id = data.get('id') if photo_id is None: # Can't do anything without this, really. continue # Icons. icon_farm = data.get('iconfarm') icon_server = data.get('iconserver') owner = data.get('owner') icon_uri = '' url = '' from_me = (ownername == username) if None not in (icon_farm, icon_server, owner): icon_uri = BUDDY_ICON_URL.format( farm=icon_farm, server=icon_server, nsid=owner) url = IMAGE_PAGE_URL.format(owner=owner, photo=photo_id) # Calculate the ISO 8601 UTC time string. try: timestamp = iso8601utc(parsetime(data.get('dateupload', ''))) except ValueError: timestamp = '' # Images. farm = data.get('farm') server = data.get('server') secret = data.get('secret') img_src, img_thumb = '', '' if None not in (farm, server, secret): args = dict( farm=farm, server=server, photo=photo_id, secret=secret, ) img_src = IMAGE_URL.format(type='m', **args) img_thumb = IMAGE_URL.format(type='t', **args) self._publish( message_id=photo_id, message=data.get('title', ''), stream='images', sender=ownername, sender_id=owner, sender_nick=ownername, icon_uri=icon_uri, url=url, from_me=from_me, timestamp=timestamp, link_url=url, link_picture=img_src, link_icon=img_thumb, latitude=data.get('latitude', 0.0), longitude=data.get('longitude', 0.0), ) return self._get_n_rows()
def _publish_entry(self, entry, stream='messages'): """Publish a single update into the Dee.SharedModel.""" message_id = entry.get('id') if message_id is None: # We can't do much with this entry. return person = entry.get('user') nick = person.get('username') name = person.get('full_name') person_id = person.get('id') message= '%s shared a picture on Instagram.' % nick person_icon = person.get('profile_picture') person_url = 'http://instagram.com/' + nick picture = entry.get('images').get('thumbnail').get('url') if entry.get('caption'): desc = entry.get('caption').get('text', '') else: desc = '' url = entry.get('link') timestamp = entry.get('created_time') if timestamp is not None: timestamp = iso8601utc(parsetime(timestamp)) likes = entry.get('likes').get('count') liked = entry.get('user_has_liked') location = entry.get('location', {}) if location: latitude = location.get('latitude', '') longitude = location.get('longitude', '') else: latitude = 0 longitude = 0 args = dict( message_id=message_id, message=message, stream=stream, likes=likes, sender_id=person_id, sender=name, sender_nick=nick, url=person_url, icon_uri=person_icon, link_url=url, link_picture=picture, link_desc=desc, timestamp=timestamp, liked=liked, latitude=latitude, longitude=longitude ) self._publish(**args) # If there are any replies, publish them as well. parent_id = message_id for comment in entry.get('comments', {}).get('data', []): if comment: self._publish_comment( comment, stream='reply_to/{}'.format(parent_id)) return args['url']
def _publish_tweet(self, tweet, stream='messages'): """Publish a single tweet into the Dee.SharedModel.""" tweet_id = tweet.get('id_str') or str(tweet.get('id', '')) if not tweet_id: log.info('Ignoring tweet with no id_str value') return # We need to record tweet_ids for use with since_id. Note that # _tweet_ids is a special dict subclass that only accepts # tweet_ids that are larger than the existing value, so at any # given time it will map the stream to the largest (most # recent) tweet_id we've seen for that stream. self._tweet_ids[stream] = tweet_id # 'user' for tweets, 'sender' for direct messages. user = tweet.get('user', {}) or tweet.get('sender', {}) screen_name = user.get('screen_name', '') avatar_url = ( user.get('profile_image_url_https') or # Twitter, or user.get('profile_image_url') or # Identi.ca '') permalink = self._tweet_permalink.format(user_id=screen_name, tweet_id=tweet_id) # If this is an RT, we are more interested in the original tweet retweet = tweet.get('retweeted_status', {}) entities = retweet.get('entities', {}) or tweet.get('entities', {}) message = retweet.get('text', '') or tweet.get('text', '') picture_url = '' urls = {} for url in (entities.get('urls', []) + entities.get('media', []) + entities.get('user_mentions', []) + entities.get('hashtags', [])): begin, end = url.get('indices', (None, None)) #Drop invalid entities (just to be safe) if None not in (begin, end): urls[begin] = url for key, url in sorted(urls.items(), reverse=True): begin, end = url.get('indices', (None, None)) expanded_url = url.get('expanded_url') display_url = url.get('display_url') other_url = url.get('url') mention_name = url.get('screen_name') picture_url = url.get('media_url', picture_url) hashtag = url.get('text') content = None # Friends has no notion of display URLs, so this is handled at the protocol level if (other_url or expanded_url): content = self._linkify(expanded_url or other_url, display_url or other_url) # Linkify hashtags until supported by friends-app if hashtag: content = self._linkify( 'https://twitter.com/search?q=%23' + hashtag + '&src=hash', '#' + hashtag) # Linkify a mention until they are supported natively by friends if mention_name: content = self._linkify_mention(mention_name) if content: message = ''.join([message[:begin], content, message[end:]]) if retweet: message = 'RT {}: {}'.format( self._linkify_mention( retweet.get('user', {}).get('screen_name', '')), message) if picture_url: stream = 'images' self._publish( message_id=tweet_id, message=message, timestamp=iso8601utc(parsetime(tweet.get('created_at', ''))), stream=stream, sender=user.get('name', ''), sender_id=str(user.get('id', '')), sender_nick=screen_name, from_me=(screen_name == self._account.user_name), icon_uri=avatar_url.replace('_normal.', '.'), liked=tweet.get('favorited', False), url=permalink, link_picture=picture_url, ) return permalink