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
200 lines
6.2 KiB
#!/usr/bin/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
|
|
|