|
|
|
@ -30,7 +30,7 @@ import gettext
|
|
|
|
|
from httplib import BadStatusLine |
|
|
|
|
from socket import error as socketError |
|
|
|
|
|
|
|
|
|
from networkbase import NetworkBase, NetworkData, auth_options, \ |
|
|
|
|
from networkbase import NetworkBase, NetworkData, NetworkUser, auth_options, \ |
|
|
|
|
NetworkDNSError, NetworkBadStatusLineError, NetworkLowLevelError, \ |
|
|
|
|
NetworkInvalidResponseError, NetworkPermissionDeniedError, \ |
|
|
|
|
MessageTooLongWarning |
|
|
|
@ -113,6 +113,15 @@ def _make_datetime(response):
|
|
|
|
|
|
|
|
|
|
return result |
|
|
|
|
|
|
|
|
|
class TwitterNetworkUser(NetworkUser): |
|
|
|
|
"""A simple wrapper around :class:`NetwokrUser`, to make things easier to |
|
|
|
|
convert twitter user information into a NetworkUser object.""" |
|
|
|
|
|
|
|
|
|
def __init__(self, data): |
|
|
|
|
self.name = data['user']['name'] |
|
|
|
|
self.username = data['user']['screen_name'] |
|
|
|
|
self.avatar = data['user']['profile_image_url'] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TwitterNetworkData(NetworkData): |
|
|
|
|
"""A simple wrapper around NetworkData, to make things easier to convert |
|
|
|
@ -123,9 +132,7 @@ class TwitterNetworkData(NetworkData):
|
|
|
|
|
NetworkData.__init__(self) |
|
|
|
|
|
|
|
|
|
self.id = data['id'] |
|
|
|
|
self.name = data['user']['name'] |
|
|
|
|
self.username = data['user']['screen_name'] |
|
|
|
|
self.avatar = data['user']['profile_image_url'] |
|
|
|
|
self.author = TwitterNetworkUser(data) |
|
|
|
|
self.message_time = _to_datetime(data['created_at']) |
|
|
|
|
|
|
|
|
|
if 'protected' in data['user']: |
|
|
|
@ -136,16 +143,14 @@ class TwitterNetworkData(NetworkData):
|
|
|
|
|
self.favourited = data['favorited'] |
|
|
|
|
|
|
|
|
|
if 'in_reply_to_status_id' in data and data['in_reply_to_status_id']: |
|
|
|
|
owner = NetworkUser() |
|
|
|
|
owner.username = data['in_reply_to_screen_name'] |
|
|
|
|
# TODO: Check if we have the other data. |
|
|
|
|
self.parent = int(data['in_reply_to_status_id']) |
|
|
|
|
self.parent_owner = data['in_reply_to_screen_name'] |
|
|
|
|
|
|
|
|
|
if 'retweeted_status' in data: |
|
|
|
|
self.reposted_by = self.username |
|
|
|
|
|
|
|
|
|
retweet_user = data['retweeted_status']['user'] |
|
|
|
|
self.name = retweet_user['name'] |
|
|
|
|
self.username = retweet_user['screen_name'] |
|
|
|
|
self.avatar = retweet_user['profile_image_url'] |
|
|
|
|
self.reposted_by = self.author |
|
|
|
|
self.author = TwitterNetworkUser(data['retweeted_status']) |
|
|
|
|
self.id = data['retweeted_status']['id'] |
|
|
|
|
|
|
|
|
|
# also switch the text for the original text. |
|
|
|
@ -393,13 +398,13 @@ class Connection(NetworkBase):
|
|
|
|
|
def link(self, message): |
|
|
|
|
"""Return a link directly to the message.""" |
|
|
|
|
assert(isinstance(message, NetworkData)) |
|
|
|
|
return 'http://twitter.com/%s/status/%s' % (message.username, |
|
|
|
|
return 'http://twitter.com/%s/status/%s' % (message.author.username, |
|
|
|
|
message.id) |
|
|
|
|
|
|
|
|
|
def reply_prefix(self, message): |
|
|
|
|
"""Returns the prefix needed for a reply.""" |
|
|
|
|
assert(isinstance(message, NetworkData)) |
|
|
|
|
return '@' + message.username + ' ' |
|
|
|
|
return '@' + message.author.username + ' ' |
|
|
|
|
|
|
|
|
|
def replies(self): |
|
|
|
|
"""Return a list of NetworkData objects for the replies for the user |
|
|
|
@ -434,8 +439,8 @@ class Connection(NetworkBase):
|
|
|
|
|
# start with the username of the original user, we add it |
|
|
|
|
# for the user. |
|
|
|
|
|
|
|
|
|
if not status.startswith('@' + reply_to.username): |
|
|
|
|
body['status'] = '@' + reply_to.username + ' ' + \ |
|
|
|
|
if not status.startswith('@' + reply_to.author.username): |
|
|
|
|
body['status'] = '@' + reply_to.author.username + ' ' + \ |
|
|
|
|
status |
|
|
|
|
else: |
|
|
|
|
body['in_reply_to_status_id'] = reply_to |
|
|
|
@ -486,7 +491,8 @@ class Connection(NetworkBase):
|
|
|
|
|
"""Check if the message belongs to the user. If so, returns True; |
|
|
|
|
False otherwise.""" |
|
|
|
|
assert(isinstance(message, NetworkData)) |
|
|
|
|
return (message.username == self._options[self.NAMESPACE]['username']) |
|
|
|
|
return (message.author.username == |
|
|
|
|
self._options[self.NAMESPACE]['username']) |
|
|
|
|
|
|
|
|
|
def can_reply(self, message): |
|
|
|
|
"""Always return True; Twitter allows replying to any messages, |
|
|
|
@ -496,7 +502,7 @@ class Connection(NetworkBase):
|
|
|
|
|
def can_repost(self, message): |
|
|
|
|
"""Twitter ignores retweets from the user.""" |
|
|
|
|
assert(isinstance(message, NetworkData)) |
|
|
|
|
return not (message.username == |
|
|
|
|
return not (message.author.username == |
|
|
|
|
self._options[self.NAMESPACE]['username']) |
|
|
|
|
|
|
|
|
|
def can_favourite(self, message): |
|
|
|
|