A micro-blogging tool with multiple interfaces.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

200 lines
6.2 KiB

#!/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 <http://www.gnu.org/licenses/>.
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