#!/usr/bin/python # -*- coding: utf-8 -*- # Mitter, a client for Twitter. # Copyright (C) 2007, 2008 The Mitter Contributors # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . """ .. moduleauthor:: Julio Biason The :mod:`networkbase` module defines the base classes for all networks. """ import logging import datetime from mitterlib.constants import version # logging _log = logging.getLogger('mitterlib.network.Network') def auth_options(namespace, options, auths): """Convert the auth fields into options for the command line.""" for option in auths: options.add_option(group=namespace, option=option['name'], default=None, help=option['help'], *(option['flags'])) #-------------------------------------------------------------------- # Exceptions #-------------------------------------------------------------------- class NetworkError(Exception): """Base class for all network related exceptions.""" pass class NetworkUnknownError(NetworkError): """Some non-expected error occurred.""" pass class NetworkLimitExceededError(NetworkError): """The number of requests available was exceeded.""" pass class NetworkDNSError(NetworkError): """A DNS failure prevented the request to continue.""" pass class NetworkInvalidResponseError(NetworkError): """The server returned the information in an unexpected way.""" pass class NetworkLowLevelError(NetworkError): """A low level error occurred in the network layer.""" pass class NetworkBadStatusLineError(NetworkError): """Bad status line exception.""" pass class NetworkAuthorizationFailError(NetworkError): """Authorization failure.""" pass class NetworkPermissionDeniedError(NetworkError): """Permission denied when accessing the message/list.""" pass #-------------------------------------------------------------------- # Warnings #-------------------------------------------------------------------- class NetworkWarning(Warning): """Base warning for networks.""" pass class MessageTooLongWarning(NetworkWarning): """The message is too long for the network.""" pass #-------------------------------------------------------------------- # The classes #-------------------------------------------------------------------- class NetworkData(object): """Provides an uniform way to access information about posts. The following fields should appear: **id** The message identification. **name** The name to be displayed as author of the message. **username** The message author username in the network. **avatar** URL to the author avatar. **message** The message. **message_time** Message timestamp (as a datetime object). Defaults to None. **parent** The parent of this message, in case of a reply. **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. """ def __init__(self): self.id = '' self.name = '' self.username = '' self.avatar = '' self.message = '' self.message_time = None self.parent = '' self.network = '' class NetworkBase(object): """Base class for all networks.""" _user_agent = 'Mitter %s' % (version) # TODO: We'll probably need a ICON attribute in the future. #: Namespace of the network, used to identify options. NAMESPACE = 'Meta' AUTH = [] """List of fields the interface must request to the user in order to retrieve information from the network. It's a list of dictionaries, containing: * *name*: Name of the option, used in ConfigOpt (for the name in the config file and to access it through the options variable); * *flags*: The list of command line options for this option (as in OptParse); * *prompt*: The prompt to be used by interfaces when requesting the variable; * *help*: Description for the value; it's used by ConfigOpt to show the description of the paramater in the command line options and can be used by interfaces to show tooltips about the field; * *type*: The type of the option; valid values are: * 'str': A string; * 'passwd': Password; string, but interfaces should hide the information if possible. """ def is_setup(self): """Should return a boolean indicating if the network have all necessary options set up so it can retrieve information. :class:`Networks` won't send requests to networks that return False to this function.""" return False def messages(self): """Return a list of :class:`NetworkData` objects for the main "timeline" (the default list presented to the user.)""" return [] def update(self, status, reply_to=None): """Update the user status. *status* should be the string with the status update; *reply_to* should be used in case the message is a reply to another message, it could be a simple id or the :class:`NetworkData` object of the original data. Must return the id for the new status.""" return None def delete_message(self, message): """Delete an update. Must return True if the message was deleted or False if not. *message* can be either an id or a :class:`NetworkData` object with the information about the message to be deleted.""" return False def message(self, message_id): """Return a single :class:`NetworkData` object for a specified message.""" return None def replies(self): """Return a list of :class:`NetworkData` objects for the replies for the user messages.""" return [] def available_requests(self): """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