From c6f6cedab31850d5781a4500405218409fbf1718 Mon Sep 17 00:00:00 2001 From: Julio Biason Date: Mon, 29 Mar 2010 21:41:30 -0300 Subject: [PATCH] reply_prefix(), link(), can_repost(), can_reply(), can_delete() and can_favourite() were removed in favour of a properties in the NetworkData object (since those values wouldn't change for a message.) --- docs/networkbase.rst | 5 ++ mitterlib/network/__init__.py | 36 +-------- mitterlib/network/networkbase.py | 124 +++++++++++++------------------ mitterlib/network/twitter.py | 63 ++++++---------- 4 files changed, 82 insertions(+), 146 deletions(-) diff --git a/docs/networkbase.rst b/docs/networkbase.rst index 1a19be5..8ba3b63 100644 --- a/docs/networkbase.rst +++ b/docs/networkbase.rst @@ -3,6 +3,11 @@ .. automodule:: networkbase +NetworkUser -- Unified information about users +---------------------------------------------- + +.. autoclass:: NetworkUser + NetworkData -- Unified information about messages ------------------------------------------------- diff --git a/mitterlib/network/__init__.py b/mitterlib/network/__init__.py index 73d37ff..b1de9a3 100644 --- a/mitterlib/network/__init__.py +++ b/mitterlib/network/__init__.py @@ -252,12 +252,6 @@ class Networks(object): self._save() return results - def reply_prefix(self, message): - """Return the prefix to be used in the reply for that message.""" - assert(isinstance(message, NetworkData)) - self._proxy() - return self.networks[message.network].reply_prefix(message) - def repost(self, message): """Repost a message in the user's timeline. The network used is the same in the message.""" @@ -304,11 +298,6 @@ class Networks(object): self._save() return data - def link(self, message): - """Returns a link directly to the message.""" - assert(isinstance(message, NetworkData)) - return self.networks[message.network].link(message) - def replies(self, network=None): """Return a list of NetworkData objects for the replies for the user messages.""" @@ -329,27 +318,4 @@ class Networks(object): for shortcut in self._targets(network): requests = self.networks[shortcut].available_requests() result[shortcut] = requests - return result - - def can_delete(self, message): - """Return True if the message can be deleted; False otherwise.""" - assert(isinstance(message, NetworkData)) - return self.networks[message.network].can_delete(message) - - def can_reply(self, message): - """Return True if the message can be replied; False otherwise.""" - assert(isinstance(message, NetworkData)) - return self.networks[message.network].can_reply(message) - - def can_repost(self, message): - """Return True if the message can be resposted; False otherwise.""" - assert(isinstance(message, NetworkData)) - return self.networks[message.network].can_repost(message) - - def can_favourite(self, message): - """Return True if the message can be favourited/unfavourited; False - otherwise.""" - assert(isinstance(message, NetworkData)) - return self.networks[message.network].can_favourite(message) - - # TODO: Function to return a regexp for usernames + return result \ No newline at end of file diff --git a/mitterlib/network/networkbase.py b/mitterlib/network/networkbase.py index b1e73b6..74868e0 100644 --- a/mitterlib/network/networkbase.py +++ b/mitterlib/network/networkbase.py @@ -122,66 +122,71 @@ class NetworkUser(object): class NetworkData(object): - """Provides an uniform way to access information about posts. The - following fields should appear [*]_ [*]_: + """Provides an uniform way to access information about posts.""" - **id** - The message identification. *Optional* + def __init__(self): + self.id = '' + """The message identification. *Optional*""" - **author** - Author of the message. A :class:`NetworkUser` object. + self.author = None + """Author of the message. A :class:`NetworkUser` object. + *Required*""" - **message** - The message. *Required* + self.message = '' + """The message. *Required*""" - **message_time** - Message timestamp (as a datetime object). Defaults to None. *Optional* + self.message_time = None + """Message timestamp (as a datetime object). Defaults to None. + *Optional*""" - **favourite** - Boolean indicating if the message was marked as "favourite" or not. - *Optional* + self.favourite = False + """Boolean indicating if the message was marked as "favourite" or not. + *Optional*""" - **parent** - The parent of this message, in case of a reply. *Optional* + self.parent = None + """The parent of this message, in case of a reply. *Optional*""" - **parent_owner** - Owner of the parent message (in other words, "in reply to".) It will be - a :class:`NetworkUser` object. *Optional* + self.parent_owner = None + """Owner of the parent message (in other words, "in reply to".) + It will be a :class:`NetworkUser` object. *Optional*""" - **reposted_by** - Author of the reposted message. A :class:`NetworkUser` object. - - Some networks will return the original - user in a separate table (Twitter, in this case, returns the original - message with the original user in a "retweeted_status" structure.) In - this case, the network layer must return the original user in *author* - while the friend will be in *reposted_by*. *Optional* + self.reposted_by = None + """Author of the reposted message. A :class:`NetworkUser` object. - **network** - The network id source of the message. Network classes don't need to - worry about this field themselves; :class:`Networks` will set it when - merging information from all networks. *Networks should NEVER fill - this field* + Some networks will return the original + user in a separate table (Twitter, in this case, returns the original + message with the original user in a "retweeted_status" structure.) In + this case, the network layer must return the original user in *author* + while the friend will be in *reposted_by*. *Optional*""" - **protected** - Boolean indicating if the message is protected/private or not. + self.protected = False + """Boolean indicating if the message is protected/private or not.""" - .. [*] Not all fields need to be filled if that would require more than - one network call. - .. [*] Interfaces should be aware that optional fields may not be filled. - """ + self.deletable = False + """Boolean indicating if the message can be deleted.""" + + self.replyable = False + """Boolean indicating if the message can be replied.""" + + self.repostable = False + """Boolean indicating if the message can be reposted.""" + + self.favoritable = False + """Boolean indicating if the message can be favorited.""" + + self.link = None + """Link to the original message.""" + + self.reply_prefix = '' + """Prefix to be used in messages when replying to this message.""" - def __init__(self): - self.id = '' - self.author = None - self.message = '' - self.message_time = None - self.favourite = False - self.parent = None - self.parent_owner = None - self.reposted_by = None self.network = '' - self.protected = False + """The network id source of the message. Network classes don't need to + worry about this field themselves; :class:`Networks` will set it when + merging information from all networks. *Networks should NEVER fill + this field*""" + + return class NetworkBase(object): @@ -250,12 +255,6 @@ class NetworkBase(object): # anyway? return None - def reply_prefix(self, message): - """Return the prefix to be used in case the user requests a reply for - that message. *message* must be a :class:`NetworkData` object. Returns - a string.""" - return '' - def repost(self, message): """Repost a message in your current timeline. *message* must be a valid :class:`NetworkData` object. Must return the id of the new @@ -297,21 +296,4 @@ class NetworkBase(object): """Return the number of requests the user can request before being capped. If such limitation doesn't exist for the network, a negative number should be returned.""" - return -1 - - def can_delete(self, message): - """Return True if the message can be deleted; False otherwise.""" - return False - - def can_reply(self, message): - """Return True if the message can be replied; False otherwise.""" - return False - - def can_repost(self, message): - """Return True if the message can be resposted; False otherwise.""" - return False - - def can_favourite(self, message): - """Return True if the message can be favourited/unfavourited; False - otherwise.""" - return False + return -1 \ No newline at end of file diff --git a/mitterlib/network/twitter.py b/mitterlib/network/twitter.py index 6b74b45..34ef486 100644 --- a/mitterlib/network/twitter.py +++ b/mitterlib/network/twitter.py @@ -118,6 +118,7 @@ class TwitterNetworkUser(NetworkUser): convert twitter user information into a NetworkUser object.""" def __init__(self, data): + super(TwitterNetworkUser, self).__init__() self.name = data['user']['name'] self.username = data['user']['screen_name'] self.avatar = data['user']['profile_image_url'] @@ -127,14 +128,25 @@ class TwitterNetworkData(NetworkData): """A simple wrapper around NetworkData, to make things easier to convert twitter data into a NetworkData object.""" - def __init__(self, data): + def __init__(self, data, logged_user): """Class initialization. Receives a dictionary with a single tweet.""" - NetworkData.__init__(self) + super(TwitterNetworkData, self).__init__() self.id = data['id'] self.author = TwitterNetworkUser(data) self.message_time = _to_datetime(data['created_at']) + self.replyable = True # All messages are replyables + self.favoritable = True # All messages are favoritable + + self.repostable = not (self.author.username == logged_user) + self.deletable = (self.author.username == logged_user) + + self.link = 'http://twitter.com/%s/status/%s' % ( + self.author.username, self.id) + + self.reply_prefx = '@' + self.author.username + ' ' + if 'protected' in data['user']: # twitter protects all messages from a user, not per message. self.protected = data['user']['protected'] @@ -411,18 +423,8 @@ class Connection(NetworkBase): def message(self, message_id): """Retrieves the information of one message.""" response = self._request('/statuses/show/%d.json' % (message_id)) - return TwitterNetworkData(response) - - def link(self, message): - """Return a link directly to the message.""" - assert(isinstance(message, NetworkData)) - 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.author.username + ' ' + return TwitterNetworkData(response, + self._options[self.NAMESPACE]['username']) def replies(self): """Return a list of NetworkData objects for the replies for the user @@ -472,7 +474,8 @@ class Connection(NetworkBase): # too large. # TODO: Some updates return the previous status, not the new one. Not # sure what that means. - return TwitterNetworkData(data) + return TwitterNetworkData(data, + self._options[self.NAMESPACE]['username']) def repost(self, message): """Repost a message.""" @@ -480,7 +483,8 @@ class Connection(NetworkBase): body = urllib.urlencode({'id': message.id}) resource = '/statuses/retweet/%d.json' % (message.id) data = self._request(resource, body=body) - return TwitterNetworkData(data) + return TwitterNetworkData(data, + self._options[self.NAMESPACE]['username']) def favourite(self, message): """Mark a message as favourite.""" @@ -491,7 +495,8 @@ class Connection(NetworkBase): else: resource = '/favorites/destroy/%d.json' % (message.id) data = self._request(resource, body=body) - return TwitterNetworkData(data) + return TwitterNetworkData(data, + self._options[self.NAMESPACE]['username']) def delete_message(self, message): """Delete a message.""" @@ -504,26 +509,4 @@ class Connection(NetworkBase): response = self._request(resource, body=body) _log.debug('Delete response: %s', response) return True # Either we get a response or an exception before we reach - # this. - def can_delete(self, message): - """Check if the message belongs to the user. If so, returns True; - False otherwise.""" - assert(isinstance(message, NetworkData)) - return (message.author.username == - self._options[self.NAMESPACE]['username']) - - def can_reply(self, message): - """Always return True; Twitter allows replying to any messages, - including the ones from the user.""" - return True - - def can_repost(self, message): - """Twitter ignores retweets from the user.""" - assert(isinstance(message, NetworkData)) - return not (message.author.username == - self._options[self.NAMESPACE]['username']) - - def can_favourite(self, message): - """Always return True; Twitter allows favouriting/unfavouriting any - messages.""" - return True + # this. \ No newline at end of file