#!/usr/bin/python # -*- coding:utf-8 -*- # # Copyright 2010 Le Coz Florent # # 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 . from gettext import (bindtextdomain, textdomain, bind_textdomain_codeset, gettext as _) bindtextdomain('poezio') textdomain('poezio') bind_textdomain_codeset('poezio', 'utf-8') import locale locale.setlocale(locale.LC_ALL, '') import sys import curses from datetime import datetime from handler import Handler from logging import logger from random import randrange from config import config from window import Window class User(object): """ keep trace of an user in a Room """ def __init__(self, nick, affiliation, show, status, role): self.update(affiliation, show, status, role) self.change_nick(nick) self.color = randrange(2, 10) def update(self, affiliation, show, status, role): self.affiliation = affiliation self.show = show self.status = status self.role = role def change_nick(self, nick): self.nick = nick.encode('utf-8') class Room(object): """ """ def __init__(self, name, nick, number): self.name = name self.own_nick = nick self.color_state = 11 # color used in RoomInfo self.nb = number # number used in RoomInfo self.joined = False # false until self presence is received self.users = [] self.lines = [] # (time, nick, msg) or (time, info) self.topic = '' def disconnect(self): self.joined = False self.users = [] def add_message(self, nick, msg): color = None self.set_color_state(12) if nick != self.own_nick: if self.own_nick in msg: self.set_color_state(13) color = 3 else: highlight_words = config.get('highlight_on', '').split(':') for word in highlight_words: if word.lower() in msg.lower() and word != '': self.set_color_state(13) color = 3 if not msg: logger.info('msg is None..., %s' % (nick)) return self.lines.append((datetime.now(), nick.encode('utf-8'), msg.encode('utf-8'), color)) return color def add_info(self, info): """ info, like join/quit/status messages""" try: self.lines.append((datetime.now(), info.encode('utf-8'))) return info.encode('utf-8') except: self.lines.append((datetime.now(), info)) return info def get_user_by_name(self, nick): for user in self.users: if user.nick == nick.encode('utf-8'): return user return None def set_color_state(self, color): if self.color_state < color or color == 11: self.color_state = color def on_presence(self, stanza, nick): """ """ affiliation = stanza.getAffiliation() show = stanza.getShow() status = stanza.getStatus() role = stanza.getRole() if not self.joined: # user in the room BEFORE us. 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.encode-('utf-8'))) change_nick = stanza.getStatusCode() == '303' kick = stanza.getStatusCode() == '307' user = self.get_user_by_name(nick) # New user if not user: self.users.append(User(nick, affiliation, show, status, role)) if not config.get('hide_enter_join', "false") == "true": return self.add_info(_('%(nick)s joined the room %(roomname)s') % {'nick':nick, 'roomname': self.name}) return None # 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(_('%(old_nick)s is now known as %(new_nick)s') % {'old_nick':nick, 'new_nick':stanza.getNick()}) # kick if kick: self.users.remove(user) reason = stanza.getReason().encode('utf-8') or '' try: by = stanza.getActor().encode('utf-8') except: by = None if nick == self.own_nick: self.disconnect() if by: 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)) else: if by: 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(_('%(nick)s has been kicked. Reason: %(reason)s') % {'nick':nick, 'reason':reason}) # user quit if status == 'offline' or role == 'none': self.users.remove(user) if not config.get('hide_enter_join', "false") == "true": return self.add_info(_('%s has left the room') % (nick)) return None # status change user.update(affiliation, show, status, role) if not config.get('hide_status_change', "false") == "true": return self.add_info(_('%(nick)s changed his/her status : %(a)s, %(b)s, %(c)s, %(d)s') % {'nick':nick, 'a':affiliation, 'b':role, 'c':show, 'd':status}) return None class Gui(object): """ Graphical user interface using ncurses """ def __init__(self, stdscr=None, muc=None): self.room_number = 0 self.init_curses(stdscr) self.stdscr = stdscr self.rooms = [Room('Info', '', self.next_room_number())] # current_room is self.rooms[0] self.window = Window(stdscr) self.window.new_room(self.current_room()) self.window.refresh(self.rooms) 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_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 \nWin: Go to the specified room.')), 'w': (self.command_win, _('Usage: /w \nW: Go to the specified room.')), 'part': (self.command_part, _('Usage: /part [message]\nPart: disconnect from a room. You can specify an optional message.')), 'show': (self.command_show, _(u'Usage: /show [status]\nShow: Change your availability and (optionaly) your status. The 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 /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