#!/usr/bin/env 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 warnings import mitterlib.ui.helpers.console_utils as console_utils from mitterlib.network import NetworksNoNetworkSetupError, NetworksError from mitterlib.network.networkbase import NetworkError, MessageTooLongWarning _log = logging.getLogger('ui.cmd') class Interface(cmd.Cmd): """A MH/zork-like interface to Mitter.""" NAMESPACE = 'zork' # ----------------------------------------------------------------------- # 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() return except NetworkError: print 'Network failure. Try again in a few minutes.' return data.reverse() self._messages.extend(data) print '%d new messages, %d total messages now' % (len(data), len(self._messages)) self._show_requests() def do_display(self, line=None): """Display the current message or move the cursor to the next/previous.""" if not line: line = '' # so 'lower()' doesn't fail. line = line.lower() if line == 'current': pass elif line == 'next': if self._cursor + 1 >= len(self._messages): print 'There is no next message.' print return self._cursor += 1 elif line == 'previous': if self._cursor == 0: print 'You are in the top of the list.' print return self._cursor -= 1 else: print 'Display WHAT?' print '("current", "previous" or "next")' return print 'Message %d of %d:' % (self._cursor + 1, len(self._messages)) print message = self._messages[self._cursor] console_utils.print_messages(message, self._connection) return def do_list(self, line=None): """Print a summary of the messages in the list.""" for pos in xrange(len(self._messages)): if pos == self._cursor: indicator = '>' else: indicator = ' ' message = self._messages[pos] long_line = '%s%s: %s' % (indicator, 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.""" message = self._messages[self._cursor] if self._update(line, reply_to=message): print 'Reply send.' self.lastcmd = None def do_say(self, line): """Update your status.""" if self._update(line): print 'Status updated' # clear the message so it's not send if the user press enter # twice. self.lastcmd = None def do_thread(self, line): """Display the conversation thread with the message pointed by the cursor.""" message = self._messages[self._cursor] thread = console_utils.fetch_thread(message, self._connection) console_utils.print_thread(thread, self._connection) self._show_requests() def do_retweet(self, line): """Resends the original message to your followers.""" original_message = self._messages[self._cursor] new_message = console_utils.make_retweet(original_message) return self.do_say(new_message) 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 def _show_requests(self): requests = self._connection.available_requests() available = [] for network in requests: if requests[network] >= 0: # just show information for networks that count that available.append('%d requests in %s' % ( requests[network], self._connection.name(network))) print 'You have %s' % (', '. join(available)) print # ----------------------------------------------------------------------- # 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._cursor = 0 self.prompt = '> ' return def __call__(self): """Start the interface.""" warnings.simplefilter('error') # Warnings are exceptions self.cmdloop() return @classmethod def options(self, options): # no options for this interface return