#!/usr/bin/env python # -*- coding: utf-8 -*- # Mitter, a Maemo client for Twitter. # Copyright (C) 2007, 2008 Julio Biason, Deepak Sarda # # 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 textwrap import locale import getpass import logging from mitterlib.network.networkbase import NetworkData from mitterlib.network.networkbase import NetworkError from timesince import timesince _log = logging.getLogger('mitterlib.ui.helpers.console_utils') def encode_print(text): """Try to print the text; if we get any UnicodeEncodeError, we print it without encoding.""" try: print text except UnicodeEncodeError: encoding = locale.getdefaultlocale()[1] if not encoding: encoding = 'ascii' print text.encode(encoding, 'replace') return def print_messages(data, connection, show_numbers=False, indent=0): """Print the list of messages.""" count = 0 # the wrapping thing indent_text = ' ' * (indent * 3) wrapper = textwrap.TextWrapper() wrapper.initial_indent = indent_text wrapper.subsequent_indent = indent_text if isinstance(data, NetworkData): # If it's a single message, just print it _display_message(wrapper, data, connection, show_numbers, count, indent_text) return elif isinstance(data, str): # If it just text, just print it. _display_text(wrapper, data) return # Twitter sends us the data from the newest to latest, which is not # good for displaying on a console. So we reverse the list. # TODO: Check if this is true for ALL networks. Otherwise, we'll have # problems. data.reverse() print for message in data: count += 1 if isinstance(message, str): _display_text(wrapper, message) else: _display_message(wrapper, message, connection, show_numbers, count, indent_text) return def _display_message(wrapper, message, connection, show_numbers, count, indent_text): """Print a single message (NetworkData).""" display = [] if show_numbers: display.append('%d.' % (count)) if message.username != message.name: display.append('%s (%s):' % (message.username, message.name)) else: display.append('%s:' % (message.username)) display.append(message.message) msg = ' '.join(display) for line in wrapper.wrap(msg): encode_print(line) footer = '(%s ago, in %s [%s])' % (timesince(message.message_time), connection.name(message.network), message.network) for line in wrapper.wrap(footer): encode_print(line) print print def _display_text(wrapper, text): """Print a formated text.""" text = wrapper.wrap(text) for line in text: encode_print(line) return def authorization(options, config): for network in options: namespace = network['name'] network_title = '%s credentials:' % (namespace) print network_title print '-' * len(network_title) for option in network['options']: name = option['name'] try: old_value = config[namespace][name] except KeyError: # not setup yet (so it's not in the config -- it would # probably never happen, since we are adding all options # in the config right from start, but better safe than sorry) old_value = None if old_value: old_value_prompt = ' (%s)' % (old_value) else: old_value_prompt = '' prompt = '%s%s: ' % (option['prompt'], old_value_prompt) if option['type'] == 'str': value = raw_input(prompt) elif option['type'] == 'passwd': value = getpass.getpass(prompt) if value: config[namespace][name] = value print def _thread(thread_list, connection, message_id, network): """Build a conversation thread.""" _log.debug('Requesting message %s.%s' % (message_id, network)) try: message = connection.message(message_id, network) except NetworkError, exc: _log.debug('Network error:') _log.debug(exc) thread_list.insert(0, 'Network error') return thread_list # TODO: Catch a permission denied exception and add a proper message # for it. thread_list.insert(0, message) if message.parent: _log.debug('Following parent %s', message.parent) _thread(thread_list, connection, message.parent, network) return thread_list def fetch_thread(initial_message, connection): """Retrieves a conversation thread, when possible. Returns a list of :obj:`NetworkData` objects, with the initial_message as the last element (so parents are in the top of the list.)""" thread = [initial_message] return _thread(thread, connection, initial_message.parent, initial_message.network) def print_thread(thread_list, connection): """Given a thread created by :func:`fetch_thread`, display the data using the default console functions.""" pos = 0 _log.debug('%d messages in thread', len(thread_list)) for message in thread_list: print_messages(message, connection, show_numbers=False, indent=pos) pos += 1 return def make_retweet(message): """Creates the text for a reweet.""" if not message.message.lower().startswith('rt @'): new_message = 'RT @%s: %s' % (message.username, message.message) else: # if it is a retweet already, keep the original information new_message = message.message return new_message