--- /dev/null
+from org.maemo.hermes.engine.twitter.user import User
+import urllib, urllib2
+import base64
+import simplejson
+import urlparse
+
+class TwitterApi():
+ """Twitter backend for Hermes. Inspired by
+ http://code.google.com/p/python-twitter/source/browse/twitter.py
+
+ Copyright (c) Andrew Flegg <andrew@bleb.org> 2010.
+ Released under the Artistic Licence."""
+
+
+ # -----------------------------------------------------------------------
+ def __init__(self, username, password):
+ self._username = username
+ self._password = password
+
+
+ # -----------------------------------------------------------------------
+ def get_friends(self):
+ '''Return the full list of people being followed by 'username'.'''
+
+ url = 'https://twitter.com/statuses/friends.json'
+ cursor = -1
+ users = []
+ while True:
+ json = self._FetchUrl(url, parameters = { 'cursor': cursor})
+ data = simplejson.loads(json)
+ if 'error' in data:
+ raise Exception(data['error'])
+
+ for x in data['users']:
+ users.append(User.NewFromJsonDict(x))
+
+ cursor = data['next_cursor']
+ if cursor <= data['previous_cursor']:
+ break
+
+ return users
+
+
+ # -----------------------------------------------------------------------
+ def _FetchUrl(self,
+ url,
+ parameters=None):
+ '''Fetch a URL, optionally caching for a specified time.
+
+ Args:
+ url:
+ The URL to retrieve
+ parameters:
+ A dict whose key/value pairs should encoded and added
+ to the query string. [optional]
+
+ Returns:
+ A string containing the body of the response.
+ '''
+
+ # Build the extra parameters dict
+ extra_params = {}
+ if parameters:
+ extra_params.update(parameters)
+
+ # Add key/value parameters to the query string of the url
+ url = self._BuildUrl(url, extra_params=extra_params)
+
+ # Get a url opener that can handle basic auth
+ basic_auth = base64.encodestring('%s:%s' % (self._username, self._password))[:-1]
+
+ handler = urllib2.HTTPBasicAuthHandler()
+ (scheme, netloc, path, params, query, fragment) = urlparse.urlparse(url)
+ handler.add_password('Twitter API', netloc, self._username, self._password)
+ opener = urllib2.build_opener(handler)
+ opener.addheaders = {'Authorization': 'Basic %s' % basic_auth}.items()
+
+ url_data = opener.open(url, None).read()
+ opener.close()
+ return url_data
+
+
+ # -----------------------------------------------------------------------
+ def _BuildUrl(self, url, path_elements=None, extra_params=None):
+ # Break url into consituent parts
+ (scheme, netloc, path, params, query, fragment) = urlparse.urlparse(url)
+
+ # Add any additional path elements to the path
+ if path_elements:
+ # Filter out the path elements that have a value of None
+ p = [i for i in path_elements if i]
+ if not path.endswith('/'):
+ path += '/'
+ path += '/'.join(p)
+
+ # Add any additional query parameters to the query string
+ if extra_params and len(extra_params) > 0:
+ extra_query = self._EncodeParameters(extra_params)
+ # Add it to the existing query
+ if query:
+ query += '&' + extra_query
+ else:
+ query = extra_query
+
+ # Return the rebuilt URL
+ return urlparse.urlunparse((scheme, netloc, path, params, query, fragment))
+
+
+
+ # -----------------------------------------------------------------------
+ def _EncodeParameters(self, parameters):
+ '''Return a string in key=value&key=value form
+
+ Values of None are not included in the output string.
+
+ Args:
+ parameters:
+ A dict of (key, value) tuples, where value is encoded as
+ specified by self._encoding
+ Returns:
+ A URL-encoded string in "key=value&key=value" form
+ '''
+ if parameters is None:
+ return None
+ else:
+ return urllib.urlencode(dict([(k, unicode(v).encode('utf-8')) for k, v in parameters.items() if v is not None]))
+
--- /dev/null
+# Copyright 2007 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+'''A library that provides a python interface to the Twitter API.
+
+ http://code.google.com/p/python-twitter/'''
+
+__author__ = 'dewitt@google.com'
+__version__ = '0.7-devel'
+
+
+
+class User(object):
+ '''A class representing the User structure used by the twitter API.
+
+ The User structure exposes the following properties:
+
+ user.id
+ user.name
+ user.screen_name
+ user.location
+ user.description
+ user.profile_image_url
+ user.profile_background_tile
+ user.profile_background_image_url
+ user.profile_sidebar_fill_color
+ user.profile_background_color
+ user.profile_link_color
+ user.profile_text_color
+ user.protected
+ user.utc_offset
+ user.time_zone
+ user.url
+ user.status
+ user.statuses_count
+ user.followers_count
+ user.friends_count
+ user.favourites_count
+ '''
+ def __init__(self,
+ id=None,
+ name=None,
+ screen_name=None,
+ location=None,
+ description=None,
+ profile_image_url=None,
+ profile_background_tile=None,
+ profile_background_image_url=None,
+ profile_sidebar_fill_color=None,
+ profile_background_color=None,
+ profile_link_color=None,
+ profile_text_color=None,
+ protected=None,
+ utc_offset=None,
+ time_zone=None,
+ followers_count=None,
+ friends_count=None,
+ statuses_count=None,
+ favourites_count=None,
+ url=None,
+ status=None):
+ self.id = id
+ self.name = name
+ self.screen_name = screen_name
+ self.location = location
+ self.description = description
+ self.profile_image_url = profile_image_url
+ self.profile_background_tile = profile_background_tile
+ self.profile_background_image_url = profile_background_image_url
+ self.profile_sidebar_fill_color = profile_sidebar_fill_color
+ self.profile_background_color = profile_background_color
+ self.profile_link_color = profile_link_color
+ self.profile_text_color = profile_text_color
+ self.protected = protected
+ self.utc_offset = utc_offset
+ self.time_zone = time_zone
+ self.followers_count = followers_count
+ self.friends_count = friends_count
+ self.statuses_count = statuses_count
+ self.favourites_count = favourites_count
+ self.url = url
+ self.status = status
+
+
+ def GetId(self):
+ '''Get the unique id of this user.
+
+ Returns:
+ The unique id of this user
+ '''
+ return self._id
+
+ def SetId(self, id):
+ '''Set the unique id of this user.
+
+ Args:
+ id: The unique id of this user.
+ '''
+ self._id = id
+
+ id = property(GetId, SetId,
+ doc='The unique id of this user.')
+
+ def GetName(self):
+ '''Get the real name of this user.
+
+ Returns:
+ The real name of this user
+ '''
+ return self._name
+
+ def SetName(self, name):
+ '''Set the real name of this user.
+
+ Args:
+ name: The real name of this user
+ '''
+ self._name = name
+
+ name = property(GetName, SetName,
+ doc='The real name of this user.')
+
+ def GetScreenName(self):
+ '''Get the short username of this user.
+
+ Returns:
+ The short username of this user
+ '''
+ return self._screen_name
+
+ def SetScreenName(self, screen_name):
+ '''Set the short username of this user.
+
+ Args:
+ screen_name: the short username of this user
+ '''
+ self._screen_name = screen_name
+
+ screen_name = property(GetScreenName, SetScreenName,
+ doc='The short username of this user.')
+
+ def GetLocation(self):
+ '''Get the geographic location of this user.
+
+ Returns:
+ The geographic location of this user
+ '''
+ return self._location
+
+ def SetLocation(self, location):
+ '''Set the geographic location of this user.
+
+ Args:
+ location: The geographic location of this user
+ '''
+ self._location = location
+
+ location = property(GetLocation, SetLocation,
+ doc='The geographic location of this user.')
+
+ def GetDescription(self):
+ '''Get the short text description of this user.
+
+ Returns:
+ The short text description of this user
+ '''
+ return self._description
+
+ def SetDescription(self, description):
+ '''Set the short text description of this user.
+
+ Args:
+ description: The short text description of this user
+ '''
+ self._description = description
+
+ description = property(GetDescription, SetDescription,
+ doc='The short text description of this user.')
+
+ def GetUrl(self):
+ '''Get the homepage url of this user.
+
+ Returns:
+ The homepage url of this user
+ '''
+ return self._url
+
+
+ def SetUrl(self, url):
+ '''Set the homepage url of this user.
+
+ Args:
+ url: The homepage url of this user
+ '''
+ self._url = url
+
+ url = property(GetUrl, SetUrl,
+ doc='The homepage url of this user.')
+
+ def GetProfileImageUrl(self):
+ '''Get the url of the thumbnail of this user.
+
+ Returns:
+ The url of the thumbnail of this user
+ '''
+ return self._profile_image_url
+
+ def SetProfileImageUrl(self, profile_image_url):
+ '''Set the url of the thumbnail of this user.
+
+ Args:
+ profile_image_url: The url of the thumbnail of this user
+ '''
+ self._profile_image_url = profile_image_url
+
+ profile_image_url= property(GetProfileImageUrl, SetProfileImageUrl,
+ doc='The url of the thumbnail of this user.')
+
+ def GetProfileBackgroundTile(self):
+ '''Boolean for whether to tile the profile background image.
+
+ Returns:
+ True if the background is to be tiled, False if not, None if unset.
+ '''
+ return self._profile_background_tile
+
+ def SetProfileBackgroundTile(self, profile_background_tile):
+ '''Set the boolean flag for whether to tile the profile background image.
+
+ Args:
+ profile_background_tile: Boolean flag for whether to tile or not.
+ '''
+ self._profile_background_tile = profile_background_tile
+
+ profile_background_tile = property(GetProfileBackgroundTile, SetProfileBackgroundTile,
+ doc='Boolean for whether to tile the background image.')
+
+ def GetProfileBackgroundImageUrl(self):
+ return self._profile_background_image_url
+
+ def SetProfileBackgroundImageUrl(self, profile_background_image_url):
+ self._profile_background_image_url = profile_background_image_url
+
+ profile_background_image_url = property(GetProfileBackgroundImageUrl, SetProfileBackgroundImageUrl,
+ doc='The url of the profile background of this user.')
+
+ def GetProfileSidebarFillColor(self):
+ return self._profile_sidebar_fill_color
+
+ def SetProfileSidebarFillColor(self, profile_sidebar_fill_color):
+ self._profile_sidebar_fill_color = profile_sidebar_fill_color
+
+ profile_sidebar_fill_color = property(GetProfileSidebarFillColor, SetProfileSidebarFillColor)
+
+ def GetProfileBackgroundColor(self):
+ return self._profile_background_color
+
+ def SetProfileBackgroundColor(self, profile_background_color):
+ self._profile_background_color = profile_background_color
+
+ profile_background_color = property(GetProfileBackgroundColor, SetProfileBackgroundColor)
+
+ def GetProfileLinkColor(self):
+ return self._profile_link_color
+
+ def SetProfileLinkColor(self, profile_link_color):
+ self._profile_link_color = profile_link_color
+
+ profile_link_color = property(GetProfileLinkColor, SetProfileLinkColor)
+
+ def GetProfileTextColor(self):
+ return self._profile_text_color
+
+ def SetProfileTextColor(self, profile_text_color):
+ self._profile_text_color = profile_text_color
+
+ profile_text_color = property(GetProfileTextColor, SetProfileTextColor)
+
+ def GetProtected(self):
+ return self._protected
+
+ def SetProtected(self, protected):
+ self._protected = protected
+
+ protected = property(GetProtected, SetProtected)
+
+ def GetUtcOffset(self):
+ return self._utc_offset
+
+ def SetUtcOffset(self, utc_offset):
+ self._utc_offset = utc_offset
+
+ utc_offset = property(GetUtcOffset, SetUtcOffset)
+
+ def GetTimeZone(self):
+ '''Returns the current time zone string for the user.
+
+ Returns:
+ The descriptive time zone string for the user.
+ '''
+ return self._time_zone
+
+ def SetTimeZone(self, time_zone):
+ '''Sets the user's time zone string.
+
+ Args:
+ time_zone: The descriptive time zone to assign for the user.
+ '''
+ self._time_zone = time_zone
+
+ time_zone = property(GetTimeZone, SetTimeZone)
+
+ def GetStatus(self):
+ '''Get the latest twitter.Status of this user.
+
+ Returns:
+ The latest twitter.Status of this user
+ '''
+ return self._status
+
+ def SetStatus(self, status):
+ '''Set the latest twitter.Status of this user.
+
+ Args:
+ status: The latest twitter.Status of this user
+ '''
+ self._status = status
+
+ status = property(GetStatus, SetStatus,
+ doc='The latest twitter.Status of this user.')
+
+ def GetFriendsCount(self):
+ '''Get the friend count for this user.
+
+ Returns:
+ The number of users this user has befriended.
+ '''
+ return self._friends_count
+
+ def SetFriendsCount(self, count):
+ '''Set the friend count for this user.
+
+ Args:
+ count: The number of users this user has befriended.
+ '''
+ self._friends_count = count
+
+ friends_count = property(GetFriendsCount, SetFriendsCount,
+ doc='The number of friends for this user.')
+
+ def GetFollowersCount(self):
+ '''Get the follower count for this user.
+
+ Returns:
+ The number of users following this user.
+ '''
+ return self._followers_count
+
+ def SetFollowersCount(self, count):
+ '''Set the follower count for this user.
+
+ Args:
+ count: The number of users following this user.
+ '''
+ self._followers_count = count
+
+ followers_count = property(GetFollowersCount, SetFollowersCount,
+ doc='The number of users following this user.')
+
+ def GetStatusesCount(self):
+ '''Get the number of status updates for this user.
+
+ Returns:
+ The number of status updates for this user.
+ '''
+ return self._statuses_count
+
+ def SetStatusesCount(self, count):
+ '''Set the status update count for this user.
+
+ Args:
+ count: The number of updates for this user.
+ '''
+ self._statuses_count = count
+
+ statuses_count = property(GetStatusesCount, SetStatusesCount,
+ doc='The number of updates for this user.')
+
+
+ def GetFavouritesCount(self):
+ '''Get the number of favourites for this user.
+
+ Returns:
+ The number of favourites for this user.
+ '''
+ return self._favourites_count
+
+ def SetFavouritesCount(self, count):
+ '''Set the favourite count for this user.
+
+ Args:
+ count: The number of favourites for this user.
+ '''
+ self._favourites_count = count
+
+ favourites_count = property(GetFavouritesCount, SetFavouritesCount,
+ doc='The number of favourites for this user.')
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __eq__(self, other):
+ try:
+ return other and \
+ self.id == other.id and \
+ self.name == other.name and \
+ self.screen_name == other.screen_name and \
+ self.location == other.location and \
+ self.description == other.description and \
+ self.profile_image_url == other.profile_image_url and \
+ self.profile_background_tile == other.profile_background_tile and \
+ self.profile_background_image_url == other.profile_background_image_url and \
+ self.profile_sidebar_fill_color == other.profile_sidebar_fill_color and \
+ self.profile_background_color == other.profile_background_color and \
+ self.profile_link_color == other.profile_link_color and \
+ self.profile_text_color == other.profile_text_color and \
+ self.protected == other.protected and \
+ self.utc_offset == other.utc_offset and \
+ self.time_zone == other.time_zone and \
+ self.url == other.url and \
+ self.statuses_count == other.statuses_count and \
+ self.followers_count == other.followers_count and \
+ self.favourites_count == other.favourites_count and \
+ self.friends_count == other.friends_count and \
+ self.status == other.status
+ except AttributeError:
+ return False
+
+ def __str__(self):
+ '''A string representation of this twitter.User instance.
+
+ The return value is the same as the JSON string representation.
+
+ Returns:
+ A string representation of this twitter.User instance.
+ '''
+ return self.AsJsonString()
+
+ def AsJsonString(self):
+ '''A JSON string representation of this twitter.User instance.
+
+ Returns:
+ A JSON string representation of this twitter.User instance
+ '''
+ return simplejson.dumps(self.AsDict(), sort_keys=True)
+
+ def AsDict(self):
+ '''A dict representation of this twitter.User instance.
+
+ The return value uses the same key names as the JSON representation.
+
+ Return:
+ A dict representing this twitter.User instance
+ '''
+ data = {}
+ if self.id:
+ data['id'] = self.id
+ if self.name:
+ data['name'] = self.name
+ if self.screen_name:
+ data['screen_name'] = self.screen_name
+ if self.location:
+ data['location'] = self.location
+ if self.description:
+ data['description'] = self.description
+ if self.profile_image_url:
+ data['profile_image_url'] = self.profile_image_url
+ if self.profile_background_tile is not None:
+ data['profile_background_tile'] = self.profile_background_tile
+ if self.profile_background_image_url:
+ data['profile_sidebar_fill_color'] = self.profile_background_image_url
+ if self.profile_background_color:
+ data['profile_background_color'] = self.profile_background_color
+ if self.profile_link_color:
+ data['profile_link_color'] = self.profile_link_color
+ if self.profile_text_color:
+ data['profile_text_color'] = self.profile_text_color
+ if self.protected is not None:
+ data['protected'] = self.protected
+ if self.utc_offset:
+ data['utc_offset'] = self.utc_offset
+ if self.time_zone:
+ data['time_zone'] = self.time_zone
+ if self.url:
+ data['url'] = self.url
+ if self.status:
+ data['status'] = self.status.AsDict()
+ if self.friends_count:
+ data['friends_count'] = self.friends_count
+ if self.followers_count:
+ data['followers_count'] = self.followers_count
+ if self.statuses_count:
+ data['statuses_count'] = self.statuses_count
+ if self.favourites_count:
+ data['favourites_count'] = self.favourites_count
+ return data
+
+ @staticmethod
+ def NewFromJsonDict(data):
+ '''Create a new instance based on a JSON dict.
+
+ Args:
+ data: A JSON dict, as converted from the JSON in the twitter API
+ Returns:
+ A twitter.User instance
+ '''
+ if 'status' in data:
+ status = None #Status.NewFromJsonDict(data['status'])
+ else:
+ status = None
+ return User(id=data.get('id', None),
+ name=data.get('name', None),
+ screen_name=data.get('screen_name', None),
+ location=data.get('location', None),
+ description=data.get('description', None),
+ statuses_count=data.get('statuses_count', None),
+ followers_count=data.get('followers_count', None),
+ favourites_count=data.get('favourites_count', None),
+ friends_count=data.get('friends_count', None),
+ profile_image_url=data.get('profile_image_url', None),
+ profile_background_tile = data.get('profile_background_tile', None),
+ profile_background_image_url = data.get('profile_background_image_url', None),
+ profile_sidebar_fill_color = data.get('profile_sidebar_fill_color', None),
+ profile_background_color = data.get('profile_background_color', None),
+ profile_link_color = data.get('profile_link_color', None),
+ profile_text_color = data.get('profile_text_color', None),
+ protected = data.get('protected', None),
+ utc_offset = data.get('utc_offset', None),
+ time_zone = data.get('time_zone', None),
+ url=data.get('url', None),
+ status=status)
+