#!/usr/bin/python # -*- coding: utf-8 -*- # Mitter, micro-blogging client # 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 . import logging import cmd import mitterlib.ui.console_utils as console_utils import mitterlib.constants import datetime import warnings from mitterlib.network import NetworksNoNetworkSetupError, NetworksError from mitterlib.network.networkbase import NetworkError, \ NetworkPermissionDeniedError namespace = 'cmd' # TODO: rename this var to NAMESPACE (check other files too) _log = logging.getLogger('ui.cmd') def options(options): # no options for this interface return class Interface(cmd.Cmd): """A MH-like interface to Mitter.""" # ----------------------------------------------------------------------- # Commands # ----------------------------------------------------------------------- def do_config(self, line=None): """Setup the networks.""" options = self._connection.settings() console_utils.authorization(options, self._options) return def do_fetch(self, line=None): """Retrieve the list of latest messages.""" try: data = self._connection.messages() except NetworksNoNetworkSetupError: # call the config self.do_config() except NetworkError: print 'Network failure. Try again in a few minutes.' data.reverse() self._messages.extend(data) print '%d new messages, %d total messages now' % (len(data), len(self._messages)) def do_next(self, line=None): """Get the next message in the top of the list. The message is marked as read and removed from the list.""" try: self._current_message = self._messages.pop(0) except IndexError: print 'There are no unread messages.' return console_utils.print_messages(self._current_message, self._connection) return def do_print(self, line=None): """Print the message in the current pointer.""" if self._current_message is None: print 'There is no current message.' return console_utils.print_messages(self._current_message, self._connection) def do_list(self, line=None): """Print a summary of the messages in the list.""" for message in self._messages: long_line = '%s: %s' % (message.username, message.message) if len(long_line) > 75: last_space = long_line.rfind(' ', 0, 76) long_line = long_line[:last_space] + '...' print long_line return def do_reply(self, line): """Make a reply to the current message.""" if self._current_message is None: print 'There is no current message.' return if self._update(line, reply_to=self._current_message): print 'Reply send.' self.lastcmd = None def do_update(self, line): """Update your status.""" if self._update(line): print 'Status updated' self.lastcmd = None # So we don't send the same message if the user pressed enter # again def do_exit(self, line): """Quit the application.""" _log.debug('Exiting application') return True # ----------------------------------------------------------------------- # Helper functions # ----------------------------------------------------------------------- def _update(self, status, reply_to=None): """Send the update to the server.""" try: self._connection.update(status, reply_to=reply_to) except (NetworksError, NetworkError): # TODO: capture the proper exception. # TODO: Also, NetworkError's should never get here. Networks # should catch that (leaving the status kinda messed.) print 'Network error. Try again in a few minutes.' return False except MessageTooLongWarning: print 'Your message is too long. Update NOT send.' return False return True # ----------------------------------------------------------------------- # Methods required by the main Mitter code # ----------------------------------------------------------------------- def __init__(self, connection, options): """Class initialization.""" cmd.Cmd.__init__(self) self._options = options self._last_update = None self._connection = connection self._messages = [] self._current_message = None self.prompt = '> ' return def __call__(self): """Start the interface.""" warnings.simplefilter('error') # Warnings are exceptions self.cmdloop() return