2010-01-10 20:14:17 +00:00
#!/usr/bin/python
# -*- coding:utf-8 -*-
#
# 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
2010-01-31 05:33:54 +00:00
import sys
2010-06-30 09:56:03 +00:00
import os
2010-01-31 05:33:54 +00:00
import curses
2010-01-21 01:54:50 +00:00
from datetime import datetime
2010-03-19 03:30:51 +00:00
import common
2010-01-21 01:54:50 +00:00
2010-01-31 05:33:54 +00:00
from handler import Handler
2010-01-30 02:50:24 +00:00
from config import config
2010-01-21 01:54:50 +00:00
from window import Window
2010-03-18 19:43:44 +00:00
from user import User
from room import Room
2010-06-10 01:17:59 +00:00
from message import Message
2010-06-13 13:51:02 +00:00
from connection import is_jid_the_same
2010-06-10 01:17:59 +00:00
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-01-21 01:54:50 +00:00
def __init__ ( self , stdscr = None , muc = None ) :
self . init_curses ( stdscr )
self . stdscr = stdscr
self . window = Window ( stdscr )
2010-06-10 01:17:59 +00:00
self . rooms = [ Room ( ' Info ' , ' ' , self . window ) ]
2010-06-12 17:28:51 +00:00
self . ignores = { }
2010-02-11 04:59:58 +00:00
2010-01-21 01:54:50 +00:00
self . muc = muc
2010-01-10 20:14:17 +00:00
2010-01-13 01:04:30 +00:00
self . commands = {
2010-06-12 21:28:34 +00:00
' help ' : ( self . command_help , u ' \ _o< KOIN KOIN KOIN ' ) ,
2010-06-13 00:09:28 +00:00
' join ' : ( self . command_join , _ ( " Usage: /join [room_name][/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 password to join the room. \n Examples: \n /join room@server.tld \n /join room@server.tld/ John \n /join /me_again \n /join \n /join room@server.tld/my_nick password \n /join / pass " ) ) ,
' quit ' : ( self . command_quit , _ ( " Usage: /quit \n Quit: Just disconnect from the server and exit poezio. " ) ) ,
' exit ' : ( self . command_quit , _ ( " Usage: /exit \n Exit: Just disconnect from the server and exit poezio. " ) ) ,
' next ' : ( self . rotate_rooms_right , _ ( " Usage: /next \n Next: Go to the next room. " ) ) ,
' n ' : ( self . rotate_rooms_right , _ ( " Usage: /n \n N: Go to the next room. " ) ) ,
' prev ' : ( self . rotate_rooms_left , _ ( " Usage: /prev \n Prev: Go to the previous room. " ) ) ,
' p ' : ( self . rotate_rooms_left , _ ( " Usage: /p \n P: Go to the previous room. " ) ) ,
' win ' : ( self . command_win , _ ( " Usage: /win <number> \n Win: Go to the specified room. " ) ) ,
' w ' : ( self . command_win , _ ( " Usage: /w <number> \n W: Go to the specified room. " ) ) ,
2010-06-13 16:09:12 +00:00
' ignore ' : ( self . command_ignore , _ ( " Usage: /ignore <nickname> \n Ignore: Ignore a specified nickname. " ) ) ,
' unignore ' : ( self . command_unignore , _ ( " Usage: /unignore <nickname> \n Unignore: Remove the specified nickname from the ignore list. " ) ) ,
2010-06-13 00:09:28 +00:00
' 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] \n Show: 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] \n Away: 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] \n Busy: 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] \n Avail: 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] \n Available: 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] \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) " ) ) ,
2010-06-21 08:46:06 +00:00
' unquery ' : ( self . command_unquery , _ ( " Usage: /unquery \n Close the private conversation window " ) ) ,
2010-06-13 00:09:28 +00:00
' 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>. " ) ) ,
' kick ' : ( self . command_kick , _ ( " Usage: /kick <nick> [reason] \n Kick: Kick the user with the specified nickname. You also can give an optional reason. " ) ) ,
' topic ' : ( self . command_topic , _ ( " Usage: /topic <subject> \n Topic: Change the subject of the room " ) ) ,
2010-06-13 13:51:02 +00:00
' query ' : ( self . command_query , _ ( ' Usage: /query <nick> \n Query: Open a private conversation with <nick>. This nick has to be present in the room you \' re currently in. ' ) ) ,
2010-06-13 00:09:28 +00:00
' nick ' : ( self . command_nick , _ ( " Usage: /nick <nickname> \n Nick: Change your nickname in the current room " ) )
2010-01-13 01:04:30 +00:00
}
2010-01-27 19:46:08 +00:00
self . key_func = {
" KEY_LEFT " : self . window . input . key_left ,
" KEY_RIGHT " : self . window . input . key_right ,
" KEY_UP " : self . window . input . key_up ,
" KEY_END " : self . window . input . key_end ,
" KEY_HOME " : self . window . input . key_home ,
" KEY_DOWN " : self . window . input . key_down ,
2010-06-10 01:17:59 +00:00
" KEY_PPAGE " : self . scroll_page_up ,
" KEY_NPAGE " : self . scroll_page_down ,
2010-01-27 22:29:28 +00:00
" KEY_DC " : self . window . input . key_dc ,
2010-01-28 00:55:02 +00:00
" KEY_F(5) " : self . rotate_rooms_left ,
" KEY_F(6) " : self . rotate_rooms_right ,
" kLFT5 " : self . rotate_rooms_left ,
" kRIT5 " : self . rotate_rooms_right ,
2010-02-12 02:32:50 +00:00
" \t " : self . auto_completion ,
2010-01-27 19:46:08 +00:00
" KEY_BACKSPACE " : self . window . input . key_backspace
}
2010-01-21 01:54:50 +00:00
self . handler = Handler ( )
self . handler . connect ( ' on-connected ' , self . on_connected )
self . handler . connect ( ' join-room ' , self . join_room )
self . handler . connect ( ' room-presence ' , self . room_presence )
self . handler . connect ( ' room-message ' , self . room_message )
2010-06-13 13:51:02 +00:00
self . handler . connect ( ' private-message ' , self . private_message )
2010-03-24 18:01:22 +00:00
self . handler . connect ( ' error-message ' , self . room_error )
2010-03-24 16:44:55 +00:00
self . handler . connect ( ' error ' , self . information )
2010-01-21 01:54:50 +00:00
2010-01-27 19:46:08 +00:00
def main_loop ( self , stdscr ) :
2010-05-18 13:29:02 +00:00
"""
main loop waiting for the user to press a key
"""
2010-01-27 19:46:08 +00:00
while 1 :
2010-06-10 01:17:59 +00:00
doupdate ( )
2010-01-31 01:22:39 +00:00
try :
key = stdscr . getkey ( )
except :
2010-02-02 19:13:14 +00:00
continue
2010-01-27 21:44:48 +00:00
if str ( key ) in self . key_func . keys ( ) :
2010-01-27 19:46:08 +00:00
self . key_func [ key ] ( )
2010-01-31 01:22:39 +00:00
elif str ( key ) == ' KEY_RESIZE ' :
self . window . resize ( stdscr )
2010-02-11 04:59:58 +00:00
self . window . refresh ( self . rooms )
2010-01-27 21:44:48 +00:00
elif len ( key ) > = 4 :
continue
2010-01-27 19:46:08 +00:00
elif ord ( key ) == 10 :
self . execute ( )
2010-01-27 22:32:20 +00:00
elif ord ( key ) == 8 or ord ( key ) == 127 :
2010-01-27 22:29:28 +00:00
self . window . input . key_backspace ( )
2010-01-27 23:02:12 +00:00
elif ord ( key ) < 32 :
continue
2010-01-27 19:46:08 +00:00
else :
2010-01-28 00:55:02 +00:00
if ord ( key ) == 27 and ord ( stdscr . getkey ( ) ) == 91 :
2010-05-11 10:38:57 +00:00
last = ord ( stdscr . getkey ( ) ) # FIXME: ugly ugly workaround.
2010-01-28 00:55:02 +00:00
if last == 51 :
self . window . input . key_dc ( )
continue
2010-01-27 22:37:40 +00:00
elif ord ( key ) > 190 and ord ( key ) < 225 :
2010-01-27 19:46:08 +00:00
key = key + stdscr . getkey ( )
elif ord ( key ) == 226 :
key = key + stdscr . getkey ( )
key = key + stdscr . getkey ( )
self . window . do_command ( key )
2010-01-26 17:10:37 +00:00
def current_room ( self ) :
2010-05-18 13:29:02 +00:00
"""
returns the current room , the one we are viewing
"""
2010-02-10 16:47:43 +00:00
return self . rooms [ 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 room in self . rooms :
if room . name == name :
return room
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-01-21 01:54:50 +00:00
curses . start_color ( )
curses . noecho ( )
2010-06-10 01:17:59 +00:00
curses . curs_set ( 0 )
2010-02-14 04:18:34 +00:00
curses . use_default_colors ( )
2010-01-27 19:46:08 +00:00
stdscr . keypad ( True )
2010-05-18 13:29:02 +00:00
curses . init_pair ( 1 , curses . COLOR_WHITE ,
curses . COLOR_BLUE )
2010-06-12 23:42:55 +00:00
curses . init_pair ( 4 , curses . COLOR_CYAN , - 1 )
curses . init_pair ( 2 , curses . COLOR_RED , - 1 ) # Admin
curses . init_pair ( 3 , curses . COLOR_BLUE , - 1 ) # Participant
2010-02-14 04:18:34 +00:00
curses . init_pair ( 5 , curses . COLOR_WHITE , - 1 ) # Visitor
curses . init_pair ( 6 , curses . COLOR_CYAN , - 1 )
curses . init_pair ( 7 , curses . COLOR_GREEN , - 1 )
curses . init_pair ( 8 , curses . COLOR_MAGENTA , - 1 )
curses . init_pair ( 9 , curses . COLOR_YELLOW , - 1 )
2010-05-18 13:29:02 +00:00
curses . init_pair ( 10 , curses . COLOR_WHITE ,
curses . COLOR_CYAN ) # current room
curses . init_pair ( 11 , curses . COLOR_WHITE ,
curses . COLOR_BLUE ) # normal room
curses . init_pair ( 12 , curses . COLOR_WHITE ,
curses . COLOR_MAGENTA ) # new message room
curses . init_pair ( 13 , curses . COLOR_WHITE ,
curses . COLOR_RED ) # highlight room
curses . init_pair ( 14 , curses . COLOR_WHITE ,
curses . COLOR_YELLOW )
2010-06-13 13:51:02 +00:00
curses . init_pair ( 15 , curses . COLOR_WHITE , # new message in private room
2010-05-18 13:29:02 +00:00
curses . COLOR_GREEN )
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 ( )
2010-01-27 17:02:13 +00:00
curses . endwin ( )
2010-01-26 17:10:37 +00:00
2010-01-29 16:24:44 +00:00
def on_connected ( self , jid ) :
2010-05-18 13:29:02 +00:00
"""
2010-06-12 14:14:52 +00:00
We are connected when authentification confirmation is received
2010-05-18 13:29:02 +00:00
"""
2010-01-31 05:33:54 +00:00
self . information ( _ ( " Welcome on Poezio \ o/! " ) )
self . information ( _ ( " Your JID is %s " ) % jid )
2010-01-21 01:54:50 +00:00
def join_room ( self , room , nick ) :
2010-05-18 13:29:02 +00:00
"""
join the specified room ( muc ) , using the specified nick
"""
2010-06-10 01:17:59 +00:00
r = Room ( room , nick , self . window )
2010-02-11 04:59:58 +00:00
self . current_room ( ) . set_color_state ( 11 )
if self . current_room ( ) . nb == 0 :
self . rooms . append ( r )
else :
for ro in self . rooms :
if ro . nb == 0 :
self . rooms . insert ( self . rooms . index ( ro ) , r )
break
while self . current_room ( ) . nb != r . nb :
self . rooms . insert ( 0 , self . rooms . pop ( ) )
self . window . refresh ( self . rooms )
2010-01-21 01:54:50 +00:00
2010-02-12 02:32:50 +00:00
def auto_completion ( self ) :
2010-05-18 13:29:02 +00:00
"""
Called when Tab is pressed , complete the nickname in the input
"""
2010-02-12 02:32:50 +00:00
self . window . input . auto_completion ( self . current_room ( ) . users )
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-02-11 04:59:58 +00:00
self . current_room ( ) . set_color_state ( 11 )
2010-01-21 01:54:50 +00:00
self . rooms . append ( self . rooms . pop ( 0 ) )
2010-02-11 04:59:58 +00:00
self . window . refresh ( self . rooms )
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-02-11 04:59:58 +00:00
self . current_room ( ) . set_color_state ( 11 )
2010-01-21 01:54:50 +00:00
self . rooms . insert ( 0 , self . rooms . pop ( ) )
2010-02-11 04:59:58 +00:00
self . window . refresh ( self . rooms )
2010-01-21 01:54:50 +00:00
2010-06-10 01:17:59 +00:00
def scroll_page_down ( self , args = None ) :
self . current_room ( ) . scroll_down ( )
2010-06-21 08:38:48 +00:00
self . window . refresh ( self . rooms )
2010-06-10 01:17:59 +00:00
def scroll_page_up ( self , args = None ) :
2010-06-10 12:56:11 +00:00
self . current_room ( ) . scroll_up ( self . window . size )
2010-06-21 08:38:48 +00:00
self . window . refresh ( self . rooms )
2010-06-10 01:17:59 +00:00
2010-03-24 18:01:22 +00:00
def room_error ( self , room , error , msg ) :
2010-05-18 13:29:02 +00:00
"""
Display the error on the room window
"""
2010-06-12 22:34:13 +00:00
if not error :
return
2010-05-18 13:29:02 +00:00
room = self . get_room_by_name ( room )
2010-03-24 18:01:22 +00:00
code = error . getAttr ( ' code ' )
typ = error . getAttr ( ' type ' )
2010-06-13 13:51:02 +00:00
if error . getTag ( ' text ' ) :
body = error . getTag ( ' text ' ) . getData ( )
else :
body = _ ( ' Unknown error ' )
2010-06-10 01:17:59 +00:00
self . add_message_to_room ( room , _ ( ' Error: %(code)s - %(msg)s : %(body)s ' %
{ ' msg ' : msg , ' code ' : code , ' body ' : body } ) )
2010-03-24 18:01:22 +00:00
if code == ' 401 ' :
2010-06-10 01:17:59 +00:00
room . add ( _ ( ' To provide a password in order to join the room, type " /join / password " (replace " password " by the real password) ' ) )
2010-06-21 08:38:48 +00:00
self . window . refresh ( self . rooms )
2010-03-24 18:01:22 +00:00
2010-06-13 13:51:02 +00:00
def private_message ( self , stanza ) :
"""
When a private message is received
"""
jid = stanza . getFrom ( )
nick_from = stanza . getFrom ( ) . getResource ( )
room_from = stanza . getFrom ( ) . getStripped ( )
room = self . get_room_by_name ( jid ) # 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 )
body = stanza . getBody ( )
self . add_message_to_room ( room , body , None , nick_from )
self . window . input . refresh ( )
doupdate ( )
def open_private_window ( self , room_name , user_nick , focus = True ) :
complete_jid = room_name + ' / ' + user_nick
for room in self . rooms : # if the room exists, focus it and return
if room . jid :
if room . jid == complete_jid :
self . command_win ( str ( room . nb ) )
return
# create the new tab
own_nick = self . get_room_by_name ( room_name ) . own_nick
r = Room ( complete_jid , own_nick , self . window , complete_jid )
# insert it in the rooms
if self . current_room ( ) . nb == 0 :
self . rooms . append ( r )
else :
for ro in self . rooms :
if ro . nb == 0 :
self . rooms . insert ( self . rooms . index ( ro ) , r )
break
if focus : # focus the room if needed
while self . current_room ( ) . nb != r . nb :
self . rooms . insert ( 0 , self . rooms . pop ( ) )
# self.window.new_room(r)
self . window . refresh ( self . rooms )
return r
2010-03-18 19:43:44 +00:00
def room_message ( self , stanza , date = None ) :
2010-05-18 13:29:02 +00:00
"""
Display the message on the room window
"""
2010-03-19 03:30:51 +00:00
delay_tag = stanza . getTag ( ' delay ' , namespace = ' urn:xmpp:delay ' )
if delay_tag and not date :
delayed = True
date = common . datetime_tuple ( delay_tag . getAttr ( ' stamp ' ) )
else :
delayed = False
2010-01-21 01:54:50 +00:00
if stanza . getType ( ) != ' groupchat ' :
return # ignore all messages not comming from a MUC
nick_from = stanza . getFrom ( ) . getResource ( )
2010-03-18 19:43:44 +00:00
room_from = stanza . getFrom ( ) . getStripped ( )
2010-06-12 17:28:51 +00:00
if ( self . ignores . has_key ( room_from ) ) 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-01-26 17:10:37 +00:00
if not room :
2010-02-10 16:47:43 +00:00
self . information ( _ ( " message received for a non-existing room: %s " ) % ( room_from ) )
2010-01-28 00:55:02 +00:00
return
2010-01-26 19:33:40 +00:00
body = stanza . getBody ( )
2010-02-14 04:30:04 +00:00
subject = stanza . getSubject ( )
if subject :
2010-02-14 04:41:14 +00:00
if nick_from :
2010-06-10 01:17:59 +00:00
self . add_message_to_room ( room , _ ( " %(nick)s changed the subject to: %(subject)s " ) % { ' nick ' : nick_from , ' subject ' : subject } , date )
2010-02-14 04:41:14 +00:00
else :
2010-06-10 01:17:59 +00:00
self . add_message_to_room ( room , _ ( " The subject is: %(subject)s " ) % { ' subject ' : subject } , date )
2010-02-14 04:30:04 +00:00
room . topic = subject . encode ( ' utf-8 ' ) . replace ( ' \n ' , ' | ' )
2010-01-28 00:55:02 +00:00
if room == self . current_room ( ) :
self . window . topic_win . refresh ( room . topic )
2010-05-11 16:45:14 +00:00
elif body :
2010-03-18 19:43:44 +00:00
if body . startswith ( ' /me ' ) :
2010-06-13 00:09:28 +00:00
self . add_message_to_room ( room , " * " + nick_from + ' ' + body [ 4 : ] , date )
2010-02-14 13:33:33 +00:00
else :
2010-06-10 01:17:59 +00:00
date = date if delayed == True else None
self . add_message_to_room ( room , body , date , nick_from )
2010-06-21 08:38:48 +00:00
self . window . refresh ( self . rooms )
2010-06-10 01:17:59 +00:00
doupdate ( )
2010-01-21 01:54:50 +00:00
def room_presence ( self , stanza ) :
2010-05-18 13:29:02 +00:00
"""
Display the presence on the room window and update the
presence information of the concerned user
"""
2010-01-21 01:54:50 +00:00
from_nick = stanza . getFrom ( ) . getResource ( )
from_room = stanza . getFrom ( ) . getStripped ( )
2010-01-26 19:33:40 +00:00
room = self . get_room_by_name ( from_room )
2010-01-26 17:10:37 +00:00
if not room :
2010-03-24 16:44:55 +00:00
return
2010-01-31 00:25:17 +00:00
else :
2010-03-18 19:43:44 +00:00
msg = None
affiliation = stanza . getAffiliation ( )
show = stanza . getShow ( )
status = stanza . getStatus ( )
role = stanza . getRole ( )
if not room . joined : # user in the room BEFORE us.
2010-05-18 13:29:02 +00:00
room . users . append ( User ( from_nick , affiliation , show , status ,
role ) )
2010-03-18 19:43:44 +00:00
if from_nick . encode ( ' utf-8 ' ) == room . own_nick :
room . joined = True
2010-06-10 01:17:59 +00:00
self . add_message_to_room ( room , _ ( " Your nickname is %s " ) % ( from_nick ) )
2010-03-18 19:43:44 +00:00
else :
2010-06-13 00:09:28 +00:00
self . add_message_to_room ( room , _ ( " %s is in the room " ) % ( from_nick ) )
2010-03-18 19:43:44 +00:00
else :
change_nick = stanza . getStatusCode ( ) == ' 303 '
kick = stanza . getStatusCode ( ) == ' 307 '
user = room . get_user_by_name ( from_nick )
# New user
if not user :
2010-05-18 13:29:02 +00:00
room . users . append ( User ( from_nick , affiliation ,
show , status , role ) )
2010-05-11 16:45:14 +00:00
hide_exit_join = config . get ( ' hide_exit_join ' , - 1 )
if hide_exit_join != 0 :
2010-06-10 01:17:59 +00:00
self . add_message_to_room ( room , _ ( " %(nick)s joined the room %(roomname)s " ) % { ' nick ' : from_nick , ' roomname ' : room . name } )
2010-03-18 19:43:44 +00:00
# nick change
elif change_nick :
if user . nick == room . own_nick :
room . own_nick = stanza . getNick ( ) . encode ( ' utf-8 ' )
2010-06-13 13:51:02 +00:00
# also change our nick in all private discussion of this room
for _room in self . rooms :
if _room . jid is not None and is_jid_the_same ( _room . jid , room . name ) :
_room . own_nick = stanza . getNick ( )
2010-03-18 19:43:44 +00:00
user . change_nick ( stanza . getNick ( ) )
2010-06-10 01:17:59 +00:00
self . add_message_to_room ( room , _ ( ' %(old)s is now known as %(new)s ' ) % { ' old ' : from_nick , ' new ' : stanza . getNick ( ) } )
2010-06-13 13:51:02 +00:00
# rename the private tabs if needed
private_room = self . get_room_by_name ( stanza . getFrom ( ) )
if private_room :
self . add_message_to_room ( private_room , _ ( ' %(old_nick)s is now known as %(new_nick)s ' ) % { ' old_nick ' : from_nick , ' new_nick ' : stanza . getNick ( ) } )
new_jid = private_room . name . split ( ' / ' ) [ 0 ] + ' / ' + stanza . getNick ( )
private_room . jid = new_jid
private_room . name = new_jid
2010-03-18 19:43:44 +00:00
# kick
elif kick :
room . users . remove ( user )
2010-03-24 16:44:55 +00:00
try :
reason = stanza . getReason ( ) . encode ( ' utf-8 ' )
except :
reason = ' '
2010-03-18 19:43:44 +00:00
try :
by = stanza . getActor ( ) . encode ( ' utf-8 ' )
except :
by = None
if from_nick == room . own_nick : # we are kicked
room . disconnect ( )
if by :
2010-06-10 01:17:59 +00:00
self . add_message_to_room ( room , _ ( " You have been kicked by %(by)s . Reason: %(reason)s " ) % { ' by ' : by , ' reason ' : reason } )
2010-03-18 19:43:44 +00:00
else :
2010-06-16 09:47:52 +00:00
self . add_message_to_room ( room , _ ( " You have been kicked. Reason: %s " ) % ( reason . encode ( ' utf-8 ' ) ) )
2010-03-18 19:43:44 +00:00
else :
if by :
2010-06-10 01:17:59 +00:00
self . add_message_to_room ( room , _ ( " %(nick)s has been kicked by %(by)s . Reason: %(reason)s " ) % { ' nick ' : from_nick , ' by ' : by , ' reason ' : reason } )
2010-03-18 19:43:44 +00:00
else :
2010-06-10 01:17:59 +00:00
self . add_message_to_room ( room , _ ( " %(nick)s has been kicked. Reason: %(reason)s " ) % { ' nick ' : from_nick , ' reason ' : reason } )
2010-03-18 19:43:44 +00:00
# user quit
elif status == ' offline ' or role == ' none ' :
room . users . remove ( user )
2010-06-10 01:17:59 +00:00
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 ) :
self . add_message_to_room ( room , _ ( ' %s has left the room ' ) % ( from_nick ) )
2010-06-13 13:51:02 +00:00
private_room = self . get_room_by_name ( stanza . getFrom ( ) )
if private_room :
self . add_message_to_room ( private_room , _ ( ' %s has left the room ' ) % ( from_nick ) )
2010-03-18 19:43:44 +00:00
# status change
else :
2010-06-13 13:51:02 +00:00
# build the message
msg = _ ( ' %s changed his/her status: ' ) % from_nick
if affiliation != user . affiliation :
msg + = _ ( ' affiliation: %s , ' ) % affiliation
if role != user . role :
msg + = _ ( ' role: %s , ' ) % role
if show != user . show :
msg + = _ ( ' show: %s , ' ) % show
if status != user . status :
msg + = _ ( ' status: %s , ' ) % status
msg = msg [ : - 1 ] # remove the last ","
2010-06-10 01:17:59 +00:00
hide_status_change = config . get ( ' hide_status_change ' , - 1 ) if config . get ( ' hide_status_change ' , - 1 ) > = - 1 else - 1
2010-06-13 01:50:28 +00:00
if ( hide_status_change == - 1 or \
2010-05-11 16:45:14 +00:00
user . has_talked_since ( hide_status_change ) or \
2010-06-13 01:50:28 +00:00
user . nick == room . own_nick ) \
and \
( affiliation != user . affiliation or \
role != user . role or \
show != user . show or \
status != user . status ) :
2010-06-13 13:51:02 +00:00
# display the message in the room
2010-06-13 01:50:28 +00:00
self . add_message_to_room ( room , msg )
2010-06-13 13:51:02 +00:00
private_room = self . get_room_by_name ( stanza . getFrom ( ) )
if private_room : # display the message in private
self . add_message_to_room ( private_room , msg )
# finally, effectively change the user status
user . update ( affiliation , show , status , role )
2010-02-13 01:08:44 +00:00
if room == self . current_room ( ) :
self . window . user_win . refresh ( room . users )
2010-03-19 02:06:51 +00:00
self . window . input . refresh ( )
2010-06-10 01:17:59 +00:00
doupdate ( )
2010-03-18 19:43:44 +00:00
2010-06-10 01:17:59 +00:00
def add_message_to_room ( self , room , txt , time = None , nickname = None ) :
2010-03-18 19:43:44 +00:00
"""
2010-06-10 01:17:59 +00:00
Add the message to the room and refresh the associated component
of the interface
2010-03-18 19:43:44 +00:00
"""
2010-06-10 01:17:59 +00:00
room . add_message ( txt , time , nickname )
2010-03-18 19:43:44 +00:00
if room == self . current_room ( ) :
2010-06-10 01:17:59 +00:00
self . window . text_win . refresh ( room )
else :
2010-03-19 02:06:51 +00:00
self . window . info_win . refresh ( self . rooms , self . current_room ( ) )
2010-06-21 08:38:48 +00:00
self . window . input . refresh ( )
2010-01-13 01:04:30 +00:00
def execute ( self ) :
2010-05-18 13:29:02 +00:00
"""
Execute the / command or just send the line on the current room
"""
2010-01-21 01:54:50 +00:00
line = self . window . input . get_text ( )
self . window . input . clear_text ( )
2010-01-30 03:06:38 +00:00
self . window . input . refresh ( )
2010-01-21 01:54:50 +00:00
if line == " " :
return
2010-06-13 14:09:50 +00:00
if line . startswith ( ' / ' ) and not line . startswith ( ' /me ' ) :
2010-01-13 01:04:30 +00:00
command = line . strip ( ) [ : ] . split ( ) [ 0 ] [ 1 : ]
args = line . strip ( ) [ : ] . split ( ) [ 1 : ]
if command in self . commands . keys ( ) :
2010-01-30 04:42:29 +00:00
func = self . commands [ command ] [ 0 ]
2010-01-13 01:04:30 +00:00
func ( args )
2010-01-27 22:29:28 +00:00
return
2010-02-16 02:03:23 +00:00
else :
2010-06-10 01:17:59 +00:00
self . add_message_to_room ( self . current_room ( ) , _ ( " Error: unknown command ( %s ) " ) % ( command ) )
2010-02-16 02:03:23 +00:00
elif self . current_room ( ) . name != ' Info ' :
2010-06-13 13:51:02 +00:00
if self . current_room ( ) . jid is not None :
self . muc . send_private_message ( self . current_room ( ) . name , line )
self . add_message_to_room ( self . current_room ( ) , line . decode ( ' utf-8 ' ) , None , self . current_room ( ) . own_nick )
else :
self . muc . send_message ( self . current_room ( ) . name , line )
2010-03-18 19:43:44 +00:00
self . window . input . refresh ( )
2010-06-10 01:17:59 +00:00
doupdate ( )
2010-01-13 01:04:30 +00:00
2010-01-30 04:42:29 +00:00
def command_help ( self , args ) :
2010-05-18 13:29:02 +00:00
"""
/ help < command_name >
"""
2010-01-30 04:42:29 +00:00
room = self . current_room ( )
if len ( args ) == 0 :
2010-06-13 00:09:28 +00:00
msg = _ ( ' Available commands are: ' )
2010-01-30 04:42:29 +00:00
for command in self . 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-01-30 04:42:29 +00:00
if len ( args ) == 1 :
if args [ 0 ] in self . commands . keys ( ) :
msg = self . commands [ args [ 0 ] ] [ 1 ]
else :
2010-01-31 05:33:54 +00:00
msg = _ ( ' Unknown command: %s ' ) % args [ 0 ]
2010-06-10 01:17:59 +00:00
self . add_message_to_room ( room , msg )
2010-01-30 04:42:29 +00:00
2010-02-12 02:50:07 +00:00
def command_win ( self , args ) :
2010-05-18 13:29:02 +00:00
"""
/ win < number >
"""
2010-02-12 02:50:07 +00:00
if len ( args ) != 1 :
self . command_help ( [ ' win ' ] )
return
try :
nb = int ( args [ 0 ] )
except ValueError :
self . command_help ( [ ' win ' ] )
return
if self . current_room ( ) . nb == nb :
return
self . current_room ( ) . set_color_state ( 11 )
start = self . current_room ( )
self . rooms . append ( self . rooms . pop ( 0 ) )
while self . current_room ( ) . nb != nb :
self . rooms . append ( self . rooms . pop ( 0 ) )
if self . current_room ( ) == start :
self . window . refresh ( self . rooms )
return
self . window . refresh ( self . rooms )
2010-02-02 23:57:32 +00:00
def command_kick ( self , args ) :
2010-05-18 13:29:02 +00:00
"""
/ kick < nick > [ reason ]
"""
2010-02-02 23:57:32 +00:00
if len ( args ) < 1 :
self . command_help ( [ ' kick ' ] )
return
nick = args [ 0 ]
if len ( args ) > = 2 :
reason = ' ' . join ( args [ 1 : ] )
else :
reason = ' '
if self . current_room ( ) . name == ' Info ' or not self . current_room ( ) . joined :
return
roomname = self . current_room ( ) . name
self . muc . eject_user ( roomname , ' kick ' , nick , reason )
2010-01-13 01:04:30 +00:00
def command_join ( self , args ) :
2010-05-18 13:29:02 +00:00
"""
/ join [ room ] [ / nick ] [ password ]
"""
2010-03-24 18:01:22 +00:00
password = None
2010-01-30 04:02:23 +00:00
if len ( args ) == 0 :
r = self . current_room ( )
if r . name == ' Info ' :
return
room = r . name
nick = r . own_nick
2010-01-30 02:50:24 +00:00
else :
2010-01-30 04:02:23 +00:00
info = args [ 0 ] . split ( ' / ' )
if len ( info ) == 1 :
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 :
nick = info [ 1 ]
2010-01-31 03:07:30 +00:00
if info [ 0 ] == ' ' : # happens with /join /nickname, which is OK
2010-01-30 04:02:23 +00:00
r = self . current_room ( )
if r . name == ' Info ' :
return
room = r . name
2010-03-24 18:01:22 +00:00
if nick == ' ' :
nick = r . own_nick
2010-01-30 04:02:23 +00:00
else :
room = info [ 0 ]
2010-06-21 08:38:48 +00:00
# if len(room.split('@')) == 1: # no server is provided, like "/join hello"
# serv = self.current_room().name.split('/')[0]
# room += '@' + self.current_room.
2010-01-30 04:02:23 +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-01-30 02:50:24 +00:00
if r and r . joined : # if we are already in the room
2010-01-31 05:33:54 +00:00
self . information ( _ ( " already in room [ %s ] " ) % room )
2010-01-28 00:55:02 +00:00
return
2010-03-24 18:01:22 +00:00
self . muc . join_room ( room , nick , password )
2010-03-24 16:44:55 +00:00
if not r : # if the room window exists, we don't recreate it.
2010-01-30 02:50:24 +00:00
self . join_room ( room , nick )
2010-03-24 16:44:55 +00:00
else :
2010-06-13 00:45:45 +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-01-31 03:42:25 +00:00
def command_bookmark ( self , args ) :
2010-05-18 13:29:02 +00:00
"""
/ bookmark [ room ] [ / nick ]
"""
2010-01-31 03:42:25 +00:00
nick = None
if len ( args ) == 0 :
room = self . current_room ( )
if room . name == ' Info ' :
return
roomname = room . name
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_room ( ) . 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 )
2010-02-10 16:47:43 +00:00
config . set_and_save ( ' rooms ' , bookmarked + ' : ' + res )
2010-01-31 03:42:25 +00:00
2010-02-02 23:35:01 +00:00
def command_set ( self , args ) :
2010-05-18 13:29:02 +00:00
"""
/ set < option > [ value ]
"""
2010-02-12 19:35:18 +00:00
if len ( args ) != 2 and len ( args ) != 1 :
2010-02-02 23:35:01 +00:00
self . command_help ( [ ' set ' ] )
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 )
room = self . current_room ( )
2010-06-10 01:17:59 +00:00
self . add_message_to_room ( room , msg )
2010-02-02 23:35:01 +00:00
2010-01-31 00:25:17 +00:00
def command_show ( self , args ) :
2010-05-18 13:29:02 +00:00
"""
/ show < status > [ msg ]
"""
2010-01-31 03:07:30 +00:00
possible_show = { ' avail ' : ' None ' ,
' available ' : ' None ' ,
' ok ' : ' None ' ,
' here ' : ' None ' ,
' chat ' : ' chat ' ,
' away ' : ' away ' ,
' afk ' : ' away ' ,
' dnd ' : ' dnd ' ,
' busy ' : ' dnd ' ,
' xa ' : ' xa '
}
if len ( args ) < 1 :
return
if not args [ 0 ] in possible_show . keys ( ) :
self . command_help ( [ ' show ' ] )
return
show = possible_show [ args [ 0 ] ]
if len ( args ) > 1 :
msg = ' ' . join ( args [ 1 : ] )
else :
msg = None
for room in self . rooms :
if room . joined :
self . muc . change_show ( room . name , room . own_nick , show , msg )
2010-05-18 13:29:02 +00:00
def command_ignore ( self , args ) :
"""
/ ignore < nick >
"""
if len ( args ) != 1 :
2010-06-12 17:28:51 +00:00
self . command_help ( [ ' ignore ' ] )
return
if self . current_room ( ) . name == ' Info ' or not self . current_room ( ) . joined :
2010-05-18 13:29:02 +00:00
return
2010-06-12 17:28:51 +00:00
roomname = self . current_room ( ) . name
nick = args [ 0 ]
if not self . ignores . has_key ( roomname ) :
self . ignores [ roomname ] = set ( ) # no need for any order
if nick not in self . ignores [ roomname ] :
self . ignores [ roomname ] . add ( nick )
self . add_message_to_room ( self . current_room ( ) , _ ( " %s is now ignored " ) % nick )
else :
self . add_message_to_room ( self . current_room ( ) , _ ( " %s is already ignored " ) % nick )
2010-05-18 13:29:02 +00:00
def command_unignore ( self , args ) :
"""
/ unignore < nick >
"""
if len ( args ) != 1 :
2010-06-12 17:28:51 +00:00
self . command_help ( [ ' unignore ' ] )
return
if self . current_room ( ) . name == ' Info ' or not self . current_room ( ) . joined :
return
roomname = self . current_room ( ) . name
nick = args [ 0 ]
if not self . ignores . has_key ( roomname ) or ( nick not in self . ignores [ roomname ] ) :
self . add_message_to_room ( self . current_room ( ) , _ ( " %s was not ignored " ) % nick )
2010-05-18 13:29:02 +00:00
return
2010-06-12 17:28:51 +00:00
self . ignores [ roomname ] . remove ( nick )
if self . ignores [ roomname ] == set ( ) :
del self . ignores [ roomname ]
self . add_message_to_room ( self . current_room ( ) , _ ( " %s is now unignored " ) % nick )
2010-05-18 13:29:02 +00:00
2010-01-31 03:07:30 +00:00
def command_away ( self , args ) :
2010-05-18 13:29:02 +00:00
"""
/ away [ msg ]
"""
2010-01-31 03:07:30 +00:00
args . insert ( 0 , ' away ' )
self . command_show ( args )
def command_busy ( self , args ) :
2010-05-18 13:29:02 +00:00
"""
/ busy [ msg ]
"""
2010-01-31 03:07:30 +00:00
args . insert ( 0 , ' busy ' )
self . command_show ( args )
def command_avail ( self , args ) :
2010-05-18 13:29:02 +00:00
"""
/ avail [ msg ]
"""
2010-01-31 03:07:30 +00:00
args . insert ( 0 , ' available ' )
self . command_show ( args )
2010-01-31 00:25:17 +00:00
2010-01-30 04:02:23 +00:00
def command_part ( self , args ) :
2010-05-18 13:29:02 +00:00
"""
/ part [ msg ]
"""
2010-01-30 04:02:23 +00:00
reason = None
room = self . current_room ( )
if room . name == ' Info ' :
return
if len ( args ) :
msg = ' ' . join ( args )
else :
msg = None
2010-01-30 04:42:29 +00:00
if room . joined :
self . muc . quit_room ( room . name , room . own_nick , msg )
2010-01-30 04:02:23 +00:00
self . rooms . remove ( self . current_room ( ) )
2010-02-11 04:59:58 +00:00
self . window . refresh ( self . rooms )
2010-01-30 04:02:23 +00:00
2010-06-21 08:46:06 +00:00
def command_unquery ( self , args ) :
"""
/ unquery
"""
room = self . current_room ( )
if room . jid is not None :
self . rooms . remove ( room )
self . window . refresh ( self . rooms )
2010-06-13 13:51:02 +00:00
def command_query ( self , args ) :
2010-06-13 16:01:38 +00:00
"""
/ query
"""
2010-06-13 13:51:02 +00:00
if len ( args ) != 1 :
return
nick = args [ 0 ]
room = self . current_room ( )
if room . name == " Info " or room . jid is not None :
return
for user in room . users :
if user . nick == nick :
self . open_private_window ( room . name , user . nick )
2010-03-19 03:37:34 +00:00
def command_topic ( self , args ) :
2010-05-18 13:29:02 +00:00
"""
/ topic [ new topic ]
"""
2010-03-19 03:37:34 +00:00
room = self . current_room ( )
2010-06-10 12:28:25 +00:00
if len ( args ) == 0 :
2010-06-13 16:06:48 +00:00
self . add_message_to_room ( room , _ ( " The subject of the room is: %s " ) % room . topic . decode ( ' utf-8 ' ) )
2010-06-10 12:28:25 +00:00
subject = ' ' . join ( args )
2010-03-19 03:37:34 +00:00
if not room . joined or room . name == " Info " :
return
self . muc . change_subject ( room . name , subject )
2010-01-30 03:06:38 +00:00
def command_nick ( self , args ) :
2010-05-18 13:29:02 +00:00
"""
/ nick < nickname >
"""
2010-01-30 03:06:38 +00:00
if len ( args ) != 1 :
return
nick = args [ 0 ]
room = self . current_room ( )
if not room . joined or room . name == " Info " :
return
self . muc . change_nick ( room . name , nick )
2010-01-28 00:55:02 +00:00
def information ( self , msg ) :
2010-05-18 13:29:02 +00:00
"""
Displays an informational message in the " Info " room window
"""
2010-01-28 00:55:02 +00:00
room = self . get_room_by_name ( " Info " )
2010-06-10 01:17:59 +00:00
self . add_message_to_room ( room , msg )
2010-06-21 08:38:48 +00:00
self . window . input . refresh ( )
2010-01-28 00:55:02 +00:00
2010-01-13 01:04:30 +00:00
def command_quit ( self , args ) :
2010-05-18 13:29:02 +00:00
"""
/ quit
"""
2010-06-13 15:40:03 +00:00
if len ( args ) :
msg = ' ' . join ( args )
else :
msg = None
if msg :
self . muc . disconnect ( self . rooms , msg )
sleep ( 0.2 ) # :(
2010-01-26 17:10:37 +00:00
self . reset_curses ( )
2010-01-13 01:04:30 +00:00
sys . exit ( )