cleanup, launch.sh, makefile

parent 6f344064
prefix=/usr/local
LIBDIR=$(DESTDIR)$(prefix)/lib
BINDIR=$(DESTDIR)$(prefix)/bin
DATADIR=$(DESTDIR)$(prefix)/share
LOCALEDIR=$(DATADIR)/locale
MANDIR=$(DATADIR)/man
INSTALL=install
all: Makefile
clean: Makefile
install:
$(INSTALL) -d $(LOCALEDIR) $(BINDIR) $(DATADIR)/poezio $(DATADIR)/poezio/data $(DATADIR)/poezio/src
$(INSTALL) -m644 data/* $(DATADIR)/poezio/data/
for sourcefile in `find src/ -maxdepth 1 -type f | grep -v '.svn' | grep -v '.pyc'` ; do \
$(INSTALL) -m644 $$sourcefile $(DATADIR)/poezio/src; \
done
echo "#!/usr/bin/env python" > $(BINDIR)/poezio
echo "cd $(DATADIR)/poezio/src/ && python client.py" >> $(BINDIR)/poezio
for localename in `find locale/ -maxdepth 1 -type d | grep -v '.svn' | sed 's:locale/::g'` ; do \
if [ -d locale/$$localename ]; then \
$(INSTALL) -d $(LOCALEDIR)/$$localename; \
$(INSTALL) -d $(LOCALEDIR)/$$localename/LC_MESSAGES; \
msgfmt locale/$$localename/LC_MESSAGES/poezio.po -o locale/$$localename/LC_MESSAGES/poezio.mo -v; \
$(INSTALL) -m644 locale/$$localename/LC_MESSAGES/poezio.mo $(LOCALEDIR)/$$localename/LC_MESSAGES; \
fi \
done
uninstall:
rm -f $(BINDIR)/poezio
rm -rf $(DATADIR)/poezio
for gettextfile in `find $(LOCALEDIR) -name 'poezio.mo'` ; do \
rm -f $$gettextfile; \
done
pot:
xgettext src/*.py --from-code=utf-8 --keyword=_ -o locale/poezio.pot
......@@ -7,6 +7,8 @@ Poezio is a console Jabber client. Its goal is to use anonymous
connections to let the user join MultiUserChats. This way, the user
don't have to create a Jabber account, exactly like people are using
IRC. It doesn't handle contact list at all.
Poezio's commands are design to be (if possible) like well known IRC
clients (weechat, irssi, mirc).
=======================
Authors
......
[Poezio]
server = louiz.org
port = 5222
resource = poezio
default_nick = louiz_on_poezio
server = louiz.org
rooms = test@chat.jabberfr.org:discussion@kikoo.louiz.org
rooms = poezio@conference.codingteam.net:discussion@chat.jabberfr.org
logfile = logs
port = 5222
#!/bin/sh
cd src/ && python client.py "$@"
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-01-31 05:55+0100\n"
"PO-Revision-Date: 2010-01-31 06:07+0100\n"
"Last-Translator: Florent Le Coz <louizatakk@fedoraproject.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/gui.py:98
#, python-format
msgid "Your nickname is %s"
msgstr "Votre pseudo est %s"
#: src/gui.py:99
#, python-format
msgid "%s is in the room"
msgstr "%s est dans le salon"
#: src/gui.py:106
#, python-format
msgid "%(nick)s joined the room %(roomname)s"
msgstr "%(nick)s est entré dans le salon %(roomname)s"
#: src/gui.py:112
#, python-format
msgid "%(old_nick)s is now known as %(new_nick)s"
msgstr "%(old_nick)s s'appelle maintenant %(new_nick)s"
#: src/gui.py:124
#, python-format
msgid "You have been kicked by %(by)s. Reason: %(reason)s"
msgstr "Vous avez été kické(e) par %(by)s. Raison : %(reason)s"
#: src/gui.py:126
#, python-format
msgid "You have been kicked. Reason: %s"
msgstr "Vous avez été kické(e). Raison : %s"
#: src/gui.py:129
#, python-format
msgid "%(nick)s has been kicked by %(by)s. Reason: %(reason)s"
msgstr "%(nick)s a été kické(e) par %(by)s. Raison : %(reason)s"
#: src/gui.py:131
#, python-format
msgid "%(nick)s has been kicked. Reason: %(reason)s"
msgstr "%(nick)s a été kické(e). Raison : %(reason)s"
#: src/gui.py:135
#, python-format
msgid "%s has left the room"
msgstr "%s a quitté le salon"
#: src/gui.py:138
#, python-format
msgid "%(nick)s changed his/her status : %(a)s, %(b)s, %(c)s, %(d)s"
msgstr "%(nick)s a changé son statut : %(a)s, %(b)s, %(c)s, %(d)s"
#: src/gui.py:158
msgid "OLOL, this is SOOO recursive"
msgstr "OLOL, this is SOOO recursive"
#: src/gui.py:159
msgid ""
"Usage: /join [room_name][/nick]\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). Examples:\n"
"/join room@server.tld\n"
"/join room@server.tld/John\n"
"/join /me_again\n"
"/join"
msgstr ""
"Utilisation : /join [room_name][/nick]\n"
"Join : Entre dans le salon spécifié. Vous pouvez spécifier un pseudoname après un slash (/). Si aucun pseudonyme n'est spécifié, vous utiliserez le pseudonyme par défaut (default_nick) du fichier de configuration. Vous pouvez omettre le nom du salon : vous entrerez alors dans le salon que vous êtes en train de voir (utile après avoir été kické). Exemples :\n"
"/join room@server.tld\n"
"/join room@server.tld/Martin\n"
"/join /encore_moi\n"
"/join"
#: src/gui.py:160
msgid ""
"Usage: /quit\n"
"Quit: Just disconnect from the server and exit poezio."
msgstr ""
"Utilisation : /quit\n"
"Quit : Se déconnecte tout simplement du serveur et quitte poezio."
#: src/gui.py:161
msgid ""
"Usage: /exit\n"
"Exit: Just disconnect from the server and exit poezio."
msgstr ""
"Utilisation : /exit\n"
"Exit : Se déconnecte tout simplement du serveur et quitte poezio."
#: src/gui.py:162
msgid ""
"Usage: /next\n"
"Next: Go to the next room."
msgstr ""
"Utilisation : /next\n"
"Next : Va au salon suivant."
#: src/gui.py:163
msgid ""
"Usage: /prev\n"
"Prev: Go to the previous room."
msgstr ""
"Utilisation : /prev\n"
"Prev : Va au salon précédent."
#: src/gui.py:164
msgid ""
"Usage: /part [message]\n"
"Part: disconnect from a room. You can specify an optionnal message."
msgstr ""
"Utilisation : /part [message]\n"
"Part : Se déconnecte d'un salon. Vous pouvez spécifier un message optionnel"
#: src/gui.py:165
msgid ""
"Usage: /show <availability> [status]\n"
"Show: Change your availability and (optionnaly) 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"
msgstr ""
#: src/gui.py:166
msgid ""
"Usage: /away [message]\n"
"Away: Sets your availability to away and (optional) sets your status message. This is equivalent do \"/show away [message]\""
msgstr ""
#: src/gui.py:167
msgid ""
"Usage: /busy [message]\n"
"Busy: Sets your availability to busy and (optional) sets your status message. This is equivalent do \"/show busy [message]\""
msgstr ""
#: src/gui.py:168
msgid ""
"Usage: /avail [message]\n"
"Avail: Sets your availability to available and (optional) sets your status message. This is equivalent do \"/show available [message]\""
msgstr ""
#: src/gui.py:169
msgid ""
"Usage: /available [message]\n"
"Available: Sets your availability to available and (optional) sets your status message. This is equivalent do \"/show available [message]\""
msgstr ""
#: src/gui.py:170
msgid ""
"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 /nick. Type /help nick 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)"
msgstr ""
#: src/gui.py:171
msgid ""
"Usage: /nick <nickname>\n"
"Nick: Change your nickname in the current room"
msgstr ""
#: src/gui.py:258
msgid "Welcome on Poezio \\o/!"
msgstr ""
#: src/gui.py:259
#, python-format
msgid "Your JID is %s"
msgstr ""
#: src/gui.py:285
#, python-format
msgid "message received for a non-existing room: %s"
msgstr ""
#: src/gui.py:290
#, python-format
msgid "%(nick)s changed the subject to: %(subject)s"
msgstr ""
#: src/gui.py:311
#, python-format
msgid "presence received for a non-existing room: %s"
msgstr ""
#: src/gui.py:313
#, python-format
msgid "Error: %s"
msgstr ""
#: src/gui.py:348
msgid "Available commands are:"
msgstr ""
#: src/gui.py:351
msgid ""
"\n"
"Type /help <command_name> to know what each command does"
msgstr ""
#: src/gui.py:356
#, python-format
msgid "Unknown command : %s"
msgstr ""
#: src/gui.py:384
#, python-format
msgid "already in room [%s]"
msgstr ""
......@@ -17,6 +17,13 @@
# You should have received a copy of the GNU General Public License
# along with Poezio. If not, see <http://www.gnu.org/licenses/>.
from gettext import (bindtextdomain, textdomain, bind_textdomain_codeset,
gettext as _)
bindtextdomain('poezio')
textdomain('poezio')
bind_textdomain_codeset('poezio', 'UTF-8')
import sys
from connection import Connection
from multiuserchat import MultiUserChat
......@@ -25,10 +32,10 @@ from handler import Handler
from gui import Gui
from curses import wrapper, initscr
# sys.stderr = open('logs', 'a')
if len(sys.argv) == 1: # not debug, so hide any error message and disable C-c
import signal
signal.signal(signal.SIGINT, signal.SIG_IGN)
sys.stderr = open('/dev/null', 'w')
class Client(object):
"""
......
......@@ -19,7 +19,8 @@
# along with Poezio. If not, see <http://www.gnu.org/licenses/>.
from ConfigParser import RawConfigParser, NoOptionError
# from logging import logger
from os import environ, makedirs
from shutil import copy2
class Config(RawConfigParser):
"""
......@@ -78,4 +79,15 @@ class Config(RawConfigParser):
self.set(option, value)
self.save()
config = Config('poezio.cfg')
CONFIG_HOME = environ.get("XDG_CONFIG_HOME")
if not CONFIG_HOME:
CONFIG_HOME = environ.get('HOME')+'/.config/'
CONFIG_PATH = CONFIG_HOME + 'poezio/'
try:
makedirs(CONFIG_PATH)
copy2('../data/default_config.cfg', CONFIG_PATH+'poezio.cfg')
except:
pass
config = Config(CONFIG_PATH+'poezio.cfg')
......@@ -96,14 +96,13 @@ class Connection(Thread):
self.handler.emit('room-iq', stanza=iq)
def handler_error(self, connection, error):
print "fion"
sys.exit()
pass
def process(self, timeout=10):
if self.online:
try:self.client.Process(timeout)
except:
pass
pass # FIXME
else:
log.warning('disconnecting...')
sys.exit()
......@@ -17,25 +17,21 @@
# You should have received a copy of the GNU General Public License
# along with Poezio. If not, see <http://www.gnu.org/licenses/>.
from handler import Handler
import curses
from curses import textpad
from gettext import (bindtextdomain, textdomain, bind_textdomain_codeset,
gettext as _)
import locale
locale.setlocale(locale.LC_ALL, '')
import sys
import curses
from curses import textpad
from datetime import datetime
from handler import Handler
from logging import logger
from random import randrange
from config import config
locale.setlocale(locale.LC_ALL, '')
code = locale.getpreferredencoding()
import sys
from connection import *
from window import Window
class User(object):
......@@ -99,23 +95,21 @@ class Room(object):
self.users.append(User(nick, affiliation, show, status, role))
if nick.encode('utf-8') == self.own_nick:
self.joined = True
return self.add_info("Your nickname is %s" % (nick))
return self.add_info("%s is in the room" % (nick))
return self.add_info(_("Your nickname is %s") % (nick))
return self.add_info(_("%s is in the room") % (nick))
change_nick = stanza.getStatusCode() == '303'
kick = stanza.getStatusCode() == '307'
user = self.get_user_by_name(nick)
if change_nick and not user:
return self.add_info('WTF: change nick for %s but user unknown'% nick)
# New user
if not user:
self.users.append(User(nick, affiliation, show, status, role))
return self.add_info('%s joined the room %s' % (nick, self.name))
return self.add_info(_('%(nick)s joined the room %(roomname)s') % {'nick':nick, 'roomname': self.name})
# nick change
if change_nick:
if user.nick == self.own_nick:
self.own_nick = stanza.getNick().encode('utf-8')
user.change_nick(stanza.getNick())
return self.add_info('%s is now known as %s' % (nick, stanza.getNick()))
return self.add_info(_('%(old_nick)s is now known as %(new_nick)s') % {'old_nick':nick, 'new_nick':stanza.getNick()})
# kick
if kick:
self.users.remove(user)
......@@ -127,21 +121,21 @@ class Room(object):
if nick == self.own_nick:
self.disconnect()
if by:
return self.add_info('You have been kicked by %s. Reason: %s' % (by, reason))
return self.add_info(_('You have been kicked by %(by)s. Reason: %(reason)s') % {'by':by, 'reason':reason})
else:
return self.add_info('You have been kicked. Reason: %s' % (reason))
return self.add_info(_('You have been kicked. Reason: %s') % (reason))
else:
if by:
return self.add_info('%s has been kicked by %s. Reason: %s' % (nick, by, reason))
return self.add_info(_('%(nick)s has been kicked by %(by)s. Reason: %(reason)s') % {'nick':nick, 'by':by, 'reason':reason})
else:
return self.add_info('%s has been kicked. Reason: %s' % (nick, reason))
return self.add_info(_('%(nick)s has been kicked. Reason: %(reason)s') % {'nick':nick, 'reason':reason})
# user quit
if status == 'offline' or role == 'none':
self.users.remove(user)
return self.add_info('%s has left the room' % (nick))
return self.add_info(_('%s has left the room') % (nick))
# status change
user.update(affiliation, show, status, role)
return self.add_info('%s, status : %s, %s, %s, %s' % (nick, affiliation, role, show, status))
return self.add_info(_('%(nick)s changed his/her status : %(a)s, %(b)s, %(c)s, %(d)s') % {'nick':nick, 'b':affiliation, 'b':role, 'c':show, 'd':status})
class Gui(object):
......@@ -161,20 +155,20 @@ class Gui(object):
self.muc = muc
self.commands = {
'help': (self.command_help, 'OLOL, this is SOOO recursive'),
'join': (self.command_join, 'Usage: /join [room_name][/nick]\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). Examples:\n/join room@server.tld\n/join room@server.tld/John\n/join /me_again\n/join'),
'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_left, 'Usage: /next\nNext: Go to the next room.'),
'prev': (self.rotate_rooms_right, 'Usage: /prev\nPrev: Go to the previous room.'),
'part': (self.command_part, 'Usage: /part [message]\nPart: disconnect from a room. You can specify an optionnal message.'),
'show': (self.command_show, 'Usage: /show <availability> [status]\nShow: Change your availability and (optionnaly) 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 do "/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 do "/show busy [message]"'),
'avail': (self.command_avail, 'Usage: /avail [message]\nAvail: Sets your availability to available and (optional) sets your status message. This is equivalent do "/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 do "/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 /nick. Type /help nick 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)'),
'nick': (self.command_nick, 'Usage: /nick <nickname>\nNick: Change your nickname in the current room')
'help': (self.command_help, _('OLOL, this is SOOO recursive')),
'join': (self.command_join, _('Usage: /join [room_name][/nick]\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). Examples:\n/join room@server.tld\n/join room@server.tld/John\n/join /me_again\n/join')),
'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_left, _('Usage: /next\nNext: Go to the next room.')),
'prev': (self.rotate_rooms_right, _('Usage: /prev\nPrev: Go to the previous room.')),
'part': (self.command_part, _('Usage: /part [message]\nPart: disconnect from a room. You can specify an optional message.')),
'show': (self.command_show, _('Usage: /show <availability> [status]\nShow: Change your availability and (optionaly) your status. The <availability> argument is one of "avail, available, ok, here, chat, away, afk, dnd, busy, xa" and the optional [message] argument will be your status message')),
'away': (self.command_away, _('Usage: /away [message]\nAway: Sets your availability to away and (optional) sets your status message. This is equivalent to "/show away [message]"')),
'busy': (self.command_busy, _('Usage: /busy [message]\nBusy: Sets your availability to busy and (optional) sets your status message. This is equivalent to "/show busy [message]"')),
'avail': (self.command_avail, _('Usage: /avail [message]\nAvail: Sets your availability to available and (optional) sets your status message. This is equivalent to "/show available [message]"')),
'available': (self.command_avail, _('Usage: /available [message]\nAvailable: Sets your availability to available and (optional) sets your status message. This is equivalent to "/show available [message]"')),
'bookmark': (self.command_bookmark, _('Usage: /bookmark [roomname][/nick]\nBookmark: Bookmark the specified room (you will then auto-join it on each poezio start). This commands uses the same syntaxe as /nick. Type /help nick 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)')),
'nick': (self.command_nick, _('Usage: /nick <nickname>\nNick: Change your nickname in the current room'))
}
self.key_func = {
......@@ -261,8 +255,8 @@ class Gui(object):
curses.endwin()
def on_connected(self, jid):
self.information("Welcome on Poezio \o/!")
self.information("Your JID is %s" % jid)
self.information(_("Welcome on Poezio \o/!"))
self.information(_("Your JID is %s") % jid)
def join_room(self, room, nick):
self.window.text_win.new_win(room)
......@@ -288,12 +282,12 @@ class Gui(object):
nick_from = ''
room = self.get_room_by_name(room_from)
if not room:
self.information("message received for a non-existing room: %s" % (name))
self.information(_("message received for a non-existing room: %s") % (name))
return
body = stanza.getBody()
if not body:
body = stanza.getSubject()
info = room.add_info("%s changed the subject to: %s" % (nick_from, stanza.getSubject()))
info = room.add_info(_("%(nick)s changed the subject to: %(subject)s") % {'nick':nick_from, 'subject':stanza.getSubject()})
self.window.text_win.add_line(room, (datetime.now(), info))
room.topic = stanza.getSubject().encode('utf-8').replace('\n', '|')
if room == self.current_room():
......@@ -314,9 +308,9 @@ class Gui(object):
from_room = stanza.getFrom().getStripped()
room = self.get_room_by_name(from_room)
if not room:
self.information("presence received for a non-existing room: %s" % (name))
self.information(_("presence received for a non-existing room: %s") % (name))
if stanza.getType() == 'error':
msg = "Error: %s" % stanza.getError()
msg = _("Error: %s") % stanza.getError()
else:
msg = room.on_presence(stanza, from_nick)
if room == self.current_room():
......@@ -351,15 +345,15 @@ class Gui(object):
def command_help(self, args):
room = self.current_room()
if len(args) == 0:
msg = 'Available commands are:'
msg = _('Available commands are:')
for command in self.commands.keys():
msg += "%s " % command
msg += "\nType /help <command_name> to know what each command does"
msg += _("\nType /help <command_name> to know what each command does")
if len(args) == 1:
if args[0] in self.commands.keys():
msg = self.commands[args[0]][1]
else:
msg = 'Unknown command : %s' % args[0]
msg = _('Unknown command: %s') % args[0]
room.add_info(msg)
self.window.text_win.add_line(room, (datetime.now(), msg))
self.window.text_win.refresh(room.name)
......@@ -387,7 +381,7 @@ class Gui(object):
room = info[0]
r = self.get_room_by_name(room)
if r and r.joined: # if we are already in the room
self.information("already in room [%s]" % room)
self.information(_("already in room [%s]") % room)
return
self.muc.join_room(room, nick)
if not r: # if the room window exists, we don't recreate it.
......
......@@ -49,101 +49,15 @@ class Handler(Singleton):
'room-iq': list(),
# An iq is received
# Args: the stanza object
# 'xmpp-presence-handler': list(),
# # A presence is received
# # Args: the stanza object
# 'xmpp-iq-handler': list(),
# # An iq is received
# # Args: the stanza object
# 'xmpp-message-handler': list(),
# # A message is received
# # Args: the stanza object
# # - GUI event
# 'on-quit': list(),
# # When the user wants to quit.
# # - Roster and presence
# 'on-disconnected': list(),
# # When the user is disconnected from the server.
# 'on-message-received': list(),
# # When a message is received.
# # Args: jid, msg, subject, typ
# 'send-message': list(),
# # Send a message to someone.
# # Args: jid, msg, subj, typ
# # - vCard (XEP-0054)
# 'vcard-request': list(),
# # Request a vcard.
# # Args: jid
# 'on-vcard-received': list(),
# # When a vcard is received.
# # Args: jid, vcard
# # - Multi-User Chat (XEP-0045)
# 'gui-join-room': list(),
# # Join a room inside the GUI (call `join-room`).
# # Args: room, nickname
# 'quit-room': list(),
# # Quit a room.
# # Args: room, nick
# 'on-muc-message-received': list(),
# # When a message is received.
# # Args: jid, msg, subject, typ, stanza
# 'on-muc-presence-changed': list(),
# # When someone in the roster changes his presence.
# # Args: jid, priority, show, status, stanza
# 'on-muc-error': list(),
# # When the MUC composant sends an error
# # Args: room, code, msg
# 'eject-user': list(),
# # When the user try to eject another one.
# # Args: room, action, nick, reason
# 'change-user-role': list(),
# # When the user try to change the role of someone.
# # Args: room, nick, role
# 'change-user-affiliation': list(),
# # When the user try to change the affiliation of someone.
# # Args: room, jid, aff
# 'change-subject': list(),
# # When the user try to change the topic.
# # Args: room, subject
# 'change-nick': list()
# # When the user try to change his nick.
# # Args: room, nick
}
def connect(self, signal, func):
"""Connect a function to a signal."""
if func not in self.__signals__[signal]:
self.__signals__[signal].append(func)
else:
print "signal %s doesn't exist." % signal
def emit(self, signal, **kwargs):
"""Emit a signal."""
if self.__signals__.has_key(signal):
for func in self.__signals__[signal]:
func(**kwargs)
else