poezio/src/gui.py

1210 lines
50 KiB
Python
Raw Normal View History

2010-01-10 20:14:17 +00:00
# Copyright 2010 Le Coz Florent <louizatakk@fedoraproject.org>
#
# This file is part of Poezio.
#
# Poezio 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, version 3 of the License.
#
# Poezio 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 Poezio. If not, see <http://www.gnu.org/licenses/>.
2010-01-31 05:33:54 +00:00
from gettext import (bindtextdomain, textdomain, bind_textdomain_codeset,
gettext as _)
2010-06-13 15:40:03 +00:00
from os.path import isfile
2010-01-10 20:14:17 +00:00
2010-06-13 15:40:03 +00:00
from time import sleep
import os
import re
import sys
import shlex
2010-01-31 05:33:54 +00:00
import curses
import webbrowser
from datetime import datetime
import common
import theme
2010-08-31 23:11:02 +00:00
import multiuserchat as muc
2010-01-31 05:33:54 +00:00
from handler import Handler
from config import config
from tab import MucTab, InfoTab, PrivateTab
from window import Window
2010-03-18 19:43:44 +00:00
from user import User
from room import Room
from message import Message
from text_buffer import TextBuffer
from keyboard import read_char
2010-08-31 23:11:02 +00:00
from common import is_jid_the_same, jid_get_domain, jid_get_resource, is_jid
2010-06-13 13:51:02 +00:00
2010-08-05 22:24:23 +00:00
# http://xmpp.org/extensions/xep-0045.html#errorstatus
ERROR_AND_STATUS_CODES = {
'401': _('A password is required'),
'403': _('You are banned from the room'),
'404': _('The room does\'nt exist'),
'405': _('Your are not allowed to create a new room'),
'406': _('A reserved nick must be used'),
'407': _('You are not in the member list'),
'409': _('This nickname is already in use or has been reserved'),
'503': _('The maximum number of users has been reached'),
2010-08-05 22:24:23 +00:00
}
SHOW_NAME = {
'dnd': _('busy'),
'away': _('away'),
'xa': _('not available'),
'chat': _('chatty'),
'': _('available')
}
def doupdate():
curses.doupdate()
2010-01-11 13:28:57 +00:00
2010-01-10 20:14:17 +00:00
class Gui(object):
"""
2010-05-18 13:29:02 +00:00
User interface using ncurses
2010-01-10 20:14:17 +00:00
"""
2010-08-31 23:11:02 +00:00
def __init__(self, xmpp):
self.stdscr = curses.initscr()
self.init_curses(self.stdscr)
self.xmpp = xmpp
self.tabs = [InfoTab(self.stdscr, "lol info")]
# a unique buffer used to store global informations
# that are displayed in almost all tabs, in an
# information window.
self.information_buffer = TextBuffer()
self.information_win_size = 2 # Todo, get this from config
self.ignores = {}
2010-02-11 04:59:58 +00:00
2010-01-13 01:04:30 +00:00
self.commands = {
'help': (self.command_help, '\_o< KOIN KOIN KOIN'),
2010-07-01 21:38:57 +00:00
'join': (self.command_join, _("Usage: /join [room_name][@server][/nick] [password]\nJoin: Join the specified room. You can specify a nickname after a slash (/). If no nickname is specified, you will use the default_nick in the configuration file. You can omit the room name: you will then join the room you\'re looking at (useful if you were kicked). You can also provide a room_name without specifying a server, the server of the room you're currently in will be used. You can also provide a password to join the room.\nExamples:\n/join room@server.tld\n/join room@server.tld/John\n/join room2\n/join /me_again\n/join\n/join room@server.tld/my_nick password\n/join / password")),
'quit': (self.command_quit, _("Usage: /quit\nQuit: Just disconnect from the server and exit poezio.")),
'exit': (self.command_quit, _("Usage: /exit\nExit: Just disconnect from the server and exit poezio.")),
'next': (self.rotate_rooms_right, _("Usage: /next\nNext: Go to the next room.")),
'n': (self.rotate_rooms_right, _("Usage: /n\nN: Go to the next room.")),
'prev': (self.rotate_rooms_left, _("Usage: /prev\nPrev: Go to the previous room.")),
'p': (self.rotate_rooms_left, _("Usage: /p\nP: Go to the previous room.")),
'win': (self.command_win, _("Usage: /win <number>\nWin: Go to the specified room.")),
'w': (self.command_win, _("Usage: /w <number>\nW: Go to the specified room.")),
2010-06-13 16:09:12 +00:00
'ignore': (self.command_ignore, _("Usage: /ignore <nickname> \nIgnore: Ignore a specified nickname.")),
'unignore': (self.command_unignore, _("Usage: /unignore <nickname>\nUnignore: Remove the specified nickname from the ignore list.")),
'part': (self.command_part, _("Usage: /part [message]\n Part: disconnect from a room. You can specify an optional message.")),
'show': (self.command_show, _("Usage: /show <availability> [status]\nShow: Change your availability and (optionaly) your status. The <availability> argument is one of \"avail, available, ok, here, chat, away, afk, dnd, busy, xa\" and the optional [message] argument will be your status message")),
'away': (self.command_away, _("Usage: /away [message]\nAway: Sets your availability to away and (optional) sets your status message. This is equivalent to '/show away [message]'")),
'busy': (self.command_busy, _("Usage: /busy [message]\nBusy: Sets your availability to busy and (optional) sets your status message. This is equivalent to '/show busy [message]'")),
'avail': (self.command_avail, _("Usage: /avail [message]\nAvail: Sets your availability to available and (optional) sets your status message. This is equivalent to '/show available [message]'")),
'available': (self.command_avail, _("Usage: /available [message]\nAvailable: Sets your availability to available and (optional) sets your status message. This is equivalent to '/show available [message]'")),
'bookmark': (self.command_bookmark, _("Usage: /bookmark [roomname][/nick]\nBookmark: Bookmark the specified room (you will then auto-join it on each poezio start). This commands uses the same syntaxe as /join. Type /help join for syntaxe examples. Note that when typing \"/bookmark\" on its own, the room will be bookmarked with the nickname you\'re currently using in this room (instead of default_nick)")),
2010-06-21 08:46:06 +00:00
'unquery': (self.command_unquery, _("Usage: /unquery\nClose the private conversation window")),
'set': (self.command_set, _("Usage: /set <option> [value]\nSet: Sets the value to the option in your configuration file. You can, for example, change your default nickname by doing `/set default_nick toto` or your resource with `/set resource blabla`. You can also set an empty value (nothing) by providing no [value] after <option>.")),
'kick': (self.command_kick, _("Usage: /kick <nick> [reason]\nKick: Kick the user with the specified nickname. You also can give an optional reason.")),
'topic': (self.command_topic, _("Usage: /topic <subject> \nTopic: Change the subject of the room")),
'link': (self.command_link, _("Usage: /link [option] [number]\nLink: Interact with a link in the conversation. Available options are 'open', 'copy'. Open just opens the link in the browser if it's http://, Copy just copy the link in the clipboard. An optional number can be provided, it indicates which link to interact with.")),
'query': (self.command_query, _('Usage: /query <nick> [message]\nQuery: Open a private conversation with <nick>. This nick has to be present in the room you\'re currently in. If you specified a message after the nickname, it will immediately be sent to this user')),
2010-08-05 22:37:55 +00:00
'nick': (self.command_nick, _("Usage: /nick <nickname>\nNick: Change your nickname in the current room")),
'say': (self.command_say, _('Usage: /say <message>\nSay: Just send the message. Useful if you want your message to begin with a "/"')),
'whois': (self.command_whois, _('Usage: /whois <nickname>\nWhois: Request many informations about the user.')),
'theme': (self.command_theme, _('Usage: /theme\nTheme: Reload the theme defined in the config file.')),
'recolor': (self.command_recolor, _('Usage: /recolor\nRecolor: Re-assign a color to all participants of the current room, based on the last time they talked. Use this if the participants currently talking have too many identical colors.')),
2010-01-13 01:04:30 +00:00
}
self.key_func = {
"KEY_PPAGE": self.scroll_page_up,
"KEY_NPAGE": self.scroll_page_down,
2010-01-28 00:55:02 +00:00
"KEY_F(5)": self.rotate_rooms_left,
2010-07-20 10:01:37 +00:00
"^P": self.rotate_rooms_left,
2010-01-28 00:55:02 +00:00
"KEY_F(6)": self.rotate_rooms_right,
"KEY_F(7)": self.shrink_information_win,
"KEY_F(8)": self.grow_information_win,
2010-07-20 10:01:37 +00:00
"^N": self.rotate_rooms_right,
2010-07-08 20:20:43 +00:00
"KEY_RESIZE": self.resize_window,
'^X': self.go_to_important_room,
'^V': self.move_separator,
}
2010-08-31 23:11:02 +00:00
# Add handlers
self.xmpp.add_event_handler("session_start", self.on_connected)
self.xmpp.add_event_handler("groupchat_presence", self.on_groupchat_presence)
self.xmpp.add_event_handler("groupchat_message", self.on_groupchat_message)
self.xmpp.add_event_handler("message", self.on_message)
self.xmpp.add_event_handler("presence", self.on_presence)
self.xmpp.add_event_handler("roster_update", self.on_roster_update)
def grow_information_win(self):
"""
"""
if self.information_win_size == 14:
return
self.information_win_size += 1
for tab in self.tabs:
tab.on_info_win_size_changed(self.information_win_size, self.stdscr)
self.refresh_window()
def shrink_information_win(self):
"""
"""
if self.information_win_size == 0:
return
self.information_win_size -= 1
for tab in self.tabs:
tab.on_info_win_size_changed(self.information_win_size, self.stdscr)
self.refresh_window()
2010-08-31 23:11:02 +00:00
def on_connected(self, event):
"""
Called when we are connected and authenticated
"""
self.information(_("Welcome on Poezio \o/!"))
self.information(_("Your JID is %s") % self.xmpp.fulljid)
if not self.xmpp.anon:
# request the roster
self.xmpp.getRoster()
# send initial presence
self.xmpp.makePresence(pfrom=self.xmpp.jid).send()
2010-08-31 23:11:02 +00:00
rooms = config.get('rooms', '')
if rooms == '' or not isinstance(rooms, str):
return
rooms = rooms.split(':')
for room in rooms:
args = room.split('/')
if args[0] == '':
return
roomname = args[0]
if len(args) == 2:
nick = args[1]
else:
default = os.environ.get('USER') if os.environ.get('USER') else 'poezio'
nick = config.get('default_nick', '')
if nick == '':
nick = default
self.open_new_room(roomname, nick)
muc.join_groupchat(self.xmpp, roomname, nick)
# if not self.xmpp.anon:
2010-08-31 23:11:02 +00:00
# Todo: SEND VCARD
return
if config.get('jid', '') == '': # Don't send the vcard if we're not anonymous
self.vcard_sender.start() # because the user ALREADY has one on the server
def on_groupchat_presence(self, presence):
"""
Triggered whenever a presence stanza is received from a user in a multi-user chat room.
Display the presence on the room window and update the
presence information of the concerned user
"""
from_nick = presence['from'].resource
from_room = presence['from'].bare
2010-09-02 01:49:11 +00:00
room = self.get_room_by_name(from_room)
2010-08-31 23:11:02 +00:00
code = presence.find('{jabber:client}status')
status_codes = set([s.attrib['code'] for s in presence.findall('{http://jabber.org/protocol/muc#user}x/{http://jabber.org/protocol/muc#user}status')])
# Check if it's not an error presence.
if presence['type'] == 'error':
return self.room_error(presence, from_room)
2010-09-02 01:49:11 +00:00
if not room:
2010-08-31 23:11:02 +00:00
return
2010-09-02 00:26:37 +00:00
msg = None
affiliation = presence['muc']['affiliation']
show = presence['show']
status = presence['status']
role = presence['muc']['role']
jid = presence['muc']['jid']
typ = presence['type']
if not room.joined: # user in the room BEFORE us.
# ignore redondant presence message, see bug #1509
if from_nick not in [user.nick for user in room.users]:
new_user = User(from_nick, affiliation, show, status, role)
room.users.append(new_user)
if from_nick == room.own_nick:
2010-09-02 00:26:37 +00:00
room.joined = True
new_user.color = theme.COLOR_OWN_NICK
self.add_message_to_text_buffer(room, _("Your nickname is %s") % (from_nick))
2010-09-02 00:26:37 +00:00
if '170' in status_codes:
self.add_message_to_text_buffer(room, 'Warning: this room is publicly logged')
2010-08-31 23:11:02 +00:00
else:
2010-09-02 00:26:37 +00:00
change_nick = '303' in status_codes
kick = '307' in status_codes and typ == 'unavailable'
user = room.get_user_by_name(from_nick)
# New user
if not user:
self.on_user_join(room, from_nick, affiliation, show, status, role, jid)
# nick change
elif change_nick:
self.on_user_nick_change(room, presence, user, from_nick, from_room)
2010-09-02 00:26:37 +00:00
# kick
elif kick:
2010-09-02 01:16:17 +00:00
self.on_user_kicked(room, presence, user, from_nick)
2010-09-02 00:26:37 +00:00
# user quit
elif typ == 'unavailable':
2010-09-02 01:19:08 +00:00
self.on_user_leave_groupchat(room, user, jid, status, from_nick, from_room)
2010-09-02 00:26:37 +00:00
# status change
else:
2010-09-02 01:22:22 +00:00
self.on_user_change_status(room, user, from_nick, from_room, affiliation, role, show, status)
self.refresh_window()
2010-08-31 23:11:02 +00:00
doupdate()
2010-09-02 00:26:37 +00:00
def on_user_join(self, room, from_nick, affiliation, show, status, role, jid):
"""
When a new user joins a groupchat
"""
room.users.append(User(from_nick, affiliation,
show, status, role))
hide_exit_join = config.get('hide_exit_join', -1)
if hide_exit_join != 0:
if not jid.full:
self.add_message_to_text_buffer(room, _('%(spec)s "[%(nick)s]" joined the room') % {'nick':from_nick.replace('"', '\\"'), 'spec':theme.CHAR_JOIN.replace('"', '\\"')}, colorized=True)
2010-09-02 00:26:37 +00:00
else:
self.add_message_to_text_buffer(room, _('%(spec)s "[%(nick)s]" "(%(jid)s)" joined the room') % {'spec':theme.CHAR_JOIN.replace('"', '\\"'), 'nick':from_nick.replace('"', '\\"'), 'jid':jid.full}, colorized=True)
2010-09-02 00:26:37 +00:00
def on_user_nick_change(self, room, presence, user, from_nick, from_room):
new_nick = presence.find('{http://jabber.org/protocol/muc#user}x/{http://jabber.org/protocol/muc#user}item').attrib['nick']
if user.nick == room.own_nick:
room.own_nick = new_nick
# also change our nick in all private discussion of this room
for _tab in self.tabs:
if isinstance(_tab, PrivateTab) and is_jid_the_same(_tab.get_jid(), room.name):
_tab.own_nick = new_nick
user.change_nick(new_nick)
self.add_message_to_text_buffer(room, _('"[%(old)s]" is now known as "[%(new)s]"') % {'old':from_nick.replace('"', '\\"'), 'new':new_nick.replace('"', '\\"')}, colorized=True)
# rename the private tabs if needed
private_room = self.get_room_by_name('%s/%s' % (from_room, from_nick))
if private_room:
self.add_message_to_text_buffer(private_room, _('"[%(old_nick)s]" is now known as "[%(new_nick)s]"') % {'old_nick':from_nick.replace('"', '\\"'), 'new_nick':new_nick.replace('"', '\\"')}, colorized=True)
new_jid = private_room.name.split('/')[0]+'/'+new_nick
private_room.name = new_jid
2010-09-02 01:16:17 +00:00
def on_user_kicked(self, room, presence, user, from_nick):
"""
When someone is kicked
"""
room.users.remove(user)
by = presence.find('{http://jabber.org/protocol/muc#user}x/{http://jabber.org/protocol/muc#user}item/{http://jabber.org/protocol/muc#user}actor')
from common import debug
debug('KICK: by:%s %s, %s\n' % (presence, by, by.attrib['jid'] if by else by))
2010-09-02 01:16:17 +00:00
reason = presence.find('{http://jabber.org/protocol/muc#user}x/{http://jabber.org/protocol/muc#user}item/{http://jabber.org/protocol/muc#user}reason')
by = by.attrib['jid'] if by is not None else None
2010-09-02 01:16:17 +00:00
reason = reason.text# if reason else ''
if from_nick == room.own_nick: # we are kicked
room.disconnect()
if by:
kick_msg = _('%(spec)s [You] have been kicked by "[%(by)s]"') % {'spec': theme.CHAR_KICK.replace('"', '\\"'), 'by':by}
2010-09-02 01:16:17 +00:00
else:
2010-09-11 04:24:09 +00:00
kick_msg = _('%(spec)s [You] have been kicked.') % {'spec':theme.CHAR_KICK.replace('"', '\\"')}
2010-09-02 01:16:17 +00:00
# try to auto-rejoin
if config.get('autorejoin', 'false') == 'true':
muc.join_groupchat(self.xmpp, room.name, room.own_nick)
else:
if by:
kick_msg = _('%(spec)s "[%(nick)s]" has been kicked by "[%(by)s]"') % {'spec':theme.CHAR_KICK.replace('"', '\\"'), 'nick':from_nick.replace('"', '\\"'), 'by':by.replace('"', '\\"')}
2010-09-02 01:16:17 +00:00
else:
2010-09-11 04:24:09 +00:00
kick_msg = _('%(spec)s "[%(nick)s]" has been kicked') % {'spec':theme.CHAR_KICK, 'nick':from_nick.replace('"', '\\"')}
2010-09-02 01:16:17 +00:00
if reason:
kick_msg += _(' Reason: %(reason)s') % {'reason': reason}
self.add_message_to_text_buffer(room, kick_msg, colorized=True)
2010-09-02 01:16:17 +00:00
2010-09-02 01:19:08 +00:00
def on_user_leave_groupchat(self, room, user, jid, status, from_nick, from_room):
"""
When an user leaves a groupchat
"""
room.users.remove(user)
hide_exit_join = config.get('hide_exit_join', -1) if config.get('hide_exit_join', -1) >= -1 else -1
if hide_exit_join == -1 or user.has_talked_since(hide_exit_join):
if not jid.full:
2010-09-11 04:24:09 +00:00
leave_msg = _('%(spec)s "[%(nick)s]" has left the room') % {'nick':from_nick.replace('"', '\\"'), 'spec':theme.CHAR_QUIT.replace('"', '\\"')}
2010-09-02 01:19:08 +00:00
else:
leave_msg = _('%(spec)s "[%(nick)s]" (%(jid)s) has left the room') % {'spec':theme.CHAR_QUIT.replace('"', '\\"'), 'nick':from_nick.replace('"', '\\"'), 'jid':jid.full.replace('"', '\\"')}
2010-09-02 01:19:08 +00:00
if status:
leave_msg += ' (%s)' % status
self.add_message_to_text_buffer(room, leave_msg, colorized=True)
2010-09-02 01:19:08 +00:00
private_room = self.get_room_by_name('%s/%s' % (from_room, from_nick))
if private_room:
if not status:
self.add_message_to_text_buffer(private_room, _('%(spec)s "[%(nick)s]" has left the room') % {'nick':from_nick.replace('"', '\\"'), 'spec':theme.CHAR_QUIT.replace('"', '\\"')}, colorized=True)
2010-09-02 01:19:08 +00:00
else:
self.add_message_to_text_buffer(private_room, _('%(spec)s "[%(nick)s]" has left the room "(%(status)s)"') % {'nick':from_nick.replace('"', '\\"'), 'spec':theme.CHAR_QUIT, 'status': status.replace('"', '\\"')}, colorized=True)
2010-09-02 01:19:08 +00:00
2010-09-02 01:22:22 +00:00
def on_user_change_status(self, room, user, from_nick, from_room, affiliation, role, show, status):
"""
When an user changes her status
"""
# build the message
msg = _('"%s" changed: ')% from_nick.replace('"', '\\"')
2010-09-02 01:22:22 +00:00
if affiliation != user.affiliation:
msg += _('affiliation: %s, ') % affiliation
2010-09-02 01:22:22 +00:00
if role != user.role:
msg += _('role: %s, ') % role
if show != user.show and show in list(SHOW_NAME.keys()):
msg += _('show: %s, ') % SHOW_NAME[show]
2010-09-02 01:22:22 +00:00
if status != user.status:
msg += _('status: %s, ') % status
msg = msg[:-2] # remove the last ", "
2010-09-02 01:22:22 +00:00
hide_status_change = config.get('hide_status_change', -1) if config.get('hide_status_change', -1) >= -1 else -1
if (hide_status_change == -1 or \
user.has_talked_since(hide_status_change) or\
user.nick == room.own_nick)\
and\
(affiliation != user.affiliation or\
role != user.role or\
show != user.show or\
status != user.status):
# display the message in the room
self.add_message_to_text_buffer(room, msg, colorized=True)
2010-09-02 01:22:22 +00:00
private_room = self.get_room_by_name('%s/%s' % (from_room, from_nick))
if private_room: # display the message in private
self.add_message_to_text_buffer(private_room, msg)
2010-09-02 01:22:22 +00:00
# finally, effectively change the user status
user.update(affiliation, show, status, role)
2010-08-31 23:11:02 +00:00
def on_message(self, message):
"""
When receiving private message from a muc OR a normal message
(from one of our contacts)
"""
if message['type'] == 'groupchat':
return None
# Differentiate both type of messages, and call the appropriate handler.
jid_from = message['from']
for tab in self.tabs:
if isinstance(tab, MucTab) and tab.get_name() == jid_from.bare: # check all the MUC we are in
if message['type'] == 'error':
return self.room_error(message, tab.get_room().name)
else:
return self.on_groupchat_private_message(message)
2010-08-31 23:11:02 +00:00
return self.on_normal_message(message)
def on_groupchat_private_message(self, message):
"""
We received a Private Message (from someone in a Muc)
"""
from common import debug
debug('PRIVATE: %s\n' % message)
2010-08-31 23:11:02 +00:00
jid = message['from']
nick_from = jid.resource
room_from = jid.bare
2010-08-31 23:11:02 +00:00
room = self.get_room_by_name(jid.full) # get the tab with the private conversation
if not room: # It's the first message we receive: create the tab
room = self.open_private_window(room_from, nick_from, False)
2010-08-31 23:11:02 +00:00
if not room:
return
body = message['body']
self.add_message_to_text_buffer(room, body, None, nick_from)
self.refresh_window()
2010-08-31 23:11:02 +00:00
doupdate()
def on_normal_message(self, message):
"""
When receiving "normal" messages (from someone in our roster)
"""
from common import debug
debug('MESSAGE: %s\n' % (message))
return
def on_presence(self, presence):
"""
"""
from common import debug
debug('Presence: %s\n' % (presence))
2010-08-31 23:11:02 +00:00
return
def on_roster_update(self, iq):
"""
A subscription changed, or we received a roster item
after a roster request, etc
"""
from common import debug
debug("ROSTER UPDATE: %s\n" % (iq))
for subscriber in iq['roster']['items']:
debug("subscriber: %s\n" % (iq['roster']['items'][subscriber]['subscription']))
2010-07-08 20:20:43 +00:00
def resize_window(self):
"""
Resize the whole screen
"""
for tab in self.tabs:
tab.resize(self.stdscr)
self.refresh_window()
2010-07-08 20:20:43 +00:00
2010-08-31 23:11:02 +00:00
def main_loop(self):
2010-05-18 13:29:02 +00:00
"""
main loop waiting for the user to press a key
"""
self.refresh_window()
while True:
doupdate()
2010-08-31 23:11:02 +00:00
char=read_char(self.stdscr)
# search for keyboard shortcut
if char in list(self.key_func.keys()):
self.key_func[char]()
else:
self.do_command(char)
def current_tab(self):
2010-05-18 13:29:02 +00:00
"""
returns the current room, the one we are viewing
"""
return self.tabs[0]
2010-01-26 17:10:37 +00:00
def get_room_by_name(self, name):
2010-05-18 13:29:02 +00:00
"""
returns the room that has this name
"""
for tab in self.tabs:
if (isinstance(tab, MucTab) or
isinstance(tab, PrivateTab)) and tab.get_name() == name:
return tab.get_room()
2010-05-18 13:29:02 +00:00
return None
2010-01-26 17:10:37 +00:00
def init_curses(self, stdscr):
2010-05-18 13:29:02 +00:00
"""
ncurses initialization
"""
theme.init_colors()
curses.noecho()
curses.curs_set(0)
stdscr.keypad(True)
2010-01-26 17:10:37 +00:00
def reset_curses(self):
2010-05-18 13:29:02 +00:00
"""
Reset terminal capabilities to what they were before ncurses
init
"""
curses.echo()
2010-02-14 04:18:34 +00:00
curses.nocbreak()
curses.endwin()
2010-01-26 17:10:37 +00:00
def refresh_window(self):
"""
Refresh everything
"""
self.current_tab().set_color_state(theme.COLOR_TAB_CURRENT)
self.current_tab().refresh(self.tabs, self.information_buffer)
2010-08-31 23:11:02 +00:00
def open_new_room(self, room, nick, focus=True):
2010-05-18 13:29:02 +00:00
"""
Open a new MucTab containing a muc Room, using the specified nick
2010-05-18 13:29:02 +00:00
"""
r = Room(room, nick)
new_tab = MucTab(self.stdscr, r, self.information_win_size)
if self.current_tab().nb == 0:
self.tabs.append(new_tab)
2010-02-11 04:59:58 +00:00
else:
for ta in self.tabs:
if ta.nb == 0:
self.tabs.insert(self.tabs.index(ta), new_tab)
2010-02-11 04:59:58 +00:00
break
2010-08-31 23:11:02 +00:00
if focus:
self.command_win("%s" % new_tab.nb)
self.refresh_window()
def go_to_important_room(self):
"""
Go to the next room with activity, in this order:
- A personal conversation with a new message
- A Muc with an highlight
- A Muc with any new message
"""
for tab in self.tabs:
if tab.get_color_state() == theme.COLOR_TAB_PRIVATE:
self.command_win('%s' % tab.nb)
return
for tab in self.tabs:
if tab.get_color_state() == theme.COLOR_TAB_HIGHLIGHT:
self.command_win('%s' % tab.nb)
return
for tab in self.tabs:
if tab.get_color_state() == theme.COLOR_TAB_NEW_MESSAGE:
self.command_win('%s' % tab.nb)
return
2010-02-11 04:59:58 +00:00
def rotate_rooms_right(self, args=None):
2010-05-18 13:29:02 +00:00
"""
rotate the rooms list to the right
"""
self.current_tab().on_lose_focus()
self.tabs.append(self.tabs.pop(0))
self.current_tab().on_gain_focus()
self.refresh_window()
2010-02-11 04:59:58 +00:00
def rotate_rooms_left(self, args=None):
2010-05-18 13:29:02 +00:00
"""
rotate the rooms list to the right
"""
self.current_tab().on_lose_focus()
self.tabs.insert(0, self.tabs.pop())
self.current_tab().on_gain_focus()
self.refresh_window()
def scroll_page_down(self, args=None):
self.current_tab().on_scroll_down()
self.refresh_window()
def scroll_page_up(self, args=None):
self.current_tab().on_scroll_up()
self.refresh_window()
2010-08-31 23:11:02 +00:00
def room_error(self, error, room_name):
2010-05-18 13:29:02 +00:00
"""
Display the error on the room window
"""
2010-08-31 23:11:02 +00:00
room = self.get_room_by_name(room_name)
msg = error['error']['type']
condition = error['error']['condition']
code = error['error']['code']
body = error['error']['text']
if not body:
if code in list(ERROR_AND_STATUS_CODES.keys()):
2010-08-05 22:24:51 +00:00
body = ERROR_AND_STATUS_CODES[code]
else:
2010-08-31 23:11:02 +00:00
body = condition or _('Unknown error')
if code:
msg = _('Error: %(code)s - %(msg)s: %(body)s') % {'msg':msg, 'body':body, 'code':code}
self.add_message_to_text_buffer(room, msg)
2010-08-31 23:11:02 +00:00
else:
msg = _('Error: %(msg)s: %(body)s') % {'msg':msg, 'body':body}
self.add_message_to_text_buffer(room, msg)
if code == '401':
msg = _('To provide a password in order to join the room, type "/join / password" (replace "password" by the real password)')
self.add_message_to_text_buffer(room, msg)
2010-08-05 22:24:23 +00:00
if code == '409':
2010-08-07 00:57:36 +00:00
if config.get('alternative_nickname', '') != '':
self.command_join('%s/%s'% (room.name, room.own_nick+config.get('alternative_nickname', '')))
else:
self.add_message_to_text_buffer(room, _('You can join the room with an other nick, by typing "/join /other_nick"'))
self.refresh_window()
2010-06-13 13:51:02 +00:00
def open_private_window(self, room_name, user_nick, focus=True):
complete_jid = room_name+'/'+user_nick
for tab in self.tabs: # if the room exists, focus it and return
if isinstance(tab, PrivateTab):
if tab.get_name() == complete_jid:
self.command_win('%s' % tab.nb)
2010-06-13 13:51:02 +00:00
return
# create the new tab
room = self.get_room_by_name(room_name)
2010-07-19 19:38:33 +00:00
if not room:
return None
own_nick = room.own_nick
r = Room(complete_jid, own_nick) # PrivateRoom here
new_tab = PrivateTab(self.stdscr, r, self.information_win_size)
2010-06-13 13:51:02 +00:00
# insert it in the rooms
if self.current_tab().nb == 0:
self.tabs.append(new_tab)
2010-06-13 13:51:02 +00:00
else:
for ta in self.tabs:
if ta.nb == 0:
self.tabs.insert(self.tabs.index(ta), new_tab)
2010-06-13 13:51:02 +00:00
break
if focus: # focus the room if needed
self.command_win('%s' % (new_tab.nb))
2010-06-13 13:51:02 +00:00
# self.window.new_room(r)
self.refresh_window()
2010-06-13 13:51:02 +00:00
return r
2010-08-31 23:11:02 +00:00
def on_groupchat_message(self, message):
2010-05-18 13:29:02 +00:00
"""
2010-08-31 23:11:02 +00:00
Triggered whenever a message is received from a multi-user chat room.
2010-05-18 13:29:02 +00:00
"""
2010-09-10 21:51:13 +00:00
from common import debug
# debug('GROUPCHAT message: %s\n' % message)
2010-08-31 23:11:02 +00:00
delay_tag = message.find('{urn:xmpp:delay}delay')
if delay_tag is not None:
delayed = True
2010-08-31 23:11:02 +00:00
date = common.datetime_tuple(delay_tag.attrib['stamp'])
else:
# We support the OLD and deprecated XEP: http://xmpp.org/extensions/xep-0091.html
# But it sucks, please, Jabber servers, don't do this :(
2010-08-31 23:11:02 +00:00
delay_tag = message.find('{jabber:x:delay}x')
if delay_tag is not None:
delayed = True
2010-08-31 23:11:02 +00:00
date = common.datetime_tuple(delay_tag.attrib['stamp'])
else:
delayed = False
2010-08-31 23:11:02 +00:00
date = None
nick_from = message['mucnick']
2010-08-31 23:11:02 +00:00
room_from = message.getMucroom()
if message['type'] == 'error': # Check if it's an error
return self.room_error(message, from_room)
if nick_from == room_from:
nick_from = None
2010-09-02 01:49:11 +00:00
room = self.get_room_by_name(room_from)
if (room_from in self.ignores) and (nick_from in self.ignores[room_from]):
return
2010-03-18 19:43:44 +00:00
room = self.get_room_by_name(room_from)
2010-08-31 23:11:02 +00:00
if not room:
self.information(_("message received for a non-existing room: %s") % (room_from))
2010-01-28 00:55:02 +00:00
return
body = message['body']
subject = message['subject']
2010-09-10 21:51:13 +00:00
# debug('======== %s, %s, %s, %s====\n'% (nick_from, room_from, body, subject))
2010-02-14 04:30:04 +00:00
if subject:
2010-02-14 04:41:14 +00:00
if nick_from:
self.add_message_to_text_buffer(room, _("%(nick)s changed the subject to: %(subject)s") % {'nick':nick_from, 'subject':subject}, time=date)
2010-02-14 04:41:14 +00:00
else:
self.add_message_to_text_buffer(room, _("The subject is: %(subject)s") % {'subject':subject}, time=date)
room.topic = subject.replace('\n', '|')
elif body:
2010-03-18 19:43:44 +00:00
if body.startswith('/me '):
self.add_message_to_text_buffer(room, "* "+nick_from + ' ' + body[4:], date)
2010-02-14 13:33:33 +00:00
else:
date = date if delayed == True else None
self.add_message_to_text_buffer(room, body, date, nick_from)
self.refresh_window()
doupdate()
def add_message_to_text_buffer(self, room, txt, time=None, nickname=None, colorized=False):
2010-03-18 19:43:44 +00:00
"""
Add the message to the room if possible, else, add it to the Info window
(in the Info tab of the info window in the RosterTab)
2010-03-18 19:43:44 +00:00
"""
if not room:
self.information('Error, trying to add a message in no room: %s' % txt)
else:
room.add_message(txt, time, nickname, colorized)
self.refresh_window()
2010-01-13 01:04:30 +00:00
def command_help(self, arg):
2010-05-18 13:29:02 +00:00
"""
/help <command_name>
"""
args = arg.split()
2010-01-30 04:42:29 +00:00
if len(args) == 0:
msg = _('Available commands are: ')
for command in list(self.commands.keys()):
2010-01-30 04:42:29 +00:00
msg += "%s " % command
2010-01-31 05:33:54 +00:00
msg += _("\nType /help <command_name> to know what each command does")
2010-01-30 04:42:29 +00:00
if len(args) == 1:
if args[0] in list(self.commands.keys()):
2010-01-30 04:42:29 +00:00
msg = self.commands[args[0]][1]
else:
2010-01-31 05:33:54 +00:00
msg = _('Unknown command: %s') % args[0]
self.information(msg)
2010-01-30 04:42:29 +00:00
def command_whois(self, arg):
"""
/whois <nickname>
"""
2010-08-31 23:11:02 +00:00
# TODO
return
# check shlex here
try:
args = shlex.split(arg)
except ValueError as error:
return self.information(str(error), _("Error"))
room = self.current_room()
if len(args) != 1:
self.add_message_to_text_buffer(room, _('whois command takes exactly one argument'))
return
# check if current room is a MUC
if room.jid or room.name == 'Info':
return
nickname = args[0]
self.muc.request_vcard(room.name, nickname)
def command_theme(self, arg):
"""
"""
theme.reload_theme()
2010-08-22 14:57:47 +00:00
self.resize_window()
2010-09-11 19:48:28 +00:00
def command_recolor(self, arg):
"""
Re-assign color to the participants of the room
"""
tab = self.current_tab()
if not isinstance(tab, MucTab):
2010-09-11 19:48:28 +00:00
return
room = tab.get_room()
2010-09-11 19:48:28 +00:00
i = 0
compare_users = lambda x: x.last_talked
users = list(room.users)
# search our own user, to remove it from the room
for user in users:
if user.nick == room.own_nick:
users.remove(user)
nb_color = len(theme.LIST_COLOR_NICKNAMES)
for user in sorted(users, key=compare_users, reverse=True):
user.color = theme.LIST_COLOR_NICKNAMES[i % nb_color]
i+= 1
self.refresh_window()
def command_win(self, arg):
2010-05-18 13:29:02 +00:00
"""
/win <number>
"""
args = arg.split()
2010-02-12 02:50:07 +00:00
if len(args) != 1:
self.command_help('win')
2010-02-12 02:50:07 +00:00
return
try:
nb = int(args[0])
except ValueError:
self.command_help('win')
2010-02-12 02:50:07 +00:00
return
if self.current_tab().nb == nb:
2010-02-12 02:50:07 +00:00
return
self.current_tab().on_lose_focus()
start = self.current_tab()
self.tabs.append(self.tabs.pop(0))
while self.current_tab().nb != nb:
self.tabs.append(self.tabs.pop(0))
if self.current_tab() == start:
self.current_tab().set_color_state(theme.COLOR_TAB_CURRENT)
self.refresh_window()
2010-02-12 02:50:07 +00:00
return
self.current_tab().on_gain_focus()
self.refresh_window()
2010-02-12 02:50:07 +00:00
def command_kick(self, arg):
2010-05-18 13:29:02 +00:00
"""
/kick <nick> [reason]
"""
try:
args = shlex.split(arg)
except ValueError as error:
return self.information(str(error), _("Error"))
# TODO information message
# return self.add_message_to_text_buffer(self.current_room(), _("Error: %s") % (error))
2010-02-02 23:57:32 +00:00
if len(args) < 1:
self.command_help('kick')
2010-02-02 23:57:32 +00:00
return
nick = args[0]
if len(args) >= 2:
reason = ' '.join(args[1:])
else:
reason = ''
if not isinstance(self.current_tab(), MucTab) or not self.current_tab().get_room().joined:
2010-02-02 23:57:32 +00:00
return
roomname = self.current_tab().get_name()
2010-08-31 23:11:02 +00:00
res = muc.eject_user(self.xmpp, roomname, nick, reason)
if res['type'] == 'error':
self.room_error(res, roomname)
2010-02-02 23:57:32 +00:00
# def command_say(self, arg):
# """
# /say <message>
# """
# line = arg
# if self.current_room().name != 'Info':
# if self.current_room().jid is not None:
# muc.send_private_message(self.xmpp, self.current_room().name, line)
# self.add_message_to_text_buffer(self.current_room(), line, None, self.current_room().own_nick)
# else:
# muc.send_groupchat_message(self.xmpp, self.current_room().name, line)
# self.window.input.refresh()
# doupdate()
2010-08-05 22:37:55 +00:00
def command_join(self, arg):
2010-05-18 13:29:02 +00:00
"""
/join [room][/nick] [password]
"""
args = arg.split()
password = None
2010-01-30 04:02:23 +00:00
if len(args) == 0:
t = self.current_tab()
if not isinstance(t, MucTab) and not isinstance(t, PrivateTab):
2010-01-30 04:02:23 +00:00
return
room = t.get_name()
nick = t.get_room().own_nick
else:
2010-01-30 04:02:23 +00:00
info = args[0].split('/')
if len(info) == 1:
default = os.environ.get('USER') if os.environ.get('USER') else 'poezio'
nick = config.get('default_nick', '')
if nick == '':
nick = default
2010-01-30 04:02:23 +00:00
else:
nick = info[1]
2010-01-31 03:07:30 +00:00
if info[0] == '': # happens with /join /nickname, which is OK
t = self.current_tab()
if not isinstance(t, MucTab):
2010-01-30 04:02:23 +00:00
return
room = t.get_name()
if nick == '':
nick = t.get_room().own_nick
2010-01-30 04:02:23 +00:00
else:
room = info[0]
if not is_jid(room): # no server is provided, like "/join hello"
# use the server of the current room if available
# check if the current room's name has a server
if isinstance(self.current_tab(), MucTab) and\
is_jid(self.current_tab().get_name()):
room += '@%s' % jid_get_domain(self.current_tab().get_name())
else: # no server could be found, print a message and return
# self.add_message_to_text_buffer(self.current_room(), _("You didn't specify a server for the room you want to join"))
# TODO INFO
return
r = self.get_room_by_name(room)
if len(args) == 2: # a password is provided
password = args[1]
# TODO
# if r and r.joined: # if we are already in the room
# self.command_win('%s' % (r.nb))
# return
2010-08-31 23:11:02 +00:00
room = room.lower()
if r and not r.joined:
self.xmpp.plugin['xep_0045'].joinMUC(room, nick, password)
if not r: # if the room window exists, we don't recreate it.
2010-08-31 23:11:02 +00:00
self.open_new_room(room, nick)
self.xmpp.plugin['xep_0045'].joinMUC(room, nick, password)
else:
r.own_nick = nick
r.users = []
2010-01-13 01:04:30 +00:00
def command_bookmark(self, arg):
2010-05-18 13:29:02 +00:00
"""
/bookmark [room][/nick]
"""
args = arg.split()
2010-01-31 03:42:25 +00:00
nick = None
if not isinstance(self.current_tab(), MucTab):
return
2010-01-31 03:42:25 +00:00
if len(args) == 0:
room = self.current_tab().get_room()
roomname = self.current_tab().get_name()
2010-01-31 03:42:25 +00:00
if room.joined:
nick = room.own_nick
else:
info = args[0].split('/')
if len(info) == 2:
nick = info[1]
roomname = info[0]
2010-02-14 04:10:13 +00:00
if roomname == '':
roomname = self.current_tab().get_name()
2010-01-31 03:42:25 +00:00
if nick:
res = roomname+'/'+nick
else:
res = roomname
2010-02-14 04:10:13 +00:00
bookmarked = config.get('rooms', '')
# check if the room is already bookmarked.
# if yes, replace it (i.e., update the associated nick)
bookmarked = bookmarked.split(':')
for room in bookmarked:
if room.split('/')[0] == roomname:
bookmarked.remove(room)
break
bookmarked = ':'.join(bookmarked)
bookmarks = bookmarked+':'+res
config.set_and_save('rooms', bookmarks)
self.information(_('Your bookmarks are now: %s') % bookmarks)
2010-01-31 03:42:25 +00:00
def command_set(self, arg):
2010-05-18 13:29:02 +00:00
"""
/set <option> [value]
"""
args = arg.split()
if len(args) != 2 and len(args) != 1:
self.command_help('set')
2010-02-02 23:35:01 +00:00
return
option = args[0]
if len(args) == 2:
value = args[1]
else:
value = ''
2010-02-10 16:47:43 +00:00
config.set_and_save(option, value)
2010-02-02 23:35:01 +00:00
msg = "%s=%s" % (option, value)
self.information(msg)
2010-02-02 23:35:01 +00:00
def command_show(self, arg):
2010-05-18 13:29:02 +00:00
"""
/show <status> [msg]
"""
args = arg.split()
possible_show = {'avail':None,
'available':None,
'ok':None,
'here':None,
2010-01-31 03:07:30 +00:00
'chat':'chat',
'away':'away',
'afk':'away',
'dnd':'dnd',
'busy':'dnd',
'xa':'xa'
}
if len(args) < 1:
return
if not args[0] in list(possible_show.keys()):
self.command_help('show')
2010-01-31 03:07:30 +00:00
return
show = possible_show[args[0]]
if len(args) > 1:
msg = ' '.join(args[1:])
else:
msg = None
for tab in self.tabs:
if isinstance(tab, MucTab) and tab.get_room().joined:
muc.change_show(self.xmpp, tab.get_room().name, tab.get_room().own_nick, show, msg)
2010-01-31 03:07:30 +00:00
def command_ignore(self, arg):
2010-05-18 13:29:02 +00:00
"""
/ignore <nick>
"""
try:
args = shlex.split(arg)
except ValueError as error:
return self.information(str(error), _("Error"))
2010-05-18 13:29:02 +00:00
if len(args) != 1:
self.command_help('ignore')
return
if not isinstance(self.current_tab(), MucTab):
2010-05-18 13:29:02 +00:00
return
roomname = self.current_tab().get_name()
nick = args[0]
if roomname not in self.ignores:
self.ignores[roomname] = set() # no need for any order
if nick not in self.ignores[roomname]:
self.ignores[roomname].add(nick)
self.information(_("%s is now ignored") % nick, 'info')
else:
self.information(_("%s is alread ignored") % nick, 'info')
2010-05-18 13:29:02 +00:00
def command_unignore(self, arg):
2010-05-18 13:29:02 +00:00
"""
/unignore <nick>
"""
try:
args = shlex.split(arg)
except ValueError as error:
return self.information(str(error), _("Error"))
2010-05-18 13:29:02 +00:00
if len(args) != 1:
self.command_help('unignore')
return
if not isinstance(self.current_tab(), MucTab):
return
roomname = self.current_tab().get_name()
nick = args[0]
if roomname not in self.ignores or (nick not in self.ignores[roomname]):
self.information(_("%s was not ignored") % nick, info)
2010-05-18 13:29:02 +00:00
return
self.ignores[roomname].remove(nick)
if not self.ignores[roomname]:
del self.ignores[roomname]
self.information(_("%s is now unignored") % nick, 'info')
2010-05-18 13:29:02 +00:00
def command_away(self, arg):
2010-05-18 13:29:02 +00:00
"""
/away [msg]
"""
self.command_show("away "+arg)
2010-01-31 03:07:30 +00:00
def command_busy(self, arg):
2010-05-18 13:29:02 +00:00
"""
/busy [msg]
"""
2010-08-05 00:11:11 +00:00
self.command_show("busy "+arg)
2010-01-31 03:07:30 +00:00
def command_avail(self, arg):
2010-05-18 13:29:02 +00:00
"""
/avail [msg]
"""
2010-08-05 00:11:11 +00:00
self.command_show("available "+arg)
2010-01-31 00:25:17 +00:00
def command_part(self, arg):
2010-05-18 13:29:02 +00:00
"""
/part [msg]
"""
args = arg.split()
2010-01-30 04:02:23 +00:00
reason = None
if not isinstance(self.current_tab(), MucTab) and\
not isinstance(self.current_tab(), PrivateTab):
2010-01-30 04:02:23 +00:00
return
room = self.current_tab().get_room()
2010-01-30 04:02:23 +00:00
if len(args):
msg = ' '.join(args)
else:
msg = None
if isinstance(self.current_tab(), MucTab) and\
self.current_tab().get_room().joined:
2010-08-31 23:11:02 +00:00
muc.leave_groupchat(self.xmpp, room.name, room.own_nick, arg)
self.tabs.remove(self.current_tab())
self.refresh_window()
2010-01-30 04:02:23 +00:00
def command_unquery(self, arg):
2010-06-21 08:46:06 +00:00
"""
/unquery
"""
tab = self.current_tab()
if isinstance(tab, PrivateTab):
self.tabs.remove(tab)
self.refresh_window()
2010-06-21 08:46:06 +00:00
def command_query(self, arg):
2010-06-13 16:01:38 +00:00
"""
/query <nick> [message]
2010-06-13 16:01:38 +00:00
"""
try:
args = shlex.split(arg)
except ValueError as error:
return self.information(str(error), _("Error"))
if len(args) < 1 or not isinstance(self.current_tab(), MucTab):
2010-06-13 13:51:02 +00:00
return
nick = args[0]
room = self.current_tab().get_room()
2010-09-10 22:32:31 +00:00
r = None
2010-06-13 13:51:02 +00:00
for user in room.users:
if user.nick == nick:
r = self.open_private_window(room.name, user.nick)
if r and len(args) > 1:
msg = arg[len(nick)+1:]
2010-09-10 22:32:31 +00:00
muc.send_private_message(self.xmpp, r.name, msg)
self.add_message_to_text_buffer(r, msg, None, r.own_nick)
2010-06-13 13:51:02 +00:00
def command_topic(self, arg):
2010-05-18 13:29:02 +00:00
"""
/topic [new topic]
"""
if not isinstance(self.current_tab(), MucTab):
return
room = self.current_tab().get_room()
if not arg.strip():
self.add_message_to_text_buffer(room, _("The subject of the room is: %s") % room.topic)
return
subject = arg
2010-08-31 23:11:02 +00:00
muc.change_subject(self.xmpp, room.name, subject)
2010-03-19 03:37:34 +00:00
def command_link(self, arg):
"""
/link <option> <nb>
Opens the link in a browser, or join the room, or add the JID, or
copy it in the clipboard
"""
if not isinstance(self.current_tab(), MucTab) and\
not isinstance(self.current_tab(), PrivateTab):
return
args = arg.split()
if len(args) > 2:
# INFO
# self.add_message_to_text_buffer(self.current_room(),
# _("Link: This command takes at most 2 arguments"))
return
# set the default parameters
option = "open"
nb = 0
# check the provided parameters
if len(args) >= 1:
try: # check if the argument is the number
nb = int(args[0])
except ValueError: # nope, it's the option
option = args[0]
if len(args) == 2:
try:
nb = int(args[0])
except ValueError:
# INFO
# self.add_message_to_text_buffer(self.current_room(),
# _("Link: 2nd parameter should be a number"))
return
# find the nb-th link in the current buffer
i = 0
link = None
for msg in self.current_tab().get_room().messages[:-200:-1]:
if not msg:
continue
matches = re.findall('"((ftp|http|https|gopher|mailto|news|nntp|telnet|wais|file|prospero|aim|webcal):(([A-Za-z0-9$_.+!*(),;/?:@&~=-])|%[A-Fa-f0-9]{2}){2,}(#([a-zA-Z0-9][a-zA-Z0-9$_.+!*(),;/?:@&~=%-]*))?([A-Za-z0-9$_+!*();/?:~-]))"', msg.txt)
for m in matches:
if i == nb:
url = m[0]
self.link_open(url)
return
def url_open(self, url):
"""
Use webbrowser to open the provided link
"""
webbrowser.open(url)
def move_separator(self):
"""
Move the new-messages separator at the bottom on the current
text.
"""
try:
room = self.current_tab().get_room()
except:
return
room.remove_line_separator()
room.add_line_separator()
self.refresh_window()
def command_nick(self, arg):
2010-05-18 13:29:02 +00:00
"""
/nick <nickname>
"""
try:
args = shlex.split(arg)
except ValueError as error:
return self.information(str(error), _("Error"))
if not isinstance(self.current_tab(), MucTab):
return
2010-01-30 03:06:38 +00:00
if len(args) != 1:
return
nick = args[0]
room = self.current_tab().get_room()
2010-01-30 03:06:38 +00:00
if not room.joined or room.name == "Info":
return
2010-08-31 23:11:02 +00:00
muc.change_nick(self.xmpp, room.name, nick)
2010-01-30 03:06:38 +00:00
def information(self, msg, typ=''):
2010-05-18 13:29:02 +00:00
"""
Displays an informational message in the "Info" room window
"""
self.information_buffer.add_message(msg, nickname=typ)
self.refresh_window()
2010-01-28 00:55:02 +00:00
def command_quit(self, arg):
2010-05-18 13:29:02 +00:00
"""
/quit
"""
if len(arg.strip()) != 0:
msg = arg
2010-06-13 15:40:03 +00:00
else:
msg = None
for tab in self.tabs:
if isinstance(tab, MucTab):
muc.leave_groupchat(self.xmpp, tab.get_room().name, tab.get_room().own_nick, msg)
2010-08-31 23:11:02 +00:00
self.xmpp.disconnect()
self.reset_curses()
2010-01-13 01:04:30 +00:00
sys.exit()
def do_command(self, key):
if not key:
return
from common import debug
debug('do_command, %s, %s\n' % (key, self.current_tab()))
res = self.current_tab().on_input(key)
debug('apres, %s\n' % (res))
if key in ('^J', '\n'):
self.execute(res)
def execute(self,line):
"""
Execute the /command or just send the line on the current room
"""
if line == "":
return
if line.startswith('/') and not line.startswith('/me '):
command = line.strip()[:].split()[0][1:]
arg = line[2+len(command):] # jump the '/' and the ' '
# example. on "/link 0 open", command = "link" and arg = "0 open"
if command in list(self.commands.keys()):
func = self.commands[command][0]
func(arg)
return
else:
self.information(_("unknown command (%s)") % (command), _('Error'))
else:
self.command_say(line)
def command_say(self, line):
if isinstance(self.current_tab(), PrivateTab):
muc.send_private_message(self.xmpp, self.current_tab().get_name(), line)
self.add_message_to_text_buffer(self.current_tab().get_room(), line, None, self.current_tab().get_room().own_nick)
elif isinstance(self.current_tab(), MucTab):
muc.send_groupchat_message(self.xmpp, self.current_tab().get_name(), line)
doupdate()