gui.py 31.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#!/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/>.

20 21
from gettext import (bindtextdomain, textdomain, bind_textdomain_codeset,
                     gettext as _)
22

23 24 25 26
bindtextdomain('poezio')
textdomain('poezio')
bind_textdomain_codeset('poezio', 'utf-8')

27
import locale
28 29 30 31
locale.setlocale(locale.LC_ALL, '')
import sys

import curses
32
from datetime import datetime
33 34

import common
35

36
from handler import Handler
37
from config import config
38
from window import Window
39 40
from user import User
from room import Room
41 42 43 44 45 46
from message import Message

from common import debug
def doupdate():
    debug("doupdate")
    curses.doupdate()
47

48 49
class Gui(object):
    """
50
    User interface using ncurses
51
    """
52 53 54 55
    def __init__(self, stdscr=None, muc=None):
        self.init_curses(stdscr)
        self.stdscr = stdscr
        self.window = Window(stdscr)
56 57 58
        # self.window.new_room(self.current_room())
        # self.window.refresh(self.rooms)
        self.rooms = [Room('Info', '', self.window)]
59

60
        self.muc = muc
61

62
        self.commands = {
63
            'help': (self.command_help, _('That.')),
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
            'join': (self.command_join, _("""Usage: /join [room_name][/nick]
[password]\nJoin: Join the specified room. You can specify a nickname after a
 slash (/). If no nickname is specified, you will use the default_nick in the
 configuration file. You can omit the room name: you will then join the room
 you\'re looking at (useful if you were kicked). You can also provide a password
 to join the room.\nExamples:\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\nQuit: Just
 disconnect from the server and exit poezio.""")),
            'exit': (self.command_quit, _("""Usage: /exit\nExit: Just
 disconnect from the server and exit poezio.""")),
            'next': (self.rotate_rooms_right, _("""Usage: /next\nNext:
 Go to the next room.""")),
            'n': (self.rotate_rooms_right, _("""Usage: /n\nN: Go to the
 next room.""")),
            'prev': (self.rotate_rooms_left, _("""Usage: /prev\nPrev:
 Go to the previous room.""")),
            'p': (self.rotate_rooms_left, _("""Usage: /p\nP: Go to the
 previous room.""")),
            'win': (self.command_win, _("""Usage: /win <number>\nWin: Go
 to the specified room.""")),
            'w': (self.command_win, _("""Usage: /w <number>\nW: Go to
 the specified room.""")),
            'ignore': (self.command_ignore, _("""Usage: /ignore <nickname>
\Ignore: Ignore a specified nickname.""")),
            'unignore': (self.command_unignore, _("""Usage: /unignore
 <nickname>\Unignore: Remove the specified nickname from the ignore list.""")),
            'part': (self.command_part, _("""Usage: /part [message]\n
Part: disconnect from a room. You can specify an optional message.""")),
            'show': (self.command_show, _("""Usage: /show <availability>
 [status]\nShow: Change your availability and (optionaly) your status.
 The <availability> argument is one of "avail, available, ok, here,
 chat, away, afk, dnd, busy, xa" and the optional [message] argument
 will be your status message""")),
            'away': (self.command_away, _("""Usage: /away [message]\nAway:
 Sets your availability to away and (optional) sets your status message.
 This is equivalent to '/show away [message]'""")),
            'busy': (self.command_busy, _("""Usage: /busy [message]\nBusy:
 Sets your availability to busy and (optional) sets your status message.
 This is equivalent to '/show busy [message]'""")),
            'avail': (self.command_avail, _("""Usage: /avail [message]\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]\nAvailable: Sets your availability to available and (optional)
 sets your status message. This is equivalent to '/show
 available [message]'""")),
           'bookmark': (self.command_bookmark, _("""Usage: /bookmark
 [roomname][/nick]\nBookmark: Bookmark the specified room (you will
 then auto-join it on each poezio start). This commands uses the same
 syntaxe as /join. Type /help join for syntaxe examples. Note that when
 typing "/bookmark" on its own, the room will be bookmarked with the nickname
 you\'re currently using in this room (instead of default_nick)""")),
            'set': (self.command_set, _("""Usage: /set <option>
 [value]\nSet: Sets the value to the option in your configuration
 file. You can, for example, change your default nickname by doing
 `/set default_nick toto` or your resource with `/set resource blabla`.
 You can also set an empty value (nothing) by providing no [value]
 after <option>.""")),
            'kick': (self.command_kick, _("""Usage: /kick <nick>
 [reason]\nKick: Kick the user with the specified nickname.
 You also can give an optional reason.""")),
            'topic': (self.command_topic, _("""Usage: /topic <subject>
\nTopic: Change the subject of the room""")),
            'nick': (self.command_nick, _("""Usage: /nick <nickname>
\nNick: Change your nickname in the current room"""))
131 132
            }

