Switch to Sleekxmpp. fixed #1768

This commit is contained in:
louiz@4325f9fc-e183-4c21-96ce-0ab188b42d13 2010-08-31 23:11:02 +00:00
parent d2fef9112d
commit e84b23d1ad
8 changed files with 410 additions and 795 deletions

View file

@ -47,8 +47,6 @@ import errno
import time
import traceback
import xmpp
ROOM_STATE_NONE = 11
ROOM_STATE_CURRENT = 10
ROOM_STATE_PRIVATE = 15
@ -120,20 +118,11 @@ def is_in_path(command, return_abs_path=False):
pass
return False
def get_stripped_jid(jid):
"""
Return the stripped JID (bare representation)
nick@server/resource -> nick@server
"""
if isinstance(jid, basestring):
jid = xmpp.JID(jid)
return jid.getStripped()
def is_jid(jid):
"""
Return True if this is a valid JID
"""
if xmpp.JID(jid).getNode() != '':
if jid.find('@') != -1:
return True
return False
@ -141,35 +130,34 @@ def jid_get_node(jid):
"""
nick@server/resource -> nick
"""
if isinstance(jid, basestring):
jid = xmpp.JID(jid)
return jid.getNode()
return jid.split('@', 1)[0]
def jid_get_domain(jid):
"""
nick@server/resource -> server
"""
if isinstance(jid, basestring):
jid = xmpp.JID(jid)
return jid.getDomain()
return jid.split('@',1)[-1].split('/', 1)[0]
def jid_get_resource(jid):
def jid_get_resource(fulljid):
"""
nick@server/resource -> resource
"""
if isinstance(jid, basestring):
jid = xmpp.JID(jid)
return jid.getResource()
if '/' in fulljid:
return fulljid.split('/', 1)[-1]
else:
return ''
def jid_get_bare(fulljid):
"""
nick@server/resource -> nick@server
"""
return '%s@%s' % (jid_get_domain(fulljid), jid_get_node(fulljid))
def is_jid_the_same(a, b):
"""
Compare two bare jids
"""
if isinstance(a, basestring):
a = xmpp.JID(a)
if isinstance(b, basestring):
b = xmpp.JID(b)
return a.bareMatch(b)
return jid_get_bare(a) == jid_get_bare(a)
DISTRO_INFO = {
'Arch Linux': '/etc/arch-release',

View file

@ -24,205 +24,27 @@ from gettext import (bindtextdomain, textdomain, bind_textdomain_codeset,
gettext as _)
import sys
import threading
import sleekxmpp
import xmpp
from config import config
from logging import logger
from logger import logger
from handler import Handler
from common import jid_get_node, jid_get_domain, is_jid_the_same
class Connection(threading.Thread):
import logging
class Connection(sleekxmpp.ClientXMPP):
"""
Receives everything from Jabber and emits the
appropriate signals
"""
def __init__(self, server, resource):
threading.Thread.__init__(self)
self.handler = Handler()
self.daemon = True # exit the program when this thread exits
if config.get('jid', '') == '':
self.server = server
else:
self.server = jid_get_domain(config.get('jid', ''))
self.resource = resource
self.online = 0 # 1:connected, 2:auth confirmed
self.jid = '' # we don't know our jid yet (anon account)
self.port = config.get('port', 5222)
self.client = xmpp.Client(self.server, debug=[])
def __init__(self):
sleekxmpp.ClientXMPP.__init__(self, None, None, ssl=True,
resource=config.get('resource', 'poezio'))
self.registerPlugin('xep_0045')
def run(self):
"""
run in a thread
connect to server
"""
if not self.connect_to_server(self.server, self.port):
self.handler.emit('error', msg='Could not connect to server')
sys.exit(-1)
if not self.authenticate(config.get('jid', '') == ''):
self.handler.emit('error', msg='Could not authenticate to server')
sys.exit(-1)
# TODO, become invisible before sendInitPresence
self.client.sendInitPresence(requestRoster=0)
self.register_handlers()
self.online = 1 # 2 when confirmation of our auth is received
while 1:
self.process()
def connect_to_server(self, server, port):
"""
Connect to the server
"""
if config.get('use_proxy','false') == 'true':
return self.client.connect((server, port),
{'host': config.get("proxy_server", ""),
'port': config.get("proxy_port", 1080),
'user': config.get("proxy_user", ""),
'password': config.get("proxy_password",
"")
})
else:
return self.client.connect((server, port))
def authenticate(self, anon=True):
"""
Authenticate to the server
"""
if anon:
try:
self.client.auth(None, "", self.resource)
return True
except TypeError:
self.handler.emit('error', msg=_('Error: Could not authenticate. Please make sure the server you chose (%s) supports anonymous authentication' % (config.get('server', ''))))
return False
else:
password = config.get('password', '')
jid = config.get('jid', '')
auth = self.client.auth(jid_get_node(jid), password, "salut")
return True
def register_handlers(self):
"""
registers handlers from xmpppy signals
"""
self.client.RegisterHandler('iq', self.on_get_time, typ='get',
ns="urn:xmpp:time")
self.client.RegisterHandler('iq', self.on_get_vcard)
self.client.RegisterHandler('iq', self.on_get_version, typ='get',
ns=xmpp.NS_VERSION)
self.client.RegisterHandler('presence', self.handler_presence)
self.client.RegisterHandler('message', self.handler_message)
def error_message(self, stanza):
"""
handles the error messages
"""
from_ = stanza.getFrom()
if not from_:
room_name = ''
else:
room_name = from_.getStripped()
self.handler.emit('error-message', room=room_name,
error=stanza.getTag('error'),
msg=stanza.getError())
raise xmpp.protocol.NodeProcessed
def handler_presence(self, connection, presence):
"""
check if it's a normal or a muc presence
"""
is_muc = False
tags = presence.getTags('x')
for tag in tags:
if tag.getAttr('xmlns') == 'http://jabber.org/protocol/muc#user':
is_muc = True
if is_muc:
self.handler_muc_presence(connection, presence)
else:
self.handler_normal_presence(connection, presence)
def handler_normal_presence(self, connection, presence):
"""
handles the non-MUC presences
"""
fro = presence.getFrom()
toj = presence.getAttr('to')
if presence.getType() == 'error':
self.error_message(presence)
return
if not toj or fro == toj: # own presence
self.online = 2
self.jid = toj
self.handler.emit('on-connected', jid=fro)
def handler_muc_presence(self, connection, presence):
"""
handles the presence messages
"""
if not connection:
return
self.handler.emit('room-presence', stanza=presence)
raise xmpp.protocol.NodeProcessed
def handler_delayed_message(self, connection, message):
"""
handles the delayed messages
These are received when we join a muc and we are sent the
recent history
"""
if not connection:
return
self.handler.emit('room-delayed-message', stanza=message)
raise xmpp.protocol.NodeProcessed
def handler_message(self, connection, message):
"""
handles the common messages
"""
if not connection:
return
if message.getType() == 'error':
self.error_message(message)
return
if message.getType() == 'groupchat':
self.handler.emit('room-message', stanza=message)
else:
self.handler.emit('private-message', stanza=message)
raise xmpp.protocol.NodeProcessed
def process(self, timeout=10):
"""
Main connection loop
It just waits for something to process (something is received
or something has to be sent)
"""
if self.online:
self.client.Process(timeout)
else:
logger.warning('disconnecting...')
sys.exit()
def on_get_version(self, connection, iq):
"""
Handles the iq requesting our software version
"""
if not connection:
return
self.handler.emit('send-version', iq_obj=iq)
def on_get_time(self, connection, iq):
"""
handles the iq requesting our time
"""
if not connection:
return
self.handler.emit('send-time', iq_obj=iq)
def on_get_vcard(self, connection, iq):
"""
we received a vcard
"""
from common import debug
debug('\n====\n%s\n\n' % iq)
def start(self):
# TODO, try multiple servers
if self.connect((config.get('server', 'anon.louiz.org'),
config.get('port', 5222))):
self.process(threaded=True)

View file

@ -33,6 +33,7 @@ from datetime import datetime
import common
import theme
import multiuserchat as muc
from handler import Handler
from config import config
from window import Window
@ -40,7 +41,7 @@ from user import User
from room import Room
from message import Message
from keyboard import read_char
from common import is_jid_the_same, jid_get_domain, is_jid
from common import is_jid_the_same, jid_get_domain, jid_get_resource, is_jid
# http://xmpp.org/extensions/xep-0045.html#errorstatus
ERROR_AND_STATUS_CODES = {
@ -61,15 +62,14 @@ class Gui(object):
"""
User interface using ncurses
"""
def __init__(self, stdscr=None, muc=None):
self.init_curses(stdscr)
self.stdscr = stdscr
self.window = Window(stdscr)
def __init__(self, xmpp):
self.stdscr = curses.initscr()
self.init_curses(self.stdscr)
self.xmpp = xmpp
self.window = Window(self.stdscr)
self.rooms = [Room('Info', '', self.window)]
self.ignores = {}
self.muc = muc
self.commands = {
'help': (self.command_help, u'\_o< KOIN KOIN KOIN'),
'join': (self.command_join, _("Usage: /join [room_name][@server][/nick] [password]\nJoin: Join the specified room. You can specify a nickname after a slash (/). If no nickname is specified, you will use the default_nick in the configuration file. You can omit the room name: you will then join the room you\'re looking at (useful if you were kicked). You can also provide a room_name without specifying a server, the server of the room you're currently in will be used. You can also provide a password to join the room.\nExamples:\n/join room@server.tld\n/join room@server.tld/John\n/join room2\n/join /me_again\n/join\n/join room@server.tld/my_nick password\n/join / password")),
@ -136,14 +136,230 @@ class Gui(object):
'M-b': self.window.input.jump_word_left
}
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)
self.handler.connect('private-message', self.private_message)
self.handler.connect('error-message', self.room_error)
self.handler.connect('error', self.information)
# Add handlers
self.xmpp.add_event_handler("session_start", self.on_connected)
self.xmpp.add_event_handler("groupchat_presence", self.on_groupchat_presence)
self.xmpp.add_event_handler("groupchat_message", self.on_groupchat_message)
self.xmpp.add_event_handler("message", self.on_message)
# self.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)
# self.handler.connect('private-message', self.private_message)
# self.handler.connect('error-message', self.room_error)
# self.handler.connect('error', self.information)
def on_connected(self, event):
"""
Called when we are connected and authenticated
"""
self.information(_("Welcome on Poezio \o/!"))
self.information(_("Your JID is %s") % self.xmpp.fulljid)
rooms = config.get('rooms', '')
if rooms == '' or not isinstance(rooms, str):
return
rooms = rooms.split(':')
for room in rooms:
args = room.split('/')
if args[0] == '':
return
roomname = args[0]
if len(args) == 2:
nick = args[1]
else:
default = os.environ.get('USER') if os.environ.get('USER') else 'poezio'
nick = config.get('default_nick', '')
if nick == '':
nick = default
self.open_new_room(roomname, nick)
muc.join_groupchat(self.xmpp, roomname, nick)
# Todo: SEND VCARD
return
if config.get('jid', '') == '': # Don't send the vcard if we're not anonymous
self.vcard_sender.start() # because the user ALREADY has one on the server
def on_groupchat_presence(self, presence):
"""
Triggered whenever a presence stanza is received from a user in a multi-user chat room.
Display the presence on the room window and update the
presence information of the concerned user
"""
from_nick = presence['from'].resource
from_room = presence['from'].bare
room = self.get_room_by_name(from_room)
code = presence.find('{jabber:client}status')
status_codes = set([s.attrib['code'] for s in presence.findall('{http://jabber.org/protocol/muc#user}x/{http://jabber.org/protocol/muc#user}status')])
# Check if it's not an error presence.
if presence['type'] == 'error':
return self.room_error(presence, from_room)
if not room:
return
else:
msg = None
affiliation = presence['muc']['affiliation']
show = presence['muc']['type']
status = presence['status']
role = presence['muc']['role']
jid = presence['muc']['jid']
typ = presence['type']
if not room.joined: # user in the room BEFORE us.
# ignore redondant presence message, see bug #1509
if from_nick not in [user.nick for user in room.users]:
new_user = User(from_nick, affiliation, show, status, role)
room.users.append(new_user)
if from_nick.encode('utf-8') == room.own_nick:
room.joined = True
new_user.color = theme.COLOR_OWN_NICK
self.add_message_to_room(room, _("Your nickname is %s") % (from_nick))
if '170' in status_codes:
self.add_message_to_room(room, 'Warning: this room is publicly logged')
else:
change_nick = '303' in status_codes
kick = '307' in status_codes and typ == 'unavailable'
user = room.get_user_by_name(from_nick)
# New user
if not user:
room.users.append(User(from_nick, affiliation,
show, status, role))
hide_exit_join = config.get('hide_exit_join', -1)
if hide_exit_join != 0:
if not jid.full:
self.add_message_to_room(room, _("%(spec)s [%(nick)s] joined the room") % {'nick':from_nick, 'spec':theme.CHAR_JOIN}, colorized=True)
else:
self.add_message_to_room(room, _("%(spec)s [%(nick)s] (%(jid)s) joined the room") % {'spec':theme.CHAR_JOIN, 'nick':from_nick, 'jid':jid.full}, colorized=True)
# nick change
elif change_nick:
new_nick = presence.find('{http://jabber.org/protocol/muc#user}x/{http://jabber.org/protocol/muc#user}item').attrib['nick']
if user.nick == room.own_nick:
room.own_nick = new_nick
# also change our nick in all private discussion of this room
for _room in self.rooms:
if _room.jid is not None and is_jid_the_same(_room.jid, room.name):
_room.own_nick = new_nick
user.change_nick(new_nick)
self.add_message_to_room(room, _('[%(old)s] is now known as [%(new)s]') % {'old':from_nick, 'new':new_nick}, colorized=True)
# rename the private tabs if needed
private_room = self.get_room_by_name('%s/%s' % (from_room, from_nick))
if private_room:
self.add_message_to_room(private_room, _('[%(old_nick)s] is now known as [%(new_nick)s]') % {'old_nick':from_nick, 'new_nick':new_nick}, colorized=True)
new_jid = private_room.name.split('/')[0]+'/'+new_nick
private_room.jid = private_room.name = new_jid
# kick
elif kick:
room.users.remove(user)
by = presence.find('{http://jabber.org/protocol/muc#user}x/{http://jabber.org/protocol/muc#user}item/{http://jabber.org/protocol/muc#user}actor')
reason = presence.find('{http://jabber.org/protocol/muc#user}x/{http://jabber.org/protocol/muc#user}item/{http://jabber.org/protocol/muc#user}reason')
by = by.attrib['jid'] if by else ''
reason = reason.text# if reason else ''
if from_nick == room.own_nick: # we are kicked
room.disconnect()
if by:
kick_msg = _("%(spec) [You] have been kicked by [%(by)s].") % {'spec': theme.CHAR_KICK, 'by':by}
else:
kick_msg = _("%(spec)s [You] have been kicked.") % {'spec':theme.CHAR_KICK}
# try to auto-rejoin
if config.get('autorejoin', 'false') == 'true':
muc.join_groupchat(self.xmpp, room.name, room.own_nick)
else:
if by:
kick_msg = _("%(spec)s [%(nick)s] has been kicked by %(by)s.") % {'spec':theme.CHAR_KICK, 'nick':from_nick, 'by':by}
else:
kick_msg = _("%(spec)s [%(nick)s] has been kicked") % {'spec':theme.CHAR_KICK, 'nick':from_nick}
if reason:
kick_msg += _(' Reason: %(reason)s') % {'reason': reason}
self.add_message_to_room(room, kick_msg, colorized=True)
# user quit
elif typ == 'unavailable':
room.users.remove(user)
hide_exit_join = config.get('hide_exit_join', -1) if config.get('hide_exit_join', -1) >= -1 else -1
if hide_exit_join == -1 or user.has_talked_since(hide_exit_join):
if not jid.full:
leave_msg = _('%(spec)s [%(nick)s] has left the room') % {'nick':from_nick, 'spec':theme.CHAR_QUIT}
else:
leave_msg = _('%(spec)s [%(nick)s] (%(jid)s) has left the room') % {'spec':theme.CHAR_QUIT, 'nick':from_nick, 'jid':jid.full}
if status:
leave_msg += ' (%s)' % status
self.add_message_to_room(room, leave_msg, colorized=True)
private_room = self.get_room_by_name('%s/%s' % (from_room, from_nick))
if private_room:
if not status:
self.add_message_to_room(private_room, _('%(spec)s [%(nick)s] has left the room') % {'nick':from_nick, 'spec':theme.CHAR_QUIT}, colorized=True)
else:
self.add_message_to_room(private_room, _('%(spec)s [%(nick)s] has left the room (%(status)s)') % {'nick':from_nick, 'spec':theme.CHAR_QUIT, 'status': status}, colorized=True)
# status change
else:
# 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 ","
hide_status_change = config.get('hide_status_change', -1) if config.get('hide_status_change', -1) >= -1 else -1
if (hide_status_change == -1 or \
user.has_talked_since(hide_status_change) or\
user.nick == room.own_nick)\
and\
(affiliation != user.affiliation or\
role != user.role or\
show != user.show or\
status != user.status):
# display the message in the room
self.add_message_to_room(room, msg)
private_room = self.get_room_by_name(from_room)
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)
if room == self.current_room():
self.window.user_win.refresh(room.users)
self.window.input.refresh()
doupdate()
def on_message(self, message):
"""
When receiving private message from a muc OR a normal message
(from one of our contacts)
"""
if message['type'] == 'groupchat':
return None
# Differentiate both type of messages, and call the appropriate handler.
jid_from = message['from']
for room in self.rooms:
if room.jid is None and room.name == jid_from.bare: # check all the MUC we are in
return self.on_groupchat_private_message(message)
return self.on_normal_message(message)
def on_groupchat_private_message(self, message):
"""
We received a Private Message (from someone in a Muc)
"""
jid = message['from']
nick_from = jid.user
room_from = jid.server
room = self.get_room_by_name(jid.full) # get the tab with the private conversation
if not room: # It's the first message we receive: create the tab
room = self.open_private_window(room_from, nick_from.encode('utf-8'), False)
if not room:
return
body = message['body']
self.add_message_to_room(room, body, None, nick_from)
self.window.input.refresh()
doupdate()
def on_normal_message(self, message):
"""
When receiving "normal" messages (from someone in our roster)
"""
return
def resize_window(self):
"""
@ -152,14 +368,14 @@ class Gui(object):
self.window.resize(self.stdscr)
self.window.refresh(self.rooms)
def main_loop(self, stdscr):
def main_loop(self):
"""
main loop waiting for the user to press a key
"""
self.refresh_window()
while True:
doupdate()
char=read_char(stdscr)
char=read_char(self.stdscr)
try: # if this is not a valide utf-8 char, discard it
char.decode('utf-8')
except UnicodeDecodeError:
@ -205,17 +421,11 @@ class Gui(object):
Reset terminal capabilities to what they were before ncurses
init
"""
# TODO remove me?
curses.echo()
curses.nocbreak()
curses.endwin()
def on_connected(self, jid):
"""
We are connected when authentification confirmation is received
"""
self.information(_("Welcome on Poezio \o/!"))
self.information(_("Your JID is %s") % jid)
def refresh_window(self):
"""
Refresh everything
@ -223,9 +433,9 @@ class Gui(object):
self.current_room().set_color_state(theme.COLOR_TAB_CURRENT)
self.window.refresh(self.rooms)
def join_room(self, room, nick):
def open_new_room(self, room, nick, focus=True):
"""
join the specified room (muc), using the specified nick
Open a new Tab containing a Muc room, using the specified nick
"""
r = Room(room, nick, self.window)
self.current_room().set_color_state(theme.COLOR_TAB_NORMAL)
@ -236,7 +446,8 @@ class Gui(object):
if ro.nb == 0:
self.rooms.insert(self.rooms.index(ro), r)
break
self.command_win("%s" % r.nb)
if focus:
self.command_win("%s" % r.nb)
self.refresh_window()
def completion(self):
@ -322,27 +533,28 @@ class Gui(object):
self.current_room().scroll_up(self.window.text_win.height-1)
self.refresh_window()
def room_error(self, room, error, msg):
def room_error(self, error, room_name):
"""
Display the error on the room window
"""
if not error:
return
room = self.get_room_by_name(room)
room = self.get_room_by_name(room_name)
if not room:
room = self.get_room_by_name('Info')
code = error.getAttr('code')
typ = error.getAttr('type')
if error.getTag('text'):
body = error.getTag('text').getData()
else: # No description of the error is provided in the stanza
# If it's a standard error, use our own messages
msg = error['error']['type']
condition = error['error']['condition']
code = error['error']['code']
body = error['error']['text']
if not body:
if code in ERROR_AND_STATUS_CODES.keys():
body = ERROR_AND_STATUS_CODES[code]
else:
body = _('Unknown error')
self.add_message_to_room(room, _('Error: %(code)s-%(msg)s: %(body)s' %
{'msg':msg, 'code':code, 'body':body}))
body = condition or _('Unknown error')
if code:
self.add_message_to_room(room, _('Error: %(code)s - %(msg)s: %(body)s' %
{'msg':msg, 'body':body, 'code':code}))
else:
self.add_message_to_room(room, _('Error: %(msg)s: %(body)s' %
{'msg':msg, 'body':body}))
if code == '401':
self.add_message_to_room(room, _('To provide a password in order to join the room, type "/join / password" (replace "password" by the real password)'))
if code == '409':
@ -352,23 +564,6 @@ class Gui(object):
self.add_message_to_room(room, _('You can join the room with an other nick, by typing "/join /other_nick"'))
self.refresh_window()
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.encode('utf-8'), False)
if not room:
return
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.decode('utf-8')+'/'+user_nick
for room in self.rooms: # if the room exists, focus it and return
@ -396,40 +591,41 @@ class Gui(object):
self.refresh_window()
return r
def room_message(self, stanza, date=None):
def on_groupchat_message(self, message):
"""
Display the message on the room window
Triggered whenever a message is received from a multi-user chat room.
"""
delay_tag = stanza.getTag('delay', namespace='urn:xmpp:delay')
if delay_tag:
# FIXME: not receiving subjects? :/
delay_tag = message.find('{urn:xmpp:delay}delay')
if delay_tag is not None:
delayed = True
date = common.datetime_tuple(delay_tag.getAttr('stamp'))
date = common.datetime_tuple(delay_tag.attrib['stamp'])
else:
# We support the OLD and deprecated XEP: http://xmpp.org/extensions/xep-0091.html
# But it sucks, please, Jabber servers, don't do this :(
delay_tag = stanza.getTag('x', namespace='jabber:x:delay')
if delay_tag:
delay_tag = message.find('{jabber:x:delay}x')
if delay_tag is not None:
delayed = True
date = common.datetime_tuple(delay_tag.getAttr('stamp'))
date = common.datetime_tuple(delay_tag.attrib['stamp'])
else:
delayed = False
if stanza.getType() != 'groupchat':
return # ignore all messages not comming from a MUC
nick_from = stanza.getFrom().getResource()
room_from = stanza.getFrom().getStripped()
date = None
nick_from = message['from'].resource
room_from = message.getMucroom()
room = self.get_room_by_name(room_from)
if (self.ignores.has_key(room_from)) and (nick_from in self.ignores[room_from]):
return
room = self.get_room_by_name(room_from)
if not room:
self.information(_("message received for a non-existing room: %s") % (room_from))
if not room:
self.information(_("message received for a non-existing room: %s") % (room_from))
return
body = stanza.getBody()
subject = stanza.getSubject()
body = message['body']#stanza.getBody()
subject = message['subject']#stanza.getSubject()
if subject:
if nick_from:
self.add_message_to_room(room, _("%(nick)s changed the subject to: %(subject)s") % {'nick':nick_from, 'subject':subject}, date)
self.add_message_to_room(room, _("%(nick)s changed the subject to: %(subject)s") % {'nick':nick_from, 'subject':subject}, time=date)
else:
self.add_message_to_room(room, _("The subject is: %(subject)s") % {'subject':subject}, date)
self.add_message_to_room(room, _("The subject is: %(subject)s") % {'subject':subject}, time=date)
room.topic = subject.encode('utf-8').replace('\n', '|')
if room == self.current_room():
self.window.topic_win.refresh(room.topic)
@ -442,139 +638,6 @@ class Gui(object):
self.refresh_window()
doupdate()
def room_presence(self, stanza):
"""
Display the presence on the room window and update the
presence information of the concerned user
"""
from_nick = stanza.getFrom().getResource()
from_room = stanza.getFrom().getStripped()
room = self.get_room_by_name(from_room)
if not room:
return
else:
msg = None
affiliation = stanza.getAffiliation()
show = stanza.getShow()
status = stanza.getStatus()
role = stanza.getRole()
jid = stanza.getJid()
if not room.joined: # user in the room BEFORE us.
# ignore redondant presence message, see bug #1509
if from_nick not in [user.nick for user in room.users]:
new_user = User(from_nick, affiliation, show, status, role)
room.users.append(new_user)
if from_nick.encode('utf-8') == room.own_nick:
room.joined = True
self.add_message_to_room(room, _("Your nickname is %s") % (from_nick))
# Check for a 170 status code
for xtag in stanza.getTags('x'):
for child in xtag.getTags('status'):
if child.getAttr('code') == '170':
self.add_message_to_room(room, 'Warning: this room is publicly logged')
new_user.color = theme.COLOR_OWN_NICK
else:
change_nick = stanza.getStatusCode() == '303'
kick = stanza.getStatusCode() == '307'
user = room.get_user_by_name(from_nick)
# New user
if not user:
room.users.append(User(from_nick, affiliation,
show, status, role))
hide_exit_join = config.get('hide_exit_join', -1)
if hide_exit_join != 0:
if not jid:
self.add_message_to_room(room, _("%(spec)s [%(nick)s] joined the room") % {'nick':from_nick, 'spec':theme.CHAR_JOIN}, colorized=True)
else:
self.add_message_to_room(room, _("%(spec)s [%(nick)s] (%(jid)s) joined the room") % {'spec':theme.CHAR_JOIN, 'nick':from_nick, 'jid':jid}, colorized=True)
# nick change
elif change_nick:
if user.nick == room.own_nick:
room.own_nick = stanza.getNick().encode('utf-8')
# 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()
user.change_nick(stanza.getNick())
self.add_message_to_room(room, _('[%(old)s] is now known as [%(new)s]') % {'old':from_nick, 'new':stanza.getNick()}, colorized=True)
# 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()}, colorized=True)
new_jid = private_room.name.split('/')[0]+'/'+stanza.getNick()
private_room.jid = new_jid
private_room.name = new_jid
# kick
elif kick:
room.users.remove(user)
try:
reason = stanza.getReason()
except:
reason = ''
try:
by = stanza.getActor()
except:
by = None
if from_nick == room.own_nick: # we are kicked
room.disconnect()
if by:
self.add_message_to_room(room, _("%(spec) [You] have been kicked by [%(by)s]. Reason: {%(reason)s}") % {'spec': theme.CHAR_KICK, 'by':by, 'reason':reason}, colorized=True)
else:
self.add_message_to_room(room, _("%(spec)s [You] have been kicked. Reason: %(reason)s") % {'reason':reason, 'spec':theme.CHAR_KICK}, colorized=True)
# try to auto-rejoin
if config.get('autorejoin', 'false') == 'true':
self.muc.join_room(room.name, room.own_nick)
else:
if by:
self.add_message_to_room(room, _("%(spec)s [%(nick)s] has been kicked by %(by)s. Reason: %(reason)s") % {'spec':theme.CHAR_KICK, 'nick':from_nick, 'by':by, 'reason':reason}, colorized=True)
else:
self.add_message_to_room(room, _("%(spec)s [%(nick)s] has been kicked. Reason: %(reason)s") % {'nick':from_nick, 'reason':reason, 'spec':theme.CHAR_KICK}, colorized=True)
# user quit
elif status == 'offline' or role == 'none':
room.users.remove(user)
hide_exit_join = config.get('hide_exit_join', -1) if config.get('hide_exit_join', -1) >= -1 else -1
if hide_exit_join == -1 or user.has_talked_since(hide_exit_join):
if not jid:
self.add_message_to_room(room, _('%(spec)s [%(nick)s] has left the room') % {'nick':from_nick, 'spec':theme.CHAR_QUIT}, colorized=True)
else:
self.add_message_to_room(room, _('%(spec)s [%(nick)s] (%(jid)s) has left the room') % {'spec':theme.CHAR_QUIT, 'nick':from_nick, 'jid':jid}, colorized=True)
private_room = self.get_room_by_name(stanza.getFrom())
if private_room:
self.add_message_to_room(private_room, _('%(spec)s [%(nick)s] has left the room') % {'nick':from_nick, 'spec':theme.CHAR_KICK}, colorized=True)
# status change
else:
# 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 ","
hide_status_change = config.get('hide_status_change', -1) if config.get('hide_status_change', -1) >= -1 else -1
if (hide_status_change == -1 or \
user.has_talked_since(hide_status_change) or\
user.nick == room.own_nick)\
and\
(affiliation != user.affiliation or\
role != user.role or\
show != user.show or\
status != user.status):
# display the message in the room
self.add_message_to_room(room, msg)
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)
if room == self.current_room():
self.window.user_win.refresh(room.users)
self.window.input.refresh()
doupdate()
def add_message_to_room(self, room, txt, time=None, nickname=None, colorized=False):
"""
@ -611,10 +674,10 @@ class Gui(object):
self.add_message_to_room(self.current_room(), _("Error: unknown command (%s)") % (command))
elif self.current_room().name != 'Info':
if self.current_room().jid is not None:
self.muc.send_private_message(self.current_room().name, line)
muc.send_private_message(self.xmpp, self.current_room().name, line)
self.add_message_to_room(self.current_room(), line.decode('utf-8'), None, self.current_room().own_nick.decode('utf-8'))
else:
self.muc.send_message(self.current_room().name, line)
muc.send_groupchat_message(self.xmpp, self.current_room().name, line)
self.window.input.refresh()
doupdate()
@ -640,6 +703,8 @@ class Gui(object):
"""
/whois <nickname>
"""
# TODO
return
args = arg.split()
room = self.current_room()
if len(args) != 1:
@ -701,7 +766,9 @@ class Gui(object):
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)
res = muc.eject_user(self.xmpp, roomname, nick, reason)
if res['type'] == 'error':
self.room_error(res, roomname)
def command_say(self, arg):
"""
@ -710,10 +777,10 @@ class Gui(object):
line = arg
if self.current_room().name != 'Info':
if self.current_room().jid is not None:
self.muc.send_private_message(self.current_room().name, line)
muc.send_private_message(self.xmpp, 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)
muc.send_groupchat_message(self.xmpp, self.current_room().name, line)
self.window.input.refresh()
doupdate()
@ -751,7 +818,7 @@ class Gui(object):
# use the server of the current room if available
# check if the current room's name has a server
if is_jid(self.current_room().name):
room += '@%s' % jid_get_domain(self.current_room().name.encode('utf-8'))
room += '@%s' % jid_get_domain(self.current_room().name)
else: # no server could be found, print a message and return
self.add_message_to_room(self.current_room(), _("You didn't specify a server for the room you want to join"))
return
@ -759,14 +826,14 @@ class Gui(object):
if len(args) == 2: # a password is provided
password = args[1]
if r and r.joined: # if we are already in the room
self.add_message_to_room(self.current_room(), _("already in room [%s]") % room)
self.command_win('%s' % (r.nb))
return
self.muc.join_room(room, nick, password)
room = room.lower()
self.xmpp.plugin['xep_0045'].joinMUC(room, nick, password)
if not r: # if the room window exists, we don't recreate it.
self.join_room(room, nick)
self.open_new_room(room, nick)
else:
r.own_nick = nick
# r.own_nick = nick
r.users = []
def command_bookmark(self, arg):
@ -852,7 +919,7 @@ class Gui(object):
msg = None
for room in self.rooms:
if room.joined:
self.muc.change_show(room.name, room.own_nick, show, msg)
muc.change_show(self.xmpp, room.name, room.own_nick, show, msg)
def command_ignore(self, arg):
"""
@ -926,7 +993,7 @@ class Gui(object):
else:
msg = None
if room.joined:
self.muc.quit_room(room.name, room.own_nick, msg)
muc.leave_groupchat(self.xmpp, room.name, room.own_nick, arg)
self.rooms.remove(self.current_room())
self.refresh_window()
@ -955,7 +1022,7 @@ class Gui(object):
r = self.open_private_window(room.name, user.nick.decode('utf-8'))
if r and len(args) > 1:
msg = arg[len(nick)+1:]
self.muc.send_private_message(r.name, msg)
muc.send_private_message(r.name, msg)
self.add_message_to_room(r, msg.decode('utf-8'), None, r.own_nick)
def command_topic(self, arg):
@ -970,7 +1037,7 @@ class Gui(object):
subject = ' '.join(args)
if not room.joined or room.name == "Info":
return
self.muc.change_subject(room.name, subject)
muc.change_subject(self.xmpp, room.name, subject)
def command_link(self, arg):
"""
@ -1029,7 +1096,7 @@ class Gui(object):
room = self.current_room()
if not room.joined or room.name == "Info":
return
self.muc.change_nick(room.name, nick)
muc.change_nick(self.xmpp, room.name, nick)
def information(self, msg):
"""
@ -1047,8 +1114,9 @@ class Gui(object):
msg = arg
else:
msg = None
if msg:
self.muc.disconnect(self.rooms, msg)
sleep(0.2) # :(
self.reset_curses()
for room in self.rooms:
if not room.jid and room.name != 'Info':
muc.leave_groupchat(self.xmpp, room.name, room.own_nick, msg)
self.xmpp.disconnect()
self.reset_curses()
sys.exit()

View file

@ -17,6 +17,8 @@
from singleton import Singleton
#Todo, it's not a singleton. Oh, also, remove-me
class Handler(Singleton):
"""
This class is the global handler for the software's signals.

View file

@ -1,4 +1,3 @@
# Copyright 2009, 2010 Erwan Briand
# Copyright 2010, Florent Le Coz <louizatakk@fedoraproject.org>
# This program is free software: you can redistribute it and/or modify
@ -13,331 +12,92 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Implementation of the XEP-0045: Multi-User Chat.
"""
Implementation of the XEP-0045: Multi-User Chat.
Add some facilities that are not available on the XEP_0045
sleek plugin
"""
from xmpp import NS_MUC_ADMIN, NS_MUC
from xmpp.protocol import Presence, Iq, Message, JID
import xmpp
import common
import threading
import os
import sleekxmpp
from time import (altzone, gmtime, localtime, strftime, timezone)
from xml.etree import cElementTree as ET
from handler import Handler
from config import config
from common import get_stripped_jid
from common import is_jid
from common import debug
class VcardSender(threading.Thread):
def send_private_message(xmpp, jid, line):
"""
avatar sending is really slow (don't know why...)
use a thread to send it...
Send a private message
"""
def __init__(self, connection):
threading.Thread.__init__(self)
self.connection = connection
self.handler = Handler()
msg = xmpp.makeMessage(jid)
msg['to'] = jid
msg['type'] = 'chat'
msg['body'] = line
msg.send()
def run(self):
self.send_vcard()
def send_groupchat_message(xmpp, jid, line):
"""
Send a message to the groupchat
"""
msg = xmpp.makeMessage(jid)
msg['type'] = 'groupchat'
msg['body'] = line
msg.send()
def send_vcard(self):
"""
Method stolen from Gajim (thanks)
## Copyright (C) 2006 Dimitur Kirov <dkirov AT gmail.com>
## Junglecow J <junglecow AT gmail.com>
## Copyright (C) 2006-2007 Tomasz Melcer <liori AT exroot.org>
## Travis Shirk <travis AT pobox.com>
## Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006-2008 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007 Julien Pivotto <roidelapluie AT gmail.com>
## Copyright (C) 2007-2008 Brendan Taylor <whateley AT gmail.com>
## Jean-Marie Traissard <jim AT lapin.org>
## Stephan Erb <steve-e AT h3c.de>
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
(one of these people coded this method, probably)
"""
if not self.connection:
return
vcard = {
"FN":config.get('full_name', ''),
"URL":config.get('website', ''),
"EMAIL":{
"USERID":config.get('email', '')
},
"DESC":config.get('comment', 'A proud Poezio user')
}
photo_file_path = config.get('photo', '../data/poezio_80.png')
(image, mime_type, sha1) = common.get_base64_from_file(photo_file_path)
if image:
vcard['PHOTO'] = {"TYPE":mime_type,"BINVAL":image}
iq = xmpp.Iq(typ = 'set')
iq2 = iq.addChild('vCard', namespace=xmpp.NS_VCARD)
for i in vcard:
if i == 'jid':
continue
if isinstance(vcard[i], dict):
iq3 = iq2.addChild(i)
for j in vcard[i]:
iq3.addChild(j).setData(vcard[i][j])
elif isinstance(vcard[i], list):
for j in vcard[i]:
iq3 = iq2.addChild(i)
for k in j:
iq3.addChild(k).setData(j[k])
else:
iq2.addChild(i).setData(vcard[i])
self.connection.send(iq)
iq = xmpp.Iq(typ = 'set')
iq2 = iq.addChild('vCard', namespace=xmpp.NS_VCARD_UPDATE)
iq2.addChild('PHOTO').setData(sha1)
self.connection.send(iq)
def change_show(xmpp, jid, own_nick, show, status):
"""
Change our 'Show'
"""
pres = xmpp.makePresence(pto='%s/%s' % (jid, own_nick),
pfrom=xmpp.fulljid)
if show: # if show is None, don't put a <show /> tag. It means "online"
pres['type'] = show
if status:
pres['status'] = status
debug('Change presence: %s\n' % (pres))
pres.send()
class MultiUserChat(object):
def __init__(self, connection):
self.connection = connection
self.vcard_sender = VcardSender(self.connection)
def change_subject(xmpp, jid, subject):
"""
Change the room subject
"""
msg = xmpp.makeMessage(jid)
msg['type'] = 'groupchat'
msg['subject'] = subject
msg['from'] = xmpp.jid
msg.send()
self.rooms = []
self.rn = {}
def change_nick(xmpp, jid, nick):
"""
Change our own nick in a room
"""
xmpp.makePresence(pto='%s/%s' % (jid, nick),
pfrom=xmpp.jid).send()
self.own_jid = None
def join_groupchat(xmpp, jid, nick, password=None):
"""
Join the groupchat
"""
xmpp.plugin['xep_0045'].joinMUC(jid, nick, password)
self.handler = Handler()
self.handler.connect('join-room', self.join_room)
self.handler.connect('on-connected', self.on_connected)
self.handler.connect('send-version', self.send_version)
self.handler.connect('send-time', self.send_time)
def leave_groupchat(xmpp, jid, own_nick, msg):
"""
Leave the groupchat
"""
xmpp.plugin['xep_0045'].leaveMUC(jid, own_nick, msg)
def on_connected(self, jid):
self.own_jid = jid
rooms = config.get('rooms', '')
if rooms == '' or type(rooms) != str:
return
else:
rooms = rooms.split(':')
for room in rooms:
args = room.split('/')
if args[0] == '':
return
roomname = args[0]
if len(args) == 2:
nick = args[1]
else:
default = os.environ.get('USER') if os.environ.get('USER') else 'poezio'
nick = config.get('default_nick', '')
if nick == '':
nick = default
self.handler.emit('join-room', room=roomname, nick=nick)
if config.get('jid', '') == '': # Don't send the vcard if we're not anonymous
self.vcard_sender.start() # because the user ALREADY has one on the server
def send_message(self, room, message):
mes = Message(to=room)
mes.setBody(message)
mes.setType('groupchat')
self.connection.send(mes)
def send_private_message(self, user_jid, message):
mes = Message(to=user_jid)
mes.setBody(message)
mes.setType('chat')
self.connection.send(mes)
def request_vcard(self, room_name, nickname):
"""
Request the vCard of an user, over a MUC or not
"""
request = Iq(typ='get', to='%s/%s'% (room_name, nickname))
vcard_tag = request.addChild(name='vCard', namespace='vcard-temp')
self.connection.send(request)
def join_room(self, room, nick, password=None):
"""Join a new room"""
pres = Presence(to='%s/%s' % (room, nick))
pres.setFrom('%s'%self.own_jid)
x_tag = pres.addChild(name='x', namespace=NS_MUC)
if password:
passwd = x_tag.addChild(name='password')
passwd.setData(password)
muc_history_length = config.get('muc_history_length', -1)
if muc_history_length >= 0:
history_tag = x_tag.addChild(name='history')
if muc_history_length == 0:
history_tag.setAttr('maxchars', 0)
else:
history_tag.setAttr('maxstanzas', muc_history_length)
self.connection.send(pres)
def quit_room(self, room, nick, msg=None):
"""Quit a room"""
if room is None and nick is None:
self.on_disconnect()
return
pres = Presence(to='%s/%s' % (room, nick), typ='unavailable')
if msg:
pres.setStatus(msg)
self.connection.send(pres)
def disconnect(self, rooms, msg):
"""
"""
for room in rooms:
if room.jid is None and room.joined:
pres = Presence(to='%s' % room.name,
typ='unavailable')
pres.setStatus(msg)
self.connection.send(pres)
def on_disconnect(self):
"""Called at disconnection"""
for room in self.rooms:
pres = Presence(to='%s/%s' % (room, self.rn[room]),
typ='unavailable')
self.connection.send(pres)
def on_iq(self, iq):
"""Receive a MUC iq notification"""
from_ = iq.getFrom().__str__()
if get_stripped_jid(from_) in self.rooms:
children = iq.getChildren()
for child in children:
if child.getName() == 'error':
code = int(child.getAttr('code'))
msg = None
echildren = child.getChildren()
for echild in echildren:
if echild.getName() == 'text':
msg = echild.getData()
self.handler.emit('on-muc-error',
room=from_,
code=code,
msg=msg)
def on_presence(self, presence):
"""Receive a MUC presence notification"""
from_ = presence.getFrom().__str__()
if get_stripped_jid(from_) in self.rooms:
self.handler.emit('on-muc-presence-changed',
jid=from_.encode('utf-8'),
priority=presence.getPriority(),
show=presence.getShow(),
status=presence.getStatus(),
stanza=presence
)
def on_message(self, message):
"""Receive a MUC message notification"""
from_ = message.getFrom().__str__().encode('utf-8')
if get_stripped_jid(from_) in self.rooms:
body_ = message.getBody()
type_ = message.getType()
subj_ = message.getSubject()
self.handler.emit('on-muc-message-received',
jid=from_, msg=body_, subject=subj_,
typ=type_, stanza=message)
def eject_user(self, room, action, nick, reason):
"""Eject an user from a room"""
iq = Iq(typ='set', to=room)
query = iq.addChild('query', namespace=NS_MUC_ADMIN)
item = query.addChild('item')
if action == 'kick':
item.setAttr('role', 'none')
if is_jid(nick):
item.setAttr('jid', nick)
else:
item.setAttr('nick', nick)
elif action == 'ban':
item.setAttr('affiliation', 'outcast')
item.setAttr('jid', nick)
if reason is not None:
rson = item.addChild('reason')
rson.setData(reason)
self.connection.send(iq)
def change_role(self, room, nick, role):
"""Change the role of an user"""
iq = Iq(typ='set', to=room)
query = iq.addChild('query', namespace=NS_MUC_ADMIN)
item = query.addChild('item')
item.setAttr('nick', nick)
item.setAttr('role', role)
self.connection.send(iq)
def change_aff(self, room, jid, aff):
"""Change the affiliation of an user"""
iq = Iq(typ='set', to=room)
query = iq.addChild('query', namespace=NS_MUC_ADMIN)
item = query.addChild('item')
item.setAttr('jid', jid)
item.setAttr('affiliation', aff)
self.connection.send(iq)
def change_subject(self, room, subject):
"""Change the subject of a room"""
message = Message(typ='groupchat', to=room)
subj = message.addChild('subject')
subj.setData(subject)
self.connection.send(message)
def change_nick(self, room, nick):
"""Change the nickname"""
pres = Presence(to='%s/%s' % (room, nick))
self.connection.send(pres)
def change_show(self, room, nick, show, status):
pres = Presence(to='%s/%s' % (room, nick))
if show: # if show is None, don't put a <show /> tag. It means "online"
pres.setShow(show)
if status:
pres.setStatus(status)
self.connection.send(pres)
def send_version(self, iq_obj):
"""
from gajim and modified
"""
iq_obj = iq_obj.buildReply('result')
qp = iq_obj.getTag('query')
if config.get('send_poezio_info', 'true') == 'true':
qp.setTagData('name', 'Poezio')
qp.setTagData('version', '0.6.3 dev')
else:
qp.setTagData('name', 'Unknown')
qp.setTagData('version', 'Unknown')
if config.get('send_os_info', 'true') == 'true':
qp.setTagData('os', common.get_os_info())
else:
qp.setTagData('os', 'Unknown')
self.connection.send(iq_obj)
raise xmpp.protocol.NodeProcessed
def send_time(self, iq_obj):
"""
from gajim
"""
iq_obj = iq_obj.buildReply('result')
qp = iq_obj.setTag('time',
namespace="urn:xmpp:time")
if config.get('send_time', 'true') == 'true':
qp.setTagData('utc', strftime('%Y-%m-%dT%H:%M:%SZ', gmtime()))
isdst = localtime().tm_isdst
zone = -(timezone, altzone)[isdst] / 60
tzo = (zone / 60, abs(zone % 60))
qp.setTagData('tzo', '%+03d:%02d' % (tzo))
self.connection.send(iq_obj)
raise xmpp.protocol.NodeProcessed
def eject_user(xmpp, jid, nick, reason):
"""
(try to) Eject an user from the room
"""
iq = xmpp.makeIqSet()
query = ET.Element('{http://jabber.org/protocol/muc#admin}query')
item = ET.Element('{http://jabber.org/protocol/muc#admin}item', {'nick':nick, 'role':'none'})
if reason:
reason_el = ET.Element('{http://jabber.org/protocol/muc#admin}reason')
reason_el.text = reason
item.append(reason_el)
query.append(item)
iq.append(query)
iq['to'] = jid
return iq.send()

View file

@ -25,26 +25,6 @@ import threading
import sys
import traceback
def installThreadExcepthook():
"""
Workaround for sys.excepthook thread bug
See http://bugs.python.org/issue1230540
Python, you made me sad :(
"""
init_old = threading.Thread.__init__
def init(self, *args, **kwargs):
init_old(self, *args, **kwargs)
run_old = self.run
def run_with_except_hook(*args, **kw):
try:
run_old(*args, **kw)
except (KeyboardInterrupt, SystemExit):
raise
except:
sys.excepthook(*sys.exc_info())
self.run = run_with_except_hook
threading.Thread.__init__ = init
class MyStdErr(object):
def __init__(self, fd):
"""
@ -59,6 +39,7 @@ class MyStdErr(object):
Restaure the good ol' sys.stderr, because we need
it in order to print the tracebacks
"""
sys.stderr.close()
sys.stderr = self.old_stderr
my_stderr = MyStdErr(open('/dev/null', 'a'))
@ -77,30 +58,24 @@ def exception_handler(type_, value, trace):
sys.excepthook = exception_handler
import sys
import curses
import signal
from connection import Connection
from multiuserchat import MultiUserChat
from config import config
from gui import Gui
from curses import initscr
signal.signal(signal.SIGINT, signal.SIG_IGN) # ignore ctrl-c
def main():
"""
main function
The main function consist of the Connection initialization
then the gui (ncurses) init, connection handlers and then the
connection is "started"
"""
resource = config.get('resource', 'poezio')
server = config.get('server', 'anon.louiz.org:jeproteste.info')
connection = Connection(server, resource)
connection.start()
stdscr = initscr()
gui = Gui(stdscr, MultiUserChat(connection.client))
gui.main_loop(stdscr)
xmpp = Connection() # Connection init
gui = Gui(xmpp) # Gui init.
xmpp.start() # Connect to remote server
gui.main_loop() # Refresh the screen, wait for user events etc
if __name__ == '__main__':
installThreadExcepthook()
main()

View file

@ -19,7 +19,7 @@
from datetime import datetime
from random import randrange
from config import config
from logging import logger
from logger import logger
from message import Message
import common