2011-01-01 13:27:07 +00:00
# Copyright 2010-2011 Le Coz Florent <louiz@louiz.org>
2010-01-10 20:14:17 +00:00
#
# 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/>.
2011-03-07 19:11:47 +00:00
from gettext import gettext as _
2010-01-10 20:14:17 +00:00
2010-06-13 15:40:03 +00:00
from time import sleep
2010-06-30 09:56:03 +00:00
import os
2010-08-02 19:22:41 +00:00
import re
2010-09-11 04:07:04 +00:00
import sys
2010-01-31 05:33:54 +00:00
import curses
2010-10-05 00:14:13 +00:00
import threading
2010-12-26 20:51:14 +00:00
import traceback
2010-08-02 19:22:41 +00:00
2010-01-21 01:54:50 +00:00
from datetime import datetime
2010-03-19 03:30:51 +00:00
import common
2010-08-20 20:55:42 +00:00
import theme
2010-11-09 22:41:31 +00:00
import logging
2011-03-05 20:42:56 +00:00
import singleton
2010-11-09 22:41:31 +00:00
2010-11-25 03:04:03 +00:00
from sleekxmpp . xmlstream . stanzabase import JID
2010-11-09 22:41:31 +00:00
log = logging . getLogger ( __name__ )
2010-01-21 01:54:50 +00:00
2010-08-31 23:11:02 +00:00
import multiuserchat as muc
2010-12-07 16:20:30 +00:00
import tabs
2010-12-15 15:40:43 +00:00
import windows
2011-03-05 20:42:56 +00:00
import connection
2010-12-07 16:20:30 +00:00
2011-01-21 03:46:21 +00:00
from data_forms import DataFormsTab
2010-01-30 02:50:24 +00:00
from config import config
2010-11-15 11:59:09 +00:00
from logger import logger
2010-03-18 19:43:44 +00:00
from user import User
from room import Room
2010-10-31 18:57:48 +00:00
from roster import Roster , RosterGroup , roster
2010-10-17 17:27:07 +00:00
from contact import Contact , Resource
2010-09-14 02:11:07 +00:00
from text_buffer import TextBuffer
2010-07-08 19:27:53 +00:00
from keyboard import read_char
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 = {
2010-09-14 02:11:07 +00:00
' 401 ' : _ ( ' A password is required ' ) ,
2011-01-24 16:02:46 +00:00
' 403 ' : _ ( ' Permission denied ' ) ,
2010-09-14 02:11:07 +00:00
' 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
}
2011-02-10 15:08:17 +00:00
possible_show = { ' available ' : None ,
' chat ' : ' chat ' ,
' away ' : ' away ' ,
' afk ' : ' away ' ,
' dnd ' : ' dnd ' ,
' busy ' : ' dnd ' ,
' xa ' : ' xa '
}
2010-10-05 00:14:13 +00:00
resize_lock = threading . Lock ( )
2010-11-09 20:37:39 +00:00
class Core ( object ) :
2010-01-10 20:14:17 +00:00
"""
2010-05-18 13:29:02 +00:00
User interface using ncurses
2010-01-10 20:14:17 +00:00
"""
2011-03-05 20:42:56 +00:00
def __init__ ( self ) :
2010-12-26 20:51:14 +00:00
# All uncaught exception are given to this callback, instead
# of being displayed on the screen and exiting the program.
sys . excepthook = self . on_exception
2010-10-20 23:51:34 +00:00
self . running = True
2011-03-05 20:42:56 +00:00
self . xmpp = singleton . Singleton ( connection . Connection )
2010-12-26 20:51:14 +00:00
# a unique buffer used to store global informations
# that are displayed in almost all tabs, in an
# information window.
2010-12-15 15:40:43 +00:00
self . information_buffer = TextBuffer ( )
2010-12-17 14:36:14 +00:00
self . information_win_size = config . get ( ' info_win_height ' , 2 , ' var ' )
2011-03-08 03:20:46 +00:00
self . information_win = windows . TextWin ( 20 )
self . information_buffer . add_window ( self . information_win )
2011-03-05 20:42:56 +00:00
self . tabs = [ ]
2010-10-05 00:36:43 +00:00
self . previous_tab_nb = 0
2011-01-03 15:07:32 +00:00
self . own_nick = config . get ( ' own_nick ' , ' ' ) or self . xmpp . boundjid . user
2010-11-25 03:04:03 +00:00
# global commands, available from all tabs
# a command is tuple of the form:
# (the function executing the command. Takes a string as argument,
# a string representing the help message,
# a completion function, taking a Input as argument. Can be None)
# The completion function should return True if a completion was
# made ; False otherwise
2010-01-13 01:04:30 +00:00
self . commands = {
2011-02-10 15:13:28 +00:00
' help ' : ( self . command_help , ' \ _o< KOIN KOIN KOIN ' , self . completion_help ) ,
2010-11-25 03:04:03 +00:00
' join ' : ( self . command_join , _ ( " Usage: /join [room_name][@server][/nick] [password] \n Join: 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. \n Examples: \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 " ) , self . completion_join ) ,
' exit ' : ( self . command_quit , _ ( " Usage: /exit \n Exit: Just disconnect from the server and exit poezio. " ) , None ) ,
' next ' : ( self . rotate_rooms_right , _ ( " Usage: /next \n Next: Go to the next room. " ) , None ) ,
' prev ' : ( self . rotate_rooms_left , _ ( " Usage: /prev \n Prev: Go to the previous room. " ) , None ) ,
2011-02-10 15:08:17 +00:00
' win ' : ( self . command_win , _ ( " Usage: /win <number> \n Win: Go to the specified room. " ) , self . completion_win ) ,
' w ' : ( self . command_win , _ ( " Usage: /w <number> \n W: Go to the specified room. " ) , self . completion_win ) ,
2011-03-11 21:10:37 +00:00
' show ' : ( self . command_status , _ ( ' Usage: /show <availability> [status message] \n Show: Sets your availability and (optionaly) your status message. The <availability> argument is one of \" available, chat, away, afk, dnd, busy, xa \" and the optional [status] argument will be your status message. ' ) , self . completion_status ) ,
' status ' : ( self . command_status , _ ( ' Usage: /status <availability> [status message] \n Status: Sets your availability and (optionaly) your status message. The <availability> argument is one of \" available, chat, away, afk, dnd, busy, xa \" and the optional [status] argument will be your status message. ' ) , self . completion_status ) ,
' away ' : ( self . command_away , _ ( " Usage: /away [message] \n Away: Sets your availability to away and (optionaly) your status message. This is equivalent to ' /status away [message] ' " ) , None ) ,
' busy ' : ( self . command_busy , _ ( " Usage: /busy [message] \n Busy: Sets your availability to busy and (optionaly) your status message. This is equivalent to ' /status busy [message] ' " ) , None ) ,
' available ' : ( self . command_avail , _ ( " Usage: /available [message] \n Available: Sets your availability to available and (optionaly) your status message. This is equivalent to ' /status available [message] ' " ) , None ) ,
2010-11-25 03:04:03 +00:00
' bookmark ' : ( self . command_bookmark , _ ( " Usage: /bookmark [roomname][/nick] \n Bookmark: 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) " ) , None ) ,
' set ' : ( self . command_set , _ ( " Usage: /set <option> [value] \n Set: 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>. " ) , None ) ,
' theme ' : ( self . command_theme , _ ( ' Usage: /theme \n Theme: Reload the theme defined in the config file. ' ) , None ) ,
2011-03-11 21:10:37 +00:00
' list ' : ( self . command_list , _ ( ' Usage: /list \n List: get the list of public chatrooms on the specified server ' ) , self . completion_list ) ,
' message ' : ( self . command_message , _ ( ' Usage: /message <jid> [optional message] \n Message: Open a conversation with the specified JID (even if it is not in our roster), and send a message to it, if specified ' ) , None ) ,
2011-03-15 22:40:54 +00:00
' version ' : ( self . command_version , _ ( ' Usage: /version <jid> \n Version: get the software version of the given JID (usually its XMPP client and Operating System) ' ) , None ) ,
2011-03-20 00:46:44 +00:00
' connect ' : ( self . command_reconnect , _ ( ' Usage: /connect \n Connect: disconnect from the remote server if you are currently connected and then connect to it again ' ) , None ) ,
2010-01-13 01:04:30 +00:00
}
2010-01-27 19:46:08 +00:00
self . key_func = {
2010-06-10 01:17:59 +00:00
" 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 ,
2011-02-15 19:44:31 +00:00
" M-[1;6D " : self . rotate_rooms_left ,
2010-07-20 10:01:37 +00:00
" ^P " : self . rotate_rooms_left ,
2010-11-22 01:39:37 +00:00
' kLFT3 ' : self . rotate_rooms_left ,
2010-01-28 00:55:02 +00:00
" KEY_F(6) " : self . rotate_rooms_right ,
2011-02-15 19:44:31 +00:00
" M-[1;6C " : self . rotate_rooms_right ,
2010-11-22 01:39:37 +00:00
" ^N " : self . rotate_rooms_right ,
' kRIT3 ' : self . rotate_rooms_right ,
2010-09-14 02:11:07 +00:00
" KEY_F(7) " : self . shrink_information_win ,
" KEY_F(8) " : self . grow_information_win ,
2010-10-05 00:14:13 +00:00
" KEY_RESIZE " : self . call_for_resize ,
2010-10-27 23:11:35 +00:00
' M-e ' : self . go_to_important_room ,
2010-10-05 00:36:43 +00:00
' M-r ' : self . go_to_roster ,
2010-10-27 23:11:35 +00:00
' M-z ' : self . go_to_previous_tab ,
' M-v ' : self . move_separator ,
2010-12-17 21:06:59 +00:00
' ^L ' : self . full_screen_redraw ,
2011-03-20 02:32:48 +00:00
' M-j ' : self . go_to_room_number ,
2010-01-27 19:46:08 +00:00
}
2010-08-31 23:11:02 +00:00
# Add handlers
2011-01-08 23:20:27 +00:00
self . xmpp . add_event_handler ( ' connected ' , self . on_connected )
self . xmpp . add_event_handler ( ' disconnected ' , self . on_disconnected )
self . xmpp . add_event_handler ( ' failed_auth ' , self . on_failed_auth )
self . xmpp . add_event_handler ( " session_start " , self . on_session_start )
2010-08-31 23:11:02 +00:00
self . xmpp . add_event_handler ( " groupchat_presence " , self . on_groupchat_presence )
self . xmpp . add_event_handler ( " groupchat_message " , self . on_groupchat_message )
2010-11-09 22:41:31 +00:00
self . xmpp . add_event_handler ( " groupchat_subject " , self . on_groupchat_subject )
2010-08-31 23:11:02 +00:00
self . xmpp . add_event_handler ( " message " , self . on_message )
2010-09-26 18:01:38 +00:00
self . xmpp . add_event_handler ( " got_online " , self . on_got_online )
self . xmpp . add_event_handler ( " got_offline " , self . on_got_offline )
2010-09-08 23:00:55 +00:00
self . xmpp . add_event_handler ( " roster_update " , self . on_roster_update )
2010-10-17 17:27:07 +00:00
self . xmpp . add_event_handler ( " changed_status " , self . on_presence )
2011-01-11 05:43:31 +00:00
self . xmpp . add_event_handler ( " changed_subscription " , self . on_changed_subscription )
2011-01-21 03:46:21 +00:00
self . xmpp . add_event_handler ( " message_xform " , self . on_data_form )
2011-02-24 19:02:18 +00:00
self . xmpp . add_event_handler ( " chatstate_active " , self . on_chatstate_active )
self . xmpp . add_event_handler ( " chatstate_composing " , self . on_chatstate_composing )
self . xmpp . add_event_handler ( " chatstate_paused " , self . on_chatstate_paused )
self . xmpp . add_event_handler ( " chatstate_gone " , self . on_chatstate_gone )
self . xmpp . add_event_handler ( " chatstate_inactive " , self . on_chatstate_inactive )
2011-03-05 20:42:56 +00:00
def start ( self ) :
"""
Init curses , create the first tab , etc
"""
self . stdscr = curses . initscr ( )
self . init_curses ( self . stdscr )
2011-03-08 03:20:46 +00:00
# Init the tab's size.
tabs . Tab . resize ( self . stdscr )
# resize the information_win to its initial size
self . resize_global_information_win ( )
2011-03-05 20:42:56 +00:00
default_tab = tabs . InfoTab ( ) if self . xmpp . anon \
else tabs . RosterInfoTab ( )
default_tab . on_gain_focus ( )
self . tabs . append ( default_tab )
2011-01-08 23:20:27 +00:00
self . information ( _ ( ' Welcome to poezio! ' ) )
self . refresh_window ( )
2011-03-08 03:20:46 +00:00
def resize_global_information_win ( self ) :
"""
Resize the global_information_win only once at each resize .
"""
self . information_win . resize ( self . information_win_size , tabs . Tab . width ,
tabs . Tab . height - 2 - self . information_win_size , 0 )
2010-12-26 20:51:14 +00:00
def on_exception ( self , typ , value , trace ) :
"""
2011-03-03 02:43:48 +00:00
When an exception is raised , just reset curses and call
the original exception handler ( will nicely print the traceback )
2010-12-26 20:51:14 +00:00
"""
try :
2011-01-26 04:01:16 +00:00
self . reset_curses ( )
2011-03-03 02:43:48 +00:00
except :
pass
sys . __excepthook__ ( typ , value , trace )
2010-12-26 20:51:14 +00:00
2011-03-05 20:42:56 +00:00
@property
def informations ( self ) :
return self . information_buffer
2010-09-14 02:11:07 +00:00
def grow_information_win ( self ) :
if self . information_win_size == 14 :
return
self . information_win_size + = 1
2011-03-08 03:20:46 +00:00
self . resize_global_information_win ( )
2010-09-14 02:11:07 +00:00
for tab in self . tabs :
2010-11-19 16:27:20 +00:00
tab . on_info_win_size_changed ( )
2010-09-14 02:11:07 +00:00
self . refresh_window ( )
def shrink_information_win ( self ) :
if self . information_win_size == 0 :
return
self . information_win_size - = 1
2011-03-08 03:20:46 +00:00
self . resize_global_information_win ( )
2010-09-14 02:11:07 +00:00
for tab in self . tabs :
2010-11-19 16:27:20 +00:00
tab . on_info_win_size_changed ( )
2010-09-14 02:11:07 +00:00
self . refresh_window ( )
2010-08-31 23:11:02 +00:00
2011-01-21 03:46:21 +00:00
def on_data_form ( self , message ) :
"""
When a data form is received
"""
self . information ( ' %s ' % messsage )
2011-02-24 19:02:18 +00:00
def on_chatstate_active ( self , message ) :
2011-02-24 20:39:49 +00:00
self . on_chatstate ( message , " active " )
2011-02-24 19:02:18 +00:00
def on_chatstate_inactive ( self , message ) :
2011-02-24 20:39:49 +00:00
self . on_chatstate ( message , " inactive " )
2011-02-24 19:02:18 +00:00
def on_chatstate_composing ( self , message ) :
2011-02-24 20:39:49 +00:00
self . on_chatstate ( message , " composing " )
2011-02-24 19:02:18 +00:00
def on_chatstate_paused ( self , message ) :
2011-02-24 20:39:49 +00:00
self . on_chatstate ( message , " paused " )
2011-02-24 19:02:18 +00:00
def on_chatstate_gone ( self , message ) :
2011-02-24 20:39:49 +00:00
self . on_chatstate ( message , " gone " )
def on_chatstate ( self , message , state ) :
2011-02-24 19:02:18 +00:00
if message [ ' type ' ] == ' chat ' :
2011-02-24 20:39:49 +00:00
if not self . on_chatstate_normal_conversation ( message , state ) :
2011-03-05 21:39:35 +00:00
tab = self . get_tab_by_name ( message [ ' from ' ] . full , tabs . PrivateTab )
if not tab :
2011-02-24 20:39:49 +00:00
return
self . on_chatstate_private_conversation ( message , state )
2011-02-24 20:56:16 +00:00
elif message [ ' type ' ] == ' groupchat ' :
self . on_chatstate_groupchat_conversation ( message , state )
2011-02-24 19:02:18 +00:00
2011-03-07 19:11:47 +00:00
def on_chatstate_normal_conversation ( self , message , state ) :
2011-02-24 19:02:18 +00:00
tab = self . get_tab_of_conversation_with_jid ( message [ ' from ' ] , False )
2011-02-24 20:39:49 +00:00
if not tab :
return False
tab . chatstate = state
if tab == self . current_tab ( ) :
self . refresh_window ( )
return True
def on_chatstate_private_conversation ( self , message , state ) :
tab = self . get_tab_by_name ( message [ ' from ' ] . full , tabs . PrivateTab )
2011-02-24 19:02:18 +00:00
if not tab :
return
tab . chatstate = state
2011-02-24 19:31:34 +00:00
if tab == self . current_tab ( ) :
self . refresh_window ( )
2011-02-24 20:39:49 +00:00
return True
2011-02-24 19:02:18 +00:00
2011-02-24 20:56:16 +00:00
def on_chatstate_groupchat_conversation ( self , message , state ) :
nick = message [ ' mucnick ' ]
room_from = message . getMucroom ( )
tab = self . get_tab_by_name ( room_from , tabs . MucTab )
if tab and tab . get_room ( ) and tab . get_room ( ) . get_user_by_name ( nick ) :
tab . get_room ( ) . get_user_by_name ( nick ) . chatstate = state
if tab == self . current_tab ( ) :
self . refresh_window ( )
2011-01-21 03:46:21 +00:00
def open_new_form ( self , form , on_cancel , on_send , * * kwargs ) :
"""
Open a new tab containing the form
The callback are called with the completed form as parameter in
addition with kwargs
"""
2011-03-05 20:42:56 +00:00
form_tab = DataFormsTab ( form , on_cancel , on_send , kwargs )
2011-01-21 03:46:21 +00:00
self . add_tab ( form_tab , True )
2010-09-26 18:01:38 +00:00
def on_got_offline ( self , presence ) :
jid = presence [ ' from ' ]
2010-10-31 18:57:48 +00:00
contact = roster . get_contact_by_jid ( jid . bare )
2010-09-26 18:01:38 +00:00
if not contact :
return
2010-10-17 17:27:07 +00:00
resource = contact . get_resource_by_fulljid ( jid . full )
assert resource
self . information ( ' %s is offline ' % ( resource . get_jid ( ) ) , " Roster " )
2011-01-05 01:41:19 +00:00
# If a resource got offline, display the message in the conversation with this
# precise resource.
2011-01-05 01:46:19 +00:00
self . add_information_message_to_conversation_tab ( jid . full , ' %s is offline ' % ( resource . get_jid ( ) . full ) )
2010-10-17 17:27:07 +00:00
contact . remove_resource ( resource )
2011-01-05 01:41:19 +00:00
# Display the message in the conversation with the bare JID only if that was
# the only resource online (i.e. now the contact is completely disconnected)
if not contact . get_highest_priority_resource ( ) : # No resource left: that was the last one
2011-01-05 01:46:19 +00:00
self . add_information_message_to_conversation_tab ( jid . bare , ' %s is offline ' % ( jid . bare ) )
2011-01-05 02:02:53 +00:00
self . refresh_window ( )
2010-09-26 18:01:38 +00:00
def on_got_online ( self , presence ) :
jid = presence [ ' from ' ]
2010-10-31 18:57:48 +00:00
contact = roster . get_contact_by_jid ( jid . bare )
2010-09-26 18:01:38 +00:00
if not contact :
2010-10-17 17:27:07 +00:00
# Todo, handle presence comming from contacts not in roster
2010-09-26 18:01:38 +00:00
return
2010-10-17 17:27:07 +00:00
resource = contact . get_resource_by_fulljid ( jid . full )
assert not resource
resource = Resource ( jid . full )
2010-09-26 18:01:38 +00:00
status = presence [ ' type ' ]
2010-11-10 21:15:08 +00:00
status_message = presence [ ' status ' ]
2010-10-17 17:27:07 +00:00
priority = presence . getPriority ( ) or 0
2010-11-10 21:15:08 +00:00
resource . set_status ( status_message )
2010-10-17 17:27:07 +00:00
resource . set_presence ( status )
resource . set_priority ( priority )
self . information ( " %s is online ( %s ) " % ( resource . get_jid ( ) . full , status ) , " Roster " )
2011-01-05 01:59:26 +00:00
self . add_information_message_to_conversation_tab ( jid . full , ' %s is online ' % ( jid . full ) )
if not contact . get_highest_priority_resource ( ) :
# No connected resource yet: the user's just connecting
self . add_information_message_to_conversation_tab ( jid . bare , ' %s is online ' % ( jid . bare ) )
contact . add_resource ( resource )
2011-01-05 01:46:19 +00:00
def add_information_message_to_conversation_tab ( self , jid , msg ) :
"""
Search for a ConversationTab with the given jid ( full or bare ) , if yes , add
the given message to it
"""
2011-01-26 22:43:07 +00:00
tab = self . get_tab_by_name ( jid , tabs . ConversationTab )
if tab :
2011-01-05 01:46:19 +00:00
self . add_message_to_text_buffer ( tab . get_room ( ) , msg )
2011-01-08 23:20:27 +00:00
def on_failed_connection ( self ) :
"""
We cannot contact the remote server
"""
self . information ( _ ( " Connection to remote server failed " ) )
def on_disconnected ( self , event ) :
"""
When we are disconnected from remote server
"""
2011-01-10 16:40:07 +00:00
for tab in self . tabs :
if isinstance ( tab , tabs . MucTab ) :
tab . get_room ( ) . disconnect ( )
2011-01-08 23:20:27 +00:00
self . information ( _ ( " Disconnected from server. " ) )
def on_failed_auth ( self , event ) :
"""
Authentication failed
"""
self . information ( _ ( " Authentication failed. " ) )
2010-09-26 18:01:38 +00:00
2010-08-31 23:11:02 +00:00
def on_connected ( self , event ) :
2011-01-08 23:20:27 +00:00
"""
Remote host responded , but we are not yet authenticated
"""
self . information ( _ ( " Connected to server. " ) )
def on_session_start ( self , event ) :
2010-08-31 23:11:02 +00:00
"""
Called when we are connected and authenticated
"""
2011-01-08 23:20:27 +00:00
self . information ( _ ( " Authentication success. " ) )
2010-10-16 18:47:39 +00:00
self . information ( _ ( " Your JID is %s " ) % self . xmpp . boundjid . full )
2010-09-08 23:00:55 +00:00
if not self . xmpp . anon :
# request the roster
self . xmpp . getRoster ( )
# send initial presence
2010-11-10 21:15:08 +00:00
self . xmpp . makePresence ( ) . 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 :
2010-12-07 16:31:30 +00:00
jid = JID ( room )
if jid . bare == ' ' :
2010-08-31 23:11:02 +00:00
return
2010-12-07 16:31:30 +00:00
if jid . resource != ' ' :
nick = jid . resource
2010-08-31 23:11:02 +00:00
else :
default = os . environ . get ( ' USER ' ) if os . environ . get ( ' USER ' ) else ' poezio '
2011-01-26 22:43:07 +00:00
nick = config . get ( ' default_nick ' , ' ' ) or default
tab = self . get_tab_by_name ( jid . bare , tabs . MucTab )
2011-01-10 16:40:07 +00:00
if not tab :
self . open_new_room ( jid . bare , nick , False )
2010-12-07 16:31:30 +00:00
muc . join_groupchat ( self . xmpp , jid . bare , nick )
2010-08-31 23:11:02 +00:00
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_room = presence [ ' from ' ] . bare
2011-03-05 21:39:35 +00:00
tab = self . get_tab_by_name ( from_room , tabs . MucTab )
if tab :
tab . handle_presence ( presence )
2011-01-23 22:01:53 +00:00
2011-03-05 21:39:35 +00:00
def rename_private_tabs ( self , room_name , old_nick , new_nick ) :
2010-09-02 01:16:17 +00:00
"""
2011-03-05 21:39:35 +00:00
Call this method when someone changes his / her nick in a MUC , this updates
the name of all the opened private conversations with him / her
2010-09-02 01:16:17 +00:00
"""
2011-03-05 21:39:35 +00:00
tab = self . get_tab_by_name ( ' %s / %s ' % ( room_name , old_nick ) , tabs . PrivateTab )
if tab :
tab . rename_user ( old_nick , new_nick )
2010-09-02 01:16:17 +00:00
2011-03-05 21:39:35 +00:00
def on_user_left_private_conversation ( self , room_name , nick , status_message ) :
2010-09-02 01:19:08 +00:00
"""
2011-03-05 21:39:35 +00:00
The user left the MUC : add a message in the associated private conversation
2010-09-02 01:19:08 +00:00
"""
2011-03-05 21:39:35 +00:00
tab = self . get_tab_by_name ( ' %s / %s ' % ( room_name , nick ) , tabs . PrivateTab )
if tab :
tab . user_left ( status_message , nick )
2010-09-02 01:19:08 +00:00
2011-03-05 21:39:35 +00:00
def on_user_changed_status_in_private ( self , jid , msg ) :
tab = self . get_tab_by_name ( jid )
if tab : # display the message in private
tab . get_room ( ) . add_message ( msg , colorized = True )
2010-09-02 01:22:22 +00:00
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 ' :
2010-11-11 04:22:37 +00:00
return
2010-08-31 23:11:02 +00:00
# Differentiate both type of messages, and call the appropriate handler.
jid_from = message [ ' from ' ]
2010-09-14 02:11:07 +00:00
for tab in self . tabs :
2010-12-17 14:47:18 +00:00
if tab . get_name ( ) == jid_from . bare and isinstance ( tab , tabs . MucTab ) :
2010-09-08 23:00:55 +00:00
if message [ ' type ' ] == ' error ' :
2010-09-14 02:11:07 +00:00
return self . room_error ( message , tab . get_room ( ) . name )
2010-09-08 23:00:55 +00:00
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 )
"""
jid = message [ ' from ' ]
2010-10-17 05:14:22 +00:00
nick_from = jid . resource
2010-09-02 01:11:21 +00:00
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
2010-09-03 18:01:43 +00:00
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 ' ]
2010-11-24 05:41:06 +00:00
room . add_message ( body , time = None , nickname = nick_from ,
colorized = False ,
forced_user = self . get_room_by_name ( room_from ) . get_user_by_name ( nick_from ) )
2011-02-24 20:39:49 +00:00
conversation = self . get_tab_by_name ( jid . full , tabs . PrivateTab )
2011-02-24 23:38:34 +00:00
if conversation and conversation . remote_wants_chatstates is None :
2011-02-24 20:39:49 +00:00
if message [ ' chat_state ' ] :
conversation . remote_wants_chatstates = True
else :
conversation . remote_wants_chatstates = False
2011-01-12 17:34:04 +00:00
logger . log_message ( jid . full . replace ( ' / ' , ' \\ ' ) , nick_from , body )
2010-09-14 02:11:07 +00:00
self . refresh_window ( )
2010-10-17 05:14:22 +00:00
self . doupdate ( )
2010-08-31 23:11:02 +00:00
2010-09-27 01:40:34 +00:00
def focus_tab_named ( self , tab_name ) :
for tab in self . tabs :
if tab . get_name ( ) == tab_name :
self . command_win ( ' %s ' % ( tab . nb , ) )
2011-02-24 19:02:18 +00:00
def get_tab_of_conversation_with_jid ( self , jid , create = True ) :
2010-08-31 23:11:02 +00:00
"""
2011-02-24 19:02:18 +00:00
From a JID , get the tab containing the conversation with it .
If none already exist , and create is " True " , we create it
and return it . Otherwise , we return None
2010-08-31 23:11:02 +00:00
"""
2010-11-11 04:22:37 +00:00
# We first check if we have a conversation opened with this precise resource
2011-01-26 22:43:07 +00:00
conversation = self . get_tab_by_name ( jid . full , tabs . ConversationTab )
2010-11-11 04:22:37 +00:00
if not conversation :
# If not, we search for a conversation with the bare jid
2011-01-26 22:43:07 +00:00
conversation = self . get_tab_by_name ( jid . bare , tabs . ConversationTab )
2010-11-11 04:22:37 +00:00
if not conversation :
2011-02-24 19:02:18 +00:00
if create :
# We create the conversation with the bare Jid if nothing was found
conversation = self . open_conversation_window ( jid . bare , False )
else :
conversation = None
return conversation
def on_normal_message ( self , message ) :
"""
When receiving " normal " messages ( from someone in our roster )
"""
jid = message [ ' from ' ]
body = message [ ' body ' ]
if not body :
return
conversation = self . get_tab_of_conversation_with_jid ( jid , create = True )
2011-01-03 15:07:32 +00:00
if roster . get_contact_by_jid ( jid . bare ) :
2011-01-05 01:14:30 +00:00
remote_nick = roster . get_contact_by_jid ( jid . bare ) . get_name ( ) or jid . user
2011-01-03 15:07:32 +00:00
else :
2011-01-05 01:14:30 +00:00
remote_nick = jid . user
2011-01-03 15:07:32 +00:00
conversation . get_room ( ) . add_message ( body , None , remote_nick , False , theme . COLOR_REMOTE_USER )
2011-02-24 19:02:18 +00:00
if conversation . remote_wants_chatstates is None :
if message [ ' chat_state ' ] :
conversation . remote_wants_chatstates = True
else :
conversation . remote_wants_chatstates = False
2011-01-12 17:34:04 +00:00
logger . log_message ( jid . bare , remote_nick , body )
2010-11-11 04:22:37 +00:00
if self . current_tab ( ) is not conversation :
conversation . set_color_state ( theme . COLOR_TAB_PRIVATE )
2010-09-26 18:01:38 +00:00
self . refresh_window ( )
2010-09-08 23:00:55 +00:00
def on_presence ( self , presence ) :
2010-10-17 17:27:07 +00:00
jid = presence [ ' from ' ]
2010-10-31 18:57:48 +00:00
contact = roster . get_contact_by_jid ( jid . bare )
2010-10-17 17:27:07 +00:00
if not contact :
return
resource = contact . get_resource_by_fulljid ( jid . full )
if not resource :
return
status = presence [ ' type ' ]
2010-11-10 21:15:08 +00:00
status_message = presence [ ' status ' ]
2010-10-17 17:27:07 +00:00
priority = presence . getPriority ( ) or 0
resource . set_presence ( status )
resource . set_priority ( priority )
2010-11-10 21:15:08 +00:00
resource . set_status ( status_message )
2011-01-05 02:02:53 +00:00
self . refresh_window ( )
2010-01-21 01:54:50 +00:00
2010-09-08 23:00:55 +00:00
def on_roster_update ( self , iq ) :
"""
A subscription changed , or we received a roster item
after a roster request , etc
"""
2010-09-26 18:01:38 +00:00
for item in iq . findall ( ' { jabber:iq:roster}query/ { jabber:iq:roster}item ' ) :
jid = item . attrib [ ' jid ' ]
2010-10-31 18:57:48 +00:00
contact = roster . get_contact_by_jid ( jid )
2010-09-26 18:01:38 +00:00
if not contact :
contact = Contact ( jid )
2010-10-31 18:57:48 +00:00
roster . add_contact ( contact , jid )
2010-09-26 18:01:38 +00:00
if ' ask ' in item . attrib :
contact . set_ask ( item . attrib [ ' ask ' ] )
else :
contact . set_ask ( None )
2010-09-27 01:40:34 +00:00
if ' name ' in item . attrib :
contact . set_name ( item . attrib [ ' name ' ] )
else :
contact . set_name ( None )
2010-09-26 18:01:38 +00:00
if item . attrib [ ' subscription ' ] :
contact . set_subscription ( item . attrib [ ' subscription ' ] )
groups = item . findall ( ' { jabber:iq:roster}group ' )
2010-10-31 18:57:48 +00:00
roster . edit_groups_of_contact ( contact , [ group . text for group in groups ] )
2011-01-12 05:49:33 +00:00
if item . attrib [ ' subscription ' ] == ' remove ' :
roster . remove_contact ( contact . get_bare_jid ( ) )
2010-12-07 16:20:30 +00:00
if isinstance ( self . current_tab ( ) , tabs . RosterInfoTab ) :
2010-09-26 18:01:38 +00:00
self . refresh_window ( )
2010-09-08 23:00:55 +00:00
2011-01-11 05:43:31 +00:00
def on_changed_subscription ( self , presence ) :
"""
Triggered whenever a presence stanza with a type of subscribe , subscribed , unsubscribe , or unsubscribed is received .
"""
if presence [ ' type ' ] == ' subscribe ' :
jid = presence [ ' from ' ] . bare
contact = roster . get_contact_by_jid ( jid )
if not contact :
contact = Contact ( jid )
roster . add_contact ( contact , jid )
roster . edit_groups_of_contact ( contact , [ ] )
contact . set_ask ( ' asked ' )
2011-01-12 19:37:28 +00:00
self . tabs [ 0 ] . set_color_state ( theme . COLOR_TAB_HIGHLIGHT )
self . information ( ' %s wants to subscribe to your presence ' % jid )
2011-01-11 05:43:31 +00:00
if isinstance ( self . current_tab ( ) , tabs . RosterInfoTab ) :
self . refresh_window ( )
2010-12-17 21:06:59 +00:00
def full_screen_redraw ( self ) :
"""
Completely erase and redraw the screen
"""
self . stdscr . clear ( )
self . call_for_resize ( )
2010-10-05 00:14:13 +00:00
def call_for_resize ( self ) :
"""
2011-02-15 14:27:30 +00:00
Called when we want to resize the screen
2010-07-08 20:20:43 +00:00
"""
2011-03-08 03:20:46 +00:00
tabs . Tab . resize ( self . stdscr )
self . resize_global_information_win ( )
2010-10-05 00:14:13 +00:00
with resize_lock :
for tab in self . tabs :
2011-03-08 03:20:46 +00:00
tab . resize ( )
2010-10-05 00:14:13 +00:00
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
"""
2011-03-08 03:20:46 +00:00
# curses.ungetch(0) # FIXME
2010-10-20 23:51:34 +00:00
while self . running :
2011-01-08 23:20:27 +00:00
char = read_char ( self . stdscr )
2011-03-20 01:42:29 +00:00
# Special case for M-x where x is a number
if char . startswith ( ' M- ' ) and len ( char ) == 3 :
try :
nb = int ( char [ 2 ] )
except :
pass
else :
self . command_win ( ' %s ' % nb )
2010-07-08 19:27:53 +00:00
# search for keyboard shortcut
2011-03-20 01:44:51 +00:00
if char in list ( self . key_func . keys ( ) ) :
2010-07-08 19:27:53 +00:00
self . key_func [ char ] ( )
2010-01-27 19:46:08 +00:00
else :
2010-09-14 02:11:07 +00:00
self . do_command ( char )
2011-01-08 23:20:27 +00:00
self . doupdate ( )
2010-01-27 19:46:08 +00:00
2010-09-14 02:11:07 +00:00
def current_tab ( self ) :
2010-05-18 13:29:02 +00:00
"""
returns the current room , the one we are viewing
"""
2010-09-14 02:11:07 +00:00
return self . tabs [ 0 ]
2010-01-26 17:10:37 +00:00
2010-09-26 18:01:38 +00:00
def get_conversation_by_jid ( self , jid ) :
"""
Return the room of the ConversationTab with the given jid
"""
for tab in self . tabs :
2010-12-07 16:20:30 +00:00
if isinstance ( tab , tabs . ConversationTab ) :
2010-09-26 18:01:38 +00:00
if tab . get_name ( ) == jid :
return tab . get_room ( )
return None
2011-01-26 22:32:41 +00:00
def get_tab_by_name ( self , name , typ = None ) :
2010-11-11 04:22:37 +00:00
"""
Get the tab with the given name .
2011-01-26 22:32:41 +00:00
If typ is provided , return a tab of this type only
2010-11-11 04:22:37 +00:00
"""
for tab in self . tabs :
if tab . get_name ( ) == name :
2011-01-26 22:32:41 +00:00
if ( typ and isinstance ( tab , typ ) ) or \
not typ :
return tab
2010-11-11 04:22:37 +00:00
return None
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
"""
2010-09-14 02:11:07 +00:00
for tab in self . tabs :
2010-12-07 16:20:30 +00:00
if ( isinstance ( tab , tabs . MucTab ) or
2010-12-17 14:36:14 +00:00
isinstance ( tab , tabs . PrivateTab ) ) and tab . get_name ( ) == name :
2010-09-14 02:11:07 +00:00
return tab . get_room ( )
2010-05-18 13:29:02 +00:00
return None
2010-01-26 17:10:37 +00:00
2010-01-21 01:54:50 +00:00
def init_curses ( self , stdscr ) :
2010-05-18 13:29:02 +00:00
"""
ncurses initialization
"""
2010-10-17 05:14:22 +00:00
curses . curs_set ( 1 )
2010-01-21 01:54:50 +00:00
curses . noecho ( )
2011-01-21 03:46:21 +00:00
curses . nonl ( )
2010-10-17 05:14:22 +00:00
theme . init_colors ( )
2010-01-27 19:46:08 +00:00
stdscr . keypad ( True )
2011-03-03 02:24:04 +00:00
curses . ungetch ( " " ) # H4X: without this, the screen is
stdscr . getkey ( ) # erased on the first "getkey()"
2010-01-21 01:54:50 +00:00
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 ( )
2011-01-12 15:53:07 +00:00
curses . curs_set ( 1 )
2010-01-27 17:02:13 +00:00
curses . endwin ( )
2010-01-26 17:10:37 +00:00
2010-08-04 00:17:53 +00:00
def refresh_window ( self ) :
"""
Refresh everything
"""
2010-09-14 02:11:07 +00:00
self . current_tab ( ) . set_color_state ( theme . COLOR_TAB_CURRENT )
2011-03-05 20:42:56 +00:00
self . current_tab ( ) . refresh ( )
2010-10-17 12:43:56 +00:00
self . doupdate ( )
2010-08-04 00:17:53 +00:00
2010-12-07 16:20:30 +00:00
def add_tab ( self , new_tab , focus = False ) :
2010-05-18 13:29:02 +00:00
"""
2010-12-07 16:20:30 +00:00
Appends the new_tab in the tab list and
focus it if focus == True
2010-05-18 13:29:02 +00:00
"""
2010-09-14 02:11:07 +00:00
if self . current_tab ( ) . nb == 0 :
self . tabs . append ( new_tab )
2010-02-11 04:59:58 +00:00
else :
2010-09-14 02:11:07 +00:00
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 :
2010-09-14 02:11:07 +00:00
self . command_win ( " %s " % new_tab . nb )
2010-12-07 16:20:30 +00:00
def open_new_room ( self , room , nick , focus = True ) :
"""
Open a new tab . MucTab containing a muc Room , using the specified nick
"""
r = Room ( room , nick )
2011-03-05 20:42:56 +00:00
new_tab = tabs . MucTab ( r )
2010-12-07 16:20:30 +00:00
self . add_tab ( new_tab , focus )
2010-08-04 00:17:53 +00:00
self . refresh_window ( )
2010-01-21 01:54:50 +00:00
2010-10-05 00:36:43 +00:00
def go_to_roster ( self ) :
self . command_win ( ' 0 ' )
def go_to_previous_tab ( self ) :
self . command_win ( ' %s ' % ( self . previous_tab_nb , ) )
2010-07-08 19:27:53 +00:00
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
"""
2010-09-14 02:11:07 +00:00
for tab in self . tabs :
if tab . get_color_state ( ) == theme . COLOR_TAB_PRIVATE :
self . command_win ( ' %s ' % tab . nb )
2010-07-08 19:27:53 +00:00
return
2010-09-14 02:11:07 +00:00
for tab in self . tabs :
if tab . get_color_state ( ) == theme . COLOR_TAB_HIGHLIGHT :
self . command_win ( ' %s ' % tab . nb )
2010-07-08 19:27:53 +00:00
return
2010-09-14 02:11:07 +00:00
for tab in self . tabs :
if tab . get_color_state ( ) == theme . COLOR_TAB_NEW_MESSAGE :
self . command_win ( ' %s ' % tab . nb )
2010-08-04 00:17:53 +00:00
return
2010-12-07 16:20:30 +00:00
for tab in self . tabs :
if isinstance ( tab , tabs . ChatTab ) and not tab . input . is_empty ( ) :
self . command_win ( ' %s ' % tab . nb )
return
2010-07-08 19:27:53 +00:00
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
"""
2010-09-14 02:11:07 +00:00
self . current_tab ( ) . on_lose_focus ( )
self . tabs . append ( self . tabs . pop ( 0 ) )
self . current_tab ( ) . on_gain_focus ( )
2010-08-04 00:17:53 +00:00
self . refresh_window ( )
2010-01-21 01:54:50 +00:00
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
"""
2010-09-14 02:11:07 +00:00
self . current_tab ( ) . on_lose_focus ( )
self . tabs . insert ( 0 , self . tabs . pop ( ) )
self . current_tab ( ) . on_gain_focus ( )
2010-08-04 00:17:53 +00:00
self . refresh_window ( )
2010-01-21 01:54:50 +00:00
2010-06-10 01:17:59 +00:00
def scroll_page_down ( self , args = None ) :
2010-09-14 02:11:07 +00:00
self . current_tab ( ) . on_scroll_down ( )
2010-08-04 00:17:53 +00:00
self . refresh_window ( )
2010-06-10 01:17:59 +00:00
def scroll_page_up ( self , args = None ) :
2010-09-14 02:11:07 +00:00
self . current_tab ( ) . on_scroll_up ( )
2010-08-04 00:17:53 +00:00
self . refresh_window ( )
2010-06-10 01:17:59 +00:00
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 :
2010-09-03 18:01:43 +00:00
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 :
2010-09-14 02:11:07 +00:00
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 :
2010-09-14 02:11:07 +00:00
msg = _ ( ' Error: %(msg)s : %(body)s ' ) % { ' msg ' : msg , ' body ' : body }
self . add_message_to_text_buffer ( room , msg )
2010-03-24 18:01:22 +00:00
if code == ' 401 ' :
2010-09-14 02:11:07 +00:00
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 :
2010-09-14 02:11:07 +00:00
self . add_message_to_text_buffer ( room , _ ( ' You can join the room with an other nick, by typing " /join /other_nick " ' ) )
2010-08-04 00:17:53 +00:00
self . refresh_window ( )
2010-03-24 18:01:22 +00:00
2010-11-10 21:15:08 +00:00
def open_conversation_window ( self , jid , focus = True ) :
2010-09-26 18:01:38 +00:00
"""
open a new conversation tab and focus it if needed
"""
2011-03-05 20:42:56 +00:00
new_tab = tabs . ConversationTab ( jid )
2010-09-26 18:01:38 +00:00
# insert it in the rooms
2010-12-07 16:20:30 +00:00
self . add_tab ( new_tab , focus )
2010-09-26 18:01:38 +00:00
self . refresh_window ( )
2010-11-11 04:22:37 +00:00
return new_tab
2010-09-26 18:01:38 +00:00
2010-06-13 13:51:02 +00:00
def open_private_window ( self , room_name , user_nick , focus = True ) :
2010-09-03 18:01:43 +00:00
complete_jid = room_name + ' / ' + user_nick
2010-09-14 02:11:07 +00:00
for tab in self . tabs : # if the room exists, focus it and return
2010-12-07 16:20:30 +00:00
if isinstance ( tab , tabs . PrivateTab ) :
2010-09-14 02:11:07 +00:00
if tab . get_name ( ) == complete_jid :
self . command_win ( ' %s ' % tab . nb )
2010-12-17 14:39:44 +00:00
return tab . get_room ( )
2010-06-13 13:51:02 +00:00
# create the new tab
2010-09-02 01:11:21 +00:00
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
2010-09-14 02:11:07 +00:00
r = Room ( complete_jid , own_nick ) # PrivateRoom here
2011-03-05 20:42:56 +00:00
new_tab = tabs . PrivateTab ( r )
2010-10-31 18:57:48 +00:00
# insert it in the tabs
2010-12-07 16:20:30 +00:00
self . add_tab ( new_tab , focus )
2010-06-13 13:51:02 +00:00
# self.window.new_room(r)
2010-08-04 00:17:53 +00:00
self . refresh_window ( )
2010-06-13 13:51:02 +00:00
return r
2010-11-09 22:41:31 +00:00
def on_groupchat_subject ( self , message ) :
"""
triggered when the topic is changed
"""
nick_from = message [ ' mucnick ' ]
room_from = message . getMucroom ( )
room = self . get_room_by_name ( room_from )
subject = message [ ' subject ' ]
2011-01-09 15:34:06 +00:00
if not subject or not room :
2010-11-09 22:41:31 +00:00
return
2011-01-09 01:54:36 +00:00
if nick_from :
self . add_message_to_text_buffer ( room , _ ( " %(nick)s set the subject to: %(subject)s " ) % { ' nick ' : nick_from , ' subject ' : subject } , time = None )
else :
self . add_message_to_text_buffer ( room , _ ( " The subject is: %(subject)s " ) % { ' subject ' : subject } , time = None )
2010-11-09 22:41:31 +00:00
room . topic = subject . replace ( ' \n ' , ' | ' )
self . refresh_window ( )
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
"""
2011-01-09 01:54:36 +00:00
if message [ ' subject ' ] :
return
2010-08-31 23:11:02 +00:00
delay_tag = message . find ( ' { urn:xmpp:delay}delay ' )
if delay_tag is not None :
2010-03-19 03:30:51 +00:00
delayed = True
2010-08-31 23:11:02 +00:00
date = common . datetime_tuple ( delay_tag . attrib [ ' stamp ' ] )
2010-03-19 03:30:51 +00:00
else :
2010-07-26 00:51:07 +00:00
# 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 :
2010-07-26 00:51:07 +00:00
delayed = True
2010-08-31 23:11:02 +00:00
date = common . datetime_tuple ( delay_tag . attrib [ ' stamp ' ] )
2010-07-26 00:51:07 +00:00
else :
delayed = False
2010-08-31 23:11:02 +00:00
date = None
2010-09-02 00:44:18 +00:00
nick_from = message [ ' mucnick ' ]
2010-08-31 23:11:02 +00:00
room_from = message . getMucroom ( )
2010-09-08 23:00:55 +00:00
if message [ ' type ' ] == ' error ' : # Check if it's an error
return self . room_error ( message , from_room )
2010-09-02 00:44:18 +00:00
if nick_from == room_from :
nick_from = None
2010-09-02 01:49:11 +00:00
room = self . get_room_by_name ( room_from )
2011-01-26 22:32:41 +00:00
tab = self . get_tab_by_name ( room_from , tabs . MucTab )
2010-11-24 05:41:06 +00:00
if tab and tab . get_room ( ) and tab . get_room ( ) . get_user_by_name ( nick_from ) and \
tab . get_room ( ) . get_user_by_name ( nick_from ) in tab . ignores :
2010-06-12 17:28:51 +00:00
return
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
2010-09-02 00:44:18 +00:00
body = message [ ' body ' ]
2010-11-09 22:41:31 +00:00
if body :
2010-10-11 23:09:16 +00:00
date = date if delayed == True else None
self . add_message_to_text_buffer ( room , body , date , nick_from )
2010-12-31 10:52:15 +00:00
# TODO, only if we are focused on this MUC
2010-11-09 22:41:31 +00:00
self . refresh_window ( )
self . doupdate ( )
2010-01-21 01:54:50 +00:00
2011-03-29 10:44:19 +00:00
def add_message_to_text_buffer ( self , room , txt , time = None , nickname = None ) :
2010-03-18 19:43:44 +00:00
"""
2010-09-14 02:11:07 +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
"""
2010-09-14 02:11:07 +00:00
if not room :
self . information ( ' Error, trying to add a message in no room: %s ' % txt )
2010-06-10 01:17:59 +00:00
else :
2011-03-29 10:44:19 +00:00
room . add_message ( txt , time , nickname )
2010-09-14 02:11:07 +00:00
self . refresh_window ( )
2010-01-13 01:04:30 +00:00
2010-08-02 19:22:41 +00:00
def command_help ( self , arg ) :
2010-05-18 13:29:02 +00:00
"""
/ help < command_name >
"""
2010-08-02 19:22:41 +00:00
args = arg . split ( )
2010-01-30 04:42:29 +00:00
if len ( args ) == 0 :
2010-06-13 00:09:28 +00:00
msg = _ ( ' Available commands are: ' )
2010-09-03 18:01:43 +00:00
for command in list ( self . commands . keys ( ) ) :
2010-01-30 04:42:29 +00:00
msg + = " %s " % command
2010-11-24 05:41:06 +00:00
for command in list ( self . current_tab ( ) . commands . keys ( ) ) :
msg + = " %s " % command
2010-01-31 05:33:54 +00:00
msg + = _ ( " \n Type /help <command_name> to know what each command does " )
2010-10-31 19:02:57 +00:00
if len ( args ) > = 1 :
2010-09-03 18:01:43 +00:00
if args [ 0 ] in list ( self . commands . keys ( ) ) :
2010-01-30 04:42:29 +00:00
msg = self . commands [ args [ 0 ] ] [ 1 ]
2011-02-10 15:15:33 +00:00
elif args [ 0 ] in list ( self . current_tab ( ) . commands . keys ( ) ) :
msg = self . current_tab ( ) . commands [ args [ 0 ] ] [ 1 ]
2010-01-30 04:42:29 +00:00
else :
2010-01-31 05:33:54 +00:00
msg = _ ( ' Unknown command: %s ' ) % args [ 0 ]
2010-09-14 02:11:07 +00:00
self . information ( msg )
2010-01-30 04:42:29 +00:00
2011-02-10 15:13:28 +00:00
def completion_help ( self , the_input ) :
commands = list ( self . commands . keys ( ) ) + list ( self . current_tab ( ) . commands . keys ( ) )
return the_input . auto_completion ( commands , ' ' )
2011-01-23 21:49:58 +00:00
def command_status ( self , arg ) :
2011-03-11 21:10:37 +00:00
"""
/ status < status > [ msg ]
"""
2011-01-23 21:49:58 +00:00
args = arg . split ( )
if len ( args ) < 1 :
return
if not args [ 0 ] in possible_show . keys ( ) :
2011-03-11 21:10:37 +00:00
self . command_help ( ' status ' )
2011-01-23 21:49:58 +00:00
return
show = possible_show [ args [ 0 ] ]
if len ( args ) > 1 :
msg = ' ' . join ( args [ 1 : ] )
else :
msg = None
pres = self . xmpp . make_presence ( )
if msg :
pres [ ' status ' ] = msg
pres [ ' type ' ] = show
pres . send ( )
2011-03-11 21:10:37 +00:00
for tab in self . tabs :
if isinstance ( tab , tabs . MucTab ) and tab . get_room ( ) . joined :
muc . change_show ( self . xmpp , tab . get_room ( ) . name , tab . get_room ( ) . own_nick , show , msg )
2011-01-23 21:49:58 +00:00
2011-02-10 15:08:17 +00:00
def completion_status ( self , the_input ) :
return the_input . auto_completion ( [ status for status in list ( possible_show . keys ( ) ) ] , ' ' )
2011-02-15 15:22:25 +00:00
def command_message ( self , arg ) :
"""
/ message < jid > [ message ]
"""
args = arg . split ( )
if len ( args ) < 1 :
self . command_help ( ' message ' )
return
jid = args [ 0 ]
tab = self . open_conversation_window ( jid , focus = True )
if len ( args ) > 1 :
2011-03-27 12:40:29 +00:00
tab . command_say ( arg . strip ( ) [ len ( jid ) + 1 : ] )
2011-02-15 15:22:25 +00:00
2011-03-15 22:40:54 +00:00
def command_version ( self , arg ) :
"""
/ version < jid >
"""
args = arg . split ( )
if len ( args ) < 1 :
return self . command_help ( ' version ' )
jid = args [ 0 ]
res = self . xmpp . plugin [ ' xep_0092 ' ] . get_version ( jid )
if not res :
return self . information ( ' Could not get the software version from %s ' % ( jid , ) )
version = ' %s is running %s version %s on %s ' % ( jid ,
res . get ( ' name ' ) or _ ( ' an unknown software ' ) ,
res . get ( ' version ' ) or _ ( ' unknown ' ) ,
res . get ( ' os ' ) or _ ( ' on an unknown platform ' ) )
self . information ( version )
2011-03-20 00:46:44 +00:00
def command_reconnect ( self , args ) :
"""
/ reconnect
"""
self . disconnect ( True )
2010-12-07 16:20:30 +00:00
def command_list ( self , arg ) :
"""
/ list < server >
Opens a MucListTab containing the list of the room in the specified server
"""
args = arg . split ( )
if len ( args ) > 1 :
self . command_help ( ' list ' )
return
elif len ( args ) == 0 :
if not isinstance ( self . current_tab ( ) , tabs . MucTab ) :
return self . information ( ' Warning: Please provide a server ' )
server = JID ( self . current_tab ( ) . get_name ( ) ) . server
else :
server = arg . strip ( )
2011-03-05 20:42:56 +00:00
list_tab = tabs . MucListTab ( server )
2010-12-07 16:20:30 +00:00
self . add_tab ( list_tab , True )
2011-01-02 15:50:01 +00:00
self . xmpp . plugin [ ' xep_0030 ' ] . get_items ( jid = server , block = False , callback = list_tab . on_muc_list_item_received )
2010-12-07 16:20:30 +00:00
2010-08-20 20:55:42 +00:00
def command_theme ( self , arg ) :
"""
"""
theme . reload_theme ( )
2011-02-15 14:27:30 +00:00
self . refresh_window ( )
2010-08-20 20:55:42 +00:00
2010-08-02 19:22:41 +00:00
def command_win ( self , arg ) :
2010-05-18 13:29:02 +00:00
"""
/ win < number >
"""
2010-08-02 19:22:41 +00:00
args = arg . split ( )
2010-02-12 02:50:07 +00:00
if len ( args ) != 1 :
2010-08-11 19:14:36 +00:00
self . command_help ( ' win ' )
2010-02-12 02:50:07 +00:00
return
try :
nb = int ( args [ 0 ] )
except ValueError :
2011-01-17 11:17:37 +00:00
nb = arg . strip ( )
2010-09-14 02:11:07 +00:00
if self . current_tab ( ) . nb == nb :
2010-02-12 02:50:07 +00:00
return
2010-10-05 00:36:43 +00:00
self . previous_tab_nb = self . current_tab ( ) . nb
2010-09-14 02:11:07 +00:00
self . current_tab ( ) . on_lose_focus ( )
start = self . current_tab ( )
self . tabs . append ( self . tabs . pop ( 0 ) )
2011-01-17 11:17:37 +00:00
if isinstance ( nb , int ) :
while self . current_tab ( ) . nb != nb :
self . tabs . append ( self . tabs . pop ( 0 ) )
if self . current_tab ( ) == start :
break
else :
while nb not in JID ( self . current_tab ( ) . get_name ( ) ) . user :
self . tabs . append ( self . tabs . pop ( 0 ) )
if self . current_tab ( ) is start :
break
2010-09-14 02:11:07 +00:00
self . current_tab ( ) . on_gain_focus ( )
2010-08-04 00:17:53 +00:00
self . refresh_window ( )
2010-02-12 02:50:07 +00:00
2011-02-10 15:08:17 +00:00
def completion_win ( self , the_input ) :
l = [ JID ( tab . get_name ( ) ) . user for tab in self . tabs ]
l . remove ( ' ' )
return the_input . auto_completion ( l , ' ' )
2010-11-25 03:04:03 +00:00
def completion_join ( self , the_input ) :
"""
Try to complete the server of the MUC ' s jid (for now only from the currently
open ones )
TODO : have a history of recently joined MUCs , and use that too
"""
txt = the_input . get_text ( )
if len ( txt . split ( ) ) != 2 :
# we are not on the 1st argument of the command line
return False
jid = JID ( txt . split ( ) [ 1 ] )
2010-11-29 18:36:54 +00:00
if jid . server :
if jid . resource or jid . full . endswith ( ' / ' ) :
# we are writing the resource: complete the node
if not the_input . last_completion :
2011-01-02 16:00:47 +00:00
response = self . xmpp . plugin [ ' xep_0030 ' ] . get_items ( jid = jid . server , block = True , timeout = 1 )
2010-11-29 18:54:30 +00:00
if response :
2011-01-02 16:00:47 +00:00
items = response [ ' disco_items ' ] . get_items ( )
2010-11-29 18:54:30 +00:00
else :
return True
2010-11-29 18:36:54 +00:00
items = [ ' %s / %s ' % ( tup [ 0 ] , jid . resource ) for tup in items ]
for i in range ( len ( jid . server ) + 2 + len ( jid . resource ) ) :
the_input . key_backspace ( )
else :
items = [ ]
the_input . auto_completion ( items , ' ' )
else :
# we are writing the server: complete the server
serv = jid . server
serv_list = [ ]
for tab in self . tabs :
2010-12-07 16:20:30 +00:00
if isinstance ( tab , tabs . MucTab ) :
2010-11-29 18:36:54 +00:00
serv_list . append ( ' %s @ %s ' % ( jid . user , JID ( tab . get_name ( ) ) . host ) )
the_input . auto_completion ( serv_list , ' ' )
2010-11-25 03:04:03 +00:00
return True
2010-11-29 18:36:54 +00:00
def completion_list ( self , the_input ) :
txt = the_input . get_text ( )
muc_serv_list = [ ]
for tab in self . tabs : # TODO, also from an history
2010-12-07 16:20:30 +00:00
if isinstance ( tab , tabs . MucTab ) and \
2010-11-29 18:36:54 +00:00
tab . get_name ( ) not in muc_serv_list :
2011-02-10 15:18:17 +00:00
muc_serv_list . append ( JID ( tab . get_name ( ) ) . server )
2010-11-29 18:36:54 +00:00
if muc_serv_list :
2011-02-10 15:08:17 +00:00
return the_input . auto_completion ( muc_serv_list , ' ' )
2010-11-29 18:36:54 +00:00
2011-01-04 03:36:04 +00:00
def command_join ( self , arg , histo_length = None ) :
2010-05-18 13:29:02 +00:00
"""
/ join [ room ] [ / nick ] [ password ]
"""
2010-08-02 19:22:41 +00:00
args = arg . split ( )
2010-03-24 18:01:22 +00:00
password = None
2010-01-30 04:02:23 +00:00
if len ( args ) == 0 :
2010-09-14 02:11:07 +00:00
t = self . current_tab ( )
2010-12-07 16:20:30 +00:00
if not isinstance ( t , tabs . MucTab ) and not isinstance ( t , tabs . PrivateTab ) :
2010-01-30 04:02:23 +00:00
return
2010-09-14 02:11:07 +00:00
room = t . get_name ( )
nick = t . get_room ( ) . own_nick
2010-01-30 02:50:24 +00:00
else :
2010-12-07 16:31:30 +00:00
info = JID ( args [ 0 ] )
if info . resource == ' ' :
2010-06-30 09:56:03 +00:00
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 :
2010-12-07 16:31:30 +00:00
nick = info . resource
if info . bare == ' ' : # happens with /join /nickname, which is OK
2010-09-14 02:11:07 +00:00
t = self . current_tab ( )
2010-12-07 16:20:30 +00:00
if not isinstance ( t , tabs . MucTab ) :
2010-01-30 04:02:23 +00:00
return
2010-09-14 02:11:07 +00:00
room = t . get_name ( )
2010-03-24 18:01:22 +00:00
if nick == ' ' :
2010-09-14 02:11:07 +00:00
nick = t . get_room ( ) . own_nick
2010-01-30 04:02:23 +00:00
else :
2010-12-07 16:31:30 +00:00
room = info . bare
if room . find ( ' @ ' ) == - 1 : # no server is provided, like "/join hello"
2010-07-01 21:32:44 +00:00
# use the server of the current room if available
# check if the current room's name has a server
2010-12-07 16:20:30 +00:00
if isinstance ( self . current_tab ( ) , tabs . MucTab ) and \
2010-12-07 16:31:30 +00:00
self . current_tab ( ) . get_name ( ) . find ( ' @ ' ) != - 1 :
room + = ' @ %s ' % JID ( self . current_tab ( ) . get_name ( ) ) . domain
2010-07-01 21:32:44 +00:00
else : # no server could be found, print a message and return
2010-09-27 22:53:25 +00:00
self . information ( _ ( " You didn ' t specify a server for the room you want to join " ) , ' Error ' )
2010-07-01 21:32:44 +00:00
return
2010-09-14 02:11:07 +00:00
r = self . get_room_by_name ( room )
2010-03-24 18:01:22 +00:00
if len ( args ) == 2 : # a password is provided
password = args [ 1 ]
2010-09-27 01:40:34 +00:00
if r and r . joined : # if we are already in the room
self . focus_tab_named ( r . name )
return
2011-01-17 14:54:11 +00:00
if room . startswith ( ' @ ' ) :
room = room [ 1 : ]
2010-08-31 23:11:02 +00:00
room = room . lower ( )
2010-09-14 02:11:07 +00:00
if r and not r . joined :
2011-01-04 03:36:04 +00:00
muc . join_groupchat ( self . xmpp , room , nick , password , histo_length )
2010-03-24 16:44:55 +00:00
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 )
2011-01-04 03:36:04 +00:00
muc . join_groupchat ( self . xmpp , room , nick , password , histo_length )
2010-03-24 16:44:55 +00:00
else :
2010-07-08 20:05:06 +00:00
r . own_nick = nick
2010-03-24 16:44:55 +00:00
r . users = [ ]
2010-01-13 01:04:30 +00:00
2010-08-02 19:22:41 +00:00
def command_bookmark ( self , arg ) :
2010-05-18 13:29:02 +00:00
"""
/ bookmark [ room ] [ / nick ]
"""
2010-08-02 19:22:41 +00:00
args = arg . split ( )
2010-01-31 03:42:25 +00:00
nick = None
2011-01-13 19:34:17 +00:00
if len ( args ) == 0 and not isinstance ( self . current_tab ( ) , tabs . MucTab ) :
2010-09-14 02:11:07 +00:00
return
2010-01-31 03:42:25 +00:00
if len ( args ) == 0 :
2010-09-14 02:11:07 +00:00
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 :
2010-12-07 16:31:30 +00:00
info = JID ( args [ 0 ] )
if info . resource != ' ' :
nick = info . resource
roomname = info . bare
2010-02-14 04:10:13 +00:00
if roomname == ' ' :
2010-09-14 02:11:07 +00:00
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 :
2010-12-07 16:31:30 +00:00
if JID ( room ) . bare == roomname :
2010-02-14 04:10:13 +00:00
bookmarked . remove ( room )
break
bookmarked = ' : ' . join ( bookmarked )
2010-10-05 21:28:11 +00:00
if bookmarked :
bookmarks = bookmarked + ' : ' + res
else :
bookmarks = res
2010-07-14 17:04:50 +00:00
config . set_and_save ( ' rooms ' , bookmarks )
2010-09-14 02:11:07 +00:00
self . information ( _ ( ' Your bookmarks are now: %s ' ) % bookmarks )
2010-01-31 03:42:25 +00:00
2010-08-02 19:22:41 +00:00
def command_set ( self , arg ) :
2010-05-18 13:29:02 +00:00
"""
/ set < option > [ value ]
"""
2010-08-02 19:22:41 +00:00
args = arg . split ( )
2010-02-12 19:35:18 +00:00
if len ( args ) != 2 and len ( args ) != 1 :
2010-08-11 19:14:36 +00:00
self . command_help ( ' set ' )
2010-02-02 23:35:01 +00:00
return
option = args [ 0 ]
2010-02-12 19:35:18 +00:00
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 )
2010-09-14 02:11:07 +00:00
self . information ( msg )
2010-02-02 23:35:01 +00:00
2010-08-02 19:22:41 +00:00
def command_away ( self , arg ) :
2010-05-18 13:29:02 +00:00
"""
/ away [ msg ]
"""
2011-03-11 21:10:37 +00:00
self . command_status ( " away " + arg )
2010-01-31 03:07:30 +00:00
2010-08-02 19:22:41 +00:00
def command_busy ( self , arg ) :
2010-05-18 13:29:02 +00:00
"""
/ busy [ msg ]
"""
2011-03-11 21:10:37 +00:00
self . command_status ( " busy " + arg )
2010-01-31 03:07:30 +00:00
2010-08-02 19:22:41 +00:00
def command_avail ( self , arg ) :
2010-05-18 13:29:02 +00:00
"""
/ avail [ msg ]
"""
2011-03-11 21:10:37 +00:00
self . command_status ( " available " + arg )
2010-01-31 00:25:17 +00:00
2010-11-11 04:22:37 +00:00
def close_tab ( self , tab = None ) :
2010-06-21 08:46:06 +00:00
"""
2010-11-11 04:22:37 +00:00
Close the given tab . If None , close the current one
2010-06-21 08:46:06 +00:00
"""
2010-11-11 04:22:37 +00:00
tab = tab or self . current_tab ( )
2010-12-07 16:20:30 +00:00
if isinstance ( tab , tabs . RosterInfoTab ) or \
isinstance ( tab , tabs . InfoTab ) :
2010-11-11 04:22:37 +00:00
return # The tab 0 should NEVER be closed
2011-03-07 20:41:13 +00:00
del tab . key_func # Remove self references
del tab . commands # and make the object collectable
2010-11-11 04:22:37 +00:00
tab . on_close ( )
self . tabs . remove ( tab )
2011-03-07 20:41:13 +00:00
import gc
gc . collect ( )
log . debug ( ' ___ Referrers of closing tab: \n %s \n ______ ' % gc . get_referrers ( tab ) )
2010-11-11 04:22:37 +00:00
del tab
2011-03-07 20:41:13 +00:00
self . refresh_window ( )
2010-06-21 08:46:06 +00:00
2011-03-20 02:32:48 +00:00
def go_to_room_number ( self ) :
"""
Read 2 more chars and go to the tab
with the given number
"""
char = read_char ( self . stdscr )
try :
nb1 = int ( char )
except ValueError :
return
char = read_char ( self . stdscr )
try :
nb2 = int ( char )
except ValueError :
return
self . command_win ( ' %s %s ' % ( nb1 , nb2 ) )
2010-09-11 20:07:50 +00:00
def move_separator ( self ) :
"""
Move the new - messages separator at the bottom on the current
text .
"""
2010-12-15 17:05:52 +00:00
window = self . current_tab ( ) . get_text_window ( )
if not window :
2010-09-14 02:11:07 +00:00
return
2010-12-15 17:05:52 +00:00
window . remove_line_separator ( )
window . add_line_separator ( )
2010-09-14 02:11:07 +00:00
self . refresh_window ( )
2010-09-11 20:07:50 +00:00
2010-09-14 02:11:07 +00:00
def information ( self , msg , typ = ' ' ) :
2010-05-18 13:29:02 +00:00
"""
Displays an informational message in the " Info " room window
"""
2010-09-14 02:11:07 +00:00
self . information_buffer . add_message ( msg , nickname = typ )
2010-12-15 15:40:43 +00:00
# TODO: refresh only the correct window in the current tab
2010-09-14 02:11:07 +00:00
self . refresh_window ( )
2010-01-28 00:55:02 +00:00
2011-03-20 00:46:44 +00:00
def disconnect ( self , msg = None ) :
"""
Disconnect from remote server and correctly set the states of all
parts of the client ( for example , set the MucTabs as not joined , etc )
"""
for tab in self . tabs :
if isinstance ( tab , tabs . MucTab ) :
muc . leave_groupchat ( self . xmpp , tab . get_room ( ) . name , tab . get_room ( ) . own_nick , msg )
self . save_config ( )
self . xmpp . disconnect ( False )
2010-08-02 19:22:41 +00:00
def command_quit ( self , arg ) :
2010-05-18 13:29:02 +00:00
"""
/ quit
"""
2010-08-02 19:22:41 +00:00
if len ( arg . strip ( ) ) != 0 :
msg = arg
2010-06-13 15:40:03 +00:00
else :
msg = None
2011-03-20 00:46:44 +00:00
self . disconnect ( msg )
2010-10-20 23:51:34 +00:00
self . running = False
2010-08-31 23:11:02 +00:00
self . reset_curses ( )
2011-01-12 15:53:07 +00:00
sys . exit ( )
2010-09-14 02:11:07 +00:00
2010-12-17 14:36:14 +00:00
def save_config ( self ) :
"""
Save config in the file just before exit
"""
roster . save_to_config_file ( )
config . set_and_save ( ' info_win_height ' , self . information_win_size , ' var ' )
2010-09-14 02:11:07 +00:00
def do_command ( self , key ) :
2010-09-14 22:59:40 +00:00
if not key :
return
2010-09-14 02:11:07 +00:00
res = self . current_tab ( ) . on_input ( key )
2010-11-15 13:16:30 +00:00
if res :
self . refresh_window ( )
2010-09-26 18:01:38 +00:00
def on_roster_enter_key ( self , roster_row ) :
"""
when enter is pressed on the roster window
"""
if isinstance ( roster_row , Contact ) :
2010-10-17 17:27:07 +00:00
if not self . get_conversation_by_jid ( roster_row . get_bare_jid ( ) ) :
self . open_conversation_window ( roster_row . get_bare_jid ( ) )
else :
self . focus_tab_named ( roster_row . get_bare_jid ( ) )
if isinstance ( roster_row , Resource ) :
if not self . get_conversation_by_jid ( roster_row . get_jid ( ) . full ) :
self . open_conversation_window ( roster_row . get_jid ( ) . full )
2010-09-26 18:01:38 +00:00
else :
2010-10-17 17:27:07 +00:00
self . focus_tab_named ( roster_row . get_jid ( ) . full )
2010-09-27 01:40:34 +00:00
self . refresh_window ( )
2010-09-14 02:11:07 +00:00
def execute ( self , line ) :
"""
Execute the / command or just send the line on the current room
"""
if line == " " :
return
2011-01-11 01:52:00 +00:00
if line . startswith ( ' / ' ) :
2010-09-14 02:11:07 +00:00
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 ' ) )
2010-10-17 05:14:22 +00:00
def doupdate ( self ) :
2011-01-12 15:53:07 +00:00
if not self . running :
return
2010-10-17 12:43:56 +00:00
self . current_tab ( ) . just_before_refresh ( )
2010-10-17 05:14:22 +00:00
curses . doupdate ( )