133 134 135 136 137 138 139
        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,
140 141
            "KEY_PPAGE": self.scroll_page_up,
            "KEY_NPAGE": self.scroll_page_down,
142
            "KEY_DC": self.window.input.key_dc,
143 144 145 146
            "KEY_F(5)": self.rotate_rooms_left,
            "KEY_F(6)": self.rotate_rooms_right,
            "kLFT5": self.rotate_rooms_left,
            "kRIT5": self.rotate_rooms_right,
147
            "\t": self.auto_completion,
148 149 150
            "KEY_BACKSPACE": self.window.input.key_backspace
            }

151 152 153 154 155
        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)
156
        self.handler.connect('error-message', self.room_error)
157
        self.handler.connect('error', self.information)
158

159
    def main_loop(self, stdscr):
160 161 162
        """
        main loop waiting for the user to press a key
        """
163
        while 1:
164 165
            # stdscr.leaveok(1)
            doupdate()
166 167 168
            try:
                key = stdscr.getkey()
            except:
169
                continue
170 171
            from common import debug
            # debug(str(key))
172
            if str(key) in self.key_func.keys():
173
                self.key_func[key]()
174 175
            elif str(key) == 'KEY_RESIZE':
                self.window.resize(stdscr)
176
                self.window.refresh(self.rooms)
177 178
            elif len(key) >= 4:
                continue
179 180
            elif ord(key) == 10:
                self.execute()
181
            elif ord(key) == 8 or ord(key) == 127:
182
                self.window.input.key_backspace()
183 184
            elif ord(key) < 32:
                continue
185
            else:
186
                if ord(key) == 27 and ord(stdscr.getkey()) == 91:
187
                    last = ord(stdscr.getkey()) # FIXME: ugly ugly workaround.
188 189 190
                    if last == 51:
                        self.window.input.key_dc()
                    continue
191
                elif ord(key) > 190 and ord(key) < 225:
192 193 194 195 196 197
                    key = key+stdscr.getkey()
                elif ord(key) == 226:
                    key = key+stdscr.getkey()
                    key = key+stdscr.getkey()
                self.window.do_command(key)

198 199 200 201 202 203 204
    # def next_room_number(self):
    #     """
    #     Increments the room number and returns the new number
    #     """
    #     nb = self.room_number
    #     self.room_number += 1
    #     return nb
205

206
    def current_room(self):
207 208 209
        """
        returns the current room, the one we are viewing
        """
210
        return self.rooms[0]
211 212

    def get_room_by_name(self, name):
213 214 215 216 217 218 219
        """
        returns the room that has this name
        """
        for room in self.rooms:
            if room.name == name:
                return room
        return None
220

221
    def init_curses(self, stdscr):
222 223 224
        """
        ncurses initialization
        """
225 226
        curses.start_color()
        curses.noecho()
227
        curses.curs_set(0)
228 229
        # curses.cbreak()
        # curses.raw()
230
        curses.use_default_colors()
231
        stdscr.keypad(True)
232 233
        curses.init_pair(1, curses.COLOR_WHITE,
                         curses.COLOR_BLUE)
234 235 236 237 238 239 240 241
        curses.init_pair(2, curses.COLOR_BLUE, -1)
        curses.init_pair(3, curses.COLOR_RED, -1) # Admin
        curses.init_pair(4, curses.COLOR_BLUE, -1) # Participant
        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)
242 243 244 245 246 247 248 249 250 251 252 253
        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)
        curses.init_pair(15, curses.COLOR_WHITE,
                         curses.COLOR_GREEN)
254

255
    def reset_curses(self):
256 257 258 259 260
        """
        Reset terminal capabilities to what they were before ncurses
        init
        """
        curses.echo()
261
        curses.nocbreak()
262
        curses.endwin()
263

264
    def on_connected(self, jid):
265
        """
266
        We are connected when authentification confirmation is received
267
        """
268 269
        self.information(_("Welcome on Poezio \o/!"))
        self.information(_("Your JID is %s") % jid)
270 271

    def join_room(self, room, nick):
272 273 274
        """
        join the specified room (muc), using the specified nick
        """
275
        r = Room(room, nick, self.window)
276 277 278 279 280 281 282 283 284 285
        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())
286
        # self.window.new_room(r)
287
        self.window.refresh(self.rooms)
288

289
    def auto_completion(self):
290 291 292
        """
        Called when Tab is pressed, complete the nickname in the input
        """
293 294
        self.window.input.auto_completion(self.current_room().users)

295
    def rotate_rooms_right(self, args=None):
296 297 298
        """
        rotate the rooms list to the right
        """
299
        self.current_room().set_color_state(11)
300
        self.rooms.append(self.rooms.pop(0))
301
        self.window.refresh(self.rooms)
302

303
    def rotate_rooms_left(self, args=None):
304 305 306
        """
        rotate the rooms list to the right
        """
307
        self.current_room().set_color_state(11)
308
        self.rooms.insert(0, self.rooms.pop())
309
        self.window.refresh(self.rooms)
310

311 312 313 314 315
    def scroll_page_down(self, args=None):
        self.current_room().scroll_down()
        self.window.text_win.refresh(self.current_room())

    def scroll_page_up(self, args=None):
316
        self.current_room().scroll_up(self.window.size)
317 318
        self.window.text_win.refresh(self.current_room())

319
    def room_error(self, room, error, msg):
320 321 322 323
        """
        Display the error on the room window
        """
        room = self.get_room_by_name(room)
324 325 326
        code = error.getAttr('code')
        typ = error.getAttr('type')
        body = error.getTag('text').getData()
327 328
        self.add_message_to_room(room, _('Error: %(code)s-%(msg)s: %(body)s' %
                                   {'msg':msg, 'code':code, 'body':body}))
329
        if code == '401':
330
            room.add(_('To provide a password in order to join the room, type "/join / password" (replace "password" by the real password)'))
331

332
    def room_message(self, stanza, date=None):
333 334 335
        """
        Display the message on the room window
        """
336 337 338 339 340 341
        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
342 343 344
        if stanza.getType() != 'groupchat':
            return  # ignore all messages not comming from a MUC
        nick_from = stanza.getFrom().getResource()
345 346
        room_from = stanza.getFrom().getStripped()
        room = self.get_room_by_name(room_from)
347
	if not room:
348
	    self.information(_("message received for a non-existing room: %s") % (room_from))
349
            return
350
        body = stanza.getBody()
351 352
        subject = stanza.getSubject()
        if subject:
353
            if nick_from:
354 355 356
                self.add_message_to_room(room, _("%(nick)s changed the subject to: %(subject)s") % {'nick':nick_from, 'subject':subject}, date)
 #                self.add_info(room, _("""%(nick)s changed the subject to:
 # %(subject)s""") % {'nick':nick_from, 'subject':subject}, date)
357
            else:
358 359 360
                self.add_message_to_room(room, _("The subject is: %(subject)s") % {'subject':subject}, date)
                # self.add_info(room, _("The subject is: %(subject)s") %
                #               {'subject':subject}, date)
361
            room.topic = subject.encode('utf-8').replace('\n', '|')
362 363
            if room == self.current_room():
                self.window.topic_win.refresh(room.topic)
364
        elif body:
365
            if body.startswith('/me '):
366 367 368
                # FIXME, it should be LIKE an information
                self.add_message_to_room(room, nick_from + ' ' + body[4:], date)
                # self.add_info(room, nick_from + ' ' + body[4:], date)
369
            else:
370 371 372
                date = date if delayed == True else None
                self.add_message_to_room(room, body, date, nick_from)
                # self.add_message(room, nick_from, body, date, delayed)
373
        self.window.input.refresh()
374
        doupdate()
375 376

    def room_presence(self, stanza):
377 378 379 380
        """
        Display the presence on the room window and update the
        presence information of the concerned user
        """
381 382
        if len(sys.argv) > 1:
            self.information(str(stanza))
383 384
        from_nick = stanza.getFrom().getResource()
        from_room = stanza.getFrom().getStripped()
385
	room = self.get_room_by_name(from_room)
386
	if not room:
387
            return
388
        else:
389 390 391 392 393 394
            msg = None
            affiliation = stanza.getAffiliation()
            show = stanza.getShow()
            status = stanza.getStatus()
            role = stanza.getRole()
            if not room.joined:     # user in the room BEFORE us.
395 396
                room.users.append(User(from_nick, affiliation, show, status,
                                       role))
397 398
                if from_nick.encode('utf-8') == room.own_nick:
                    room.joined = True
399 400
                    self.add_message_to_room(room, _("Your nickname is %s") % (from_nick))
                    # self.add_info(room, _("Your nickname is %s") % (from_nick))
401
                else:
402 403 404 405 406
                    self.add_message_to_room(room, _("%s is in the room") %
                                  (from_nick# .encode('utf-8')
                                   ))
                    # self.add_info(room, _("%s is in the room") %
                    #               (from_nick.encode('utf-8')))
407 408 409 410 411 412
            else:
                change_nick = stanza.getStatusCode() == '303'
                kick = stanza.getStatusCode() == '307'
                user = room.get_user_by_name(from_nick)
                # New user
                if not user:
413 414
                    room.users.append(User(from_nick, affiliation,
                                           show, status, role))
415 416
                    hide_exit_join = config.get('hide_exit_join', -1)
                    if hide_exit_join != 0:
417 418
                        self.add_message_to_room(room, _("%(nick)s joined the room %(roomname)s") % {'nick':from_nick, 'roomname': room.name})
                        # self.add_info(room, _("%(nick)s joined the room %(roomname)s") % {'nick':from_nick, 'roomname': room.name})
419 420 421 422 423
                # nick change
                elif change_nick:
                    if user.nick == room.own_nick:
                        room.own_nick = stanza.getNick().encode('utf-8')
                    user.change_nick(stanza.getNick())
424 425 426 427 428
                    self.add_message_to_room(room, _('%(old)s is now known as %(new)s') % {'old':from_nick, 'new':stanza.getNick()})
                    # self.add_info(room,
                    #               _('%(old)s is now known as %(new)s') %
                    #               {'old':from_nick,
                    #                  'new':stanza.getNick()})
429 430 431
                # kick
                elif kick:
                    room.users.remove(user)
432 433 434 435
                    try:
                        reason = stanza.getReason().encode('utf-8')
                    except:
                        reason = ''
436 437 438 439 440 441 442
                    try:
                        by = stanza.getActor().encode('utf-8')
                    except:
                        by = None
                    if from_nick == room.own_nick: # we are kicked
                        room.disconnect()
                        if by:
443 444 445
                            self.add_message_to_room(room,  _("You have been kicked by %(by)s. Reason: %(reason)s") % {'by':by, 'reason':reason})
 #                            self.add_info(room, _("""You have been kicked by
 # %(by)s. Reason: %(reason)s""") % {'by':by, 'reason':reason})
446
                        else:
447 448 449
                            self.add_message_to_room(room, _("You have been kicked. Reason: %s") % (reason))
 #                            self.add_info(room, _("""You have been
 # kicked. Reason: %s""") % (reason))
450 451
                    else:
                        if by:
452 453 454 455
                            self.add_message_to_room(room, _("%(nick)s has been kicked by %(by)s. Reason: %(reason)s") % {'nick':from_nick, 'by':by, 'reason':reason})
                            # self.add_info(room, _("""%(nick)s has been kicked
                            #              by %(by)s. Reason: %(reason)s""") %
                            #               {'nick':from_nick, 'by':by, 'reason':reason})
456
                        else:
457 458 459 460
                            self.add_message_to_room(room, _("%(nick)s has been kicked. Reason: %(reason)s") % {'nick':from_nick, 'reason':reason})
                            # self.add_info(room, _("""%(nick)s has been kicked.
                            #                      Reason: %(reason)s""") %
                            #               {'nick':from_nick, 'reason':reason})
461 462 463
                # user quit
                elif status == 'offline' or role == 'none':
                    room.users.remove(user)
464 465 466 467
                    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))
                        # self.add_info(room, _('%s has left the room') % (from_nick))
468 469 470
                # status change
                else:
                    user.update(affiliation, show, status, role)
471
                    hide_status_change = config.get('hide_status_change', -1) if config.get('hide_status_change', -1) >= -1 else -1
472 473 474
                    if hide_status_change == -1 or \
                            user.has_talked_since(hide_status_change) or\
                            user.nick == room.own_nick:
475 476
                        self.add_message_to_room(room, _('%(nick)s changed his/her status : %(a)s, %(b)s, %(c)s, %(d)s') % {'nick':from_nick, 'a':affiliation, 'b':role, 'c':show, 'd':status})
                        # self.add_info(room, _('%(nick)s changed his/her status : %(a)s, %(b)s, %(c)s, %(d)s') % {'nick':from_nick, 'a':affiliation, 'b':role, 'c':show, 'd':status})
477 478
            if room == self.current_room():
                self.window.user_win.refresh(room.users)
479
        self.window.input.refresh()
480
        doupdate()
481

482
    def add_message_to_room(self, room, txt, time=None, nickname=None):
483
        """
484 485
        Add the message to the room and refresh the associated component
        of the interface
486
        """
487
        room.add_message(txt, time, nickname)
488
        if room == self.current_room():
489 490 491
            self.window.text_win.refresh(room)
        # elif not delayed:
        else:
492
            self.window.info_win.refresh(self.rooms, self.current_room())
493

494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
        # TODO

    # def add_info(self, room, info, date=None):
    #     """
    #     add a new information in the specified room
    #     (displays it immediately AND saves it for redisplay
    #     in futur refresh)
    #     """
    #     if not date:
    #         date = datetime.now()
    #     msg = room.add_info(info, date)
    #     self.window.text_win.add_line(room, (date, msg))
    #     if room.name == self.current_room().name:
    #         self.window.text_win.refresh(room.name)
    #         self.window.input.refresh()
    #         doupdate()

    # def add_message(self, room, nick_from, body, date=None, delayed=False):
    #     """
    #     Just add a message
    #     """
    #     if not date:
    #         date = datetime.now()
    #     color = room.add_message(nick_from, body, date)
    #     self.window.text_win.add_line(room, (date, nick_from.encode('utf-8'), body.encode('utf-8'), color))
    #     if room == self.current_room():
    #         self.window.text_win.refresh(room.name)
    #     elif not delayed:
    #         self.window.info_win.refresh(self.rooms, self.current_room())

524
    def execute(self):
525 526 527
        """
        Execute the /command or just send the line on the current room
        """
528 529
        line = self.window.input.get_text()
        self.window.input.clear_text()
530
        self.window.input.refresh()
531 532
        if line == "":
            return
533
        if line.startswith('/'):
534 535 536
            command = line.strip()[:].split()[0][1:]
            args = line.strip()[:].split()[1:]
            if command in self.commands.keys():
537
                func = self.commands[command][0]
538
                func(args)
539
                return
540
            else:
541 542
                self.add_message_to_room(self.current_room(), _("Error: unknown command (%s)") % (command))
                # self.add_info(self.current_room(), _("Error: unknown command (%s)") % (command))
543
        elif self.current_room().name != 'Info':
544
            self.muc.send_message(self.current_room().name, line)
545
        self.window.input.refresh()
546
        doupdate()
547

548
    def command_help(self, args):
549 550 551
        """
        /help <command_name>
        """
552 553
        room = self.current_room()
        if len(args) == 0:
554
            msg = _('Available commands are:')
555 556
            for command in self.commands.keys():
                msg += "%s " % command
557
            msg += _("\nType /help <command_name> to know what each command does")
558 559 560 561
        if len(args) == 1:
            if args[0] in self.commands.keys():
                msg = self.commands[args[0]][1]
            else:
562
                msg = _('Unknown command: %s') % args[0]
563 564
        self.add_message_to_room(room, msg)
        # self.add_info(room, msg)
565

566
    def command_win(self, args):
567 568 569
        """
        /win <number>
        """
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
        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)

590
    def command_kick(self, args):
591 592 593
        """
        /kick <nick> [reason]
        """
594 595 596 597 598 599 600 601 602 603 604 605 606
        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)

607
    def command_join(self, args):
608 609 610
        """
        /join [room][/nick] [password]
        """
611
        password = None
612 613 614 615 616 617
        if len(args) == 0:
            r = self.current_room()
            if r.name == 'Info':
                return
            room = r.name
            nick = r.own_nick
618
        else:
619 620 621 622 623
            info = args[0].split('/')
            if len(info) == 1:
                nick = config.get('default_nick', 'Poezio')
            else:
                nick = info[1]
624
            if info[0] == '':   # happens with /join /nickname, which is OK
625 626 627 628
                r = self.current_room()
                if r.name == 'Info':
                    return
                room = r.name
629 630
                if nick == '':
                    nick = r.own_nick
631 632 633
            else:
                room = info[0]
            r = self.get_room_by_name(room)
634 635
        if len(args) == 2:       # a password is provided
            password = args[1]
636
        if r and r.joined:                   # if we are already in the room
637
            self.information(_("already in room [%s]") % room)
638
            return
639
        self.muc.join_room(room, nick, password)
640
        if not r:   # if the room window exists, we don't recreate it.
641
            self.join_room(room, nick)
642
        else:
643
            r.own_nick = nick
644
            r.users = []
645

646
    def command_bookmark(self, args):
647 648 649
        """
        /bookmark [room][/nick]
        """
650 651 652 653 654 655 656 657 658 659 660 661 662
        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]
663 664
            if roomname == '':
                roomname = self.current_room().name
665 666 667 668
        if nick:
            res = roomname+'/'+nick
        else:
            res = roomname
669 670 671 672 673 674 675 676 677
        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)
678
        config.set_and_save('rooms', bookmarked+':'+res)
679

680
    def command_set(self, args):
681 682 683
        """
        /set <option> [value]
        """
684
        if len(args) != 2 and len(args) != 1:
685 686 687
            self.command_help(['set'])
            return
        option = args[0]
688 689 690 691
        if len(args) == 2:
            value = args[1]
        else:
            value = ''
692
        config.set_and_save(option, value)
693 694
        msg = "%s=%s" % (option, value)
        room = self.current_room()
695 696
        self.add_message_to_room(room, msg)
        # self.add_info(room, msg)
697

698
    def command_show(self, args):
699 700 701
        """
        /show <status> [msg]
        """
702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726
        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)

727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
    def command_ignore(self, args):
        """
        /ignore <nick>
        """
        # TODO
        if len(args) != 1:
            self.command_help([ignore])
            return

    def command_unignore(self, args):
        """
        /unignore <nick>
        """
        # TODO
        if len(args) != 1:
            self.command_help([ignore])
            return

745
    def command_away(self, args):
746 747 748
        """
        /away [msg]
        """
749 750 751 752
        args.insert(0, 'away')
        self.command_show(args)

    def command_busy(self, args):
753 754 755
        """
        /busy [msg]
        """
756 757 758 759
        args.insert(0, 'busy')
        self.command_show(args)

    def command_avail(self, args):
760 761 762
        """
        /avail [msg]
        """
763 764
        args.insert(0, 'available')
        self.command_show(args)
765

766
    def command_part(self, args):
767 768 769
        """
        /part [msg]
        """
770 771 772 773 774 775 776 777
        reason = None
        room = self.current_room()
        if room.name == 'Info':
            return
        if len(args):
            msg = ' '.join(args)
        else:
            msg = None
778 779
        if room.joined:
            self.muc.quit_room(room.name, room.own_nick, msg)
780
        self.rooms.remove(self.current_room())
781
        self.window.refresh(self.rooms)
782

783
    def command_topic(self, args):
784 785 786
        """
        /topic [new topic]
        """
787
        room = self.current_room()
788
        if len(args) == 0:
789
            self.add_message_to_room(room, _("The subject of the room is: %s") % room.topic)
790
        subject = ' '.join(args)
791 792 793 794
        if not room.joined or room.name == "Info":
            return
        self.muc.change_subject(room.name, subject)

795
    def command_nick(self, args):
796 797 798
        """
        /nick <nickname>
        """
799 800 801 802 803 804 805 806
        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)

807
    def information(self, msg):
808 809 810
        """
        Displays an informational message in the "Info" room window
        """
811
        room = self.get_room_by_name("Info")
812 813
        self.add_message_to_room(room, msg)
        # self.add_info(room, msg)
814

815
    def command_quit(self, args):
816 817 818
        """
        /quit
        """
819
	self.reset_curses()
820
        sys.exit()