# 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 _) from os.path import isfile from time import sleep import os import re import sys import shlex import curses import threading import traceback from datetime import datetime import common import theme import logging from sleekxmpp.xmlstream.stanzabase import JID log = logging.getLogger(__name__) import multiuserchat as muc import tabs import windows from connection import connection from config import config from logger import logger from user import User from room import Room from roster import Roster, RosterGroup, roster from contact import Contact, Resource from text_buffer import TextBuffer from keyboard import read_char # http://xmpp.org/extensions/xep-0045.html#errorstatus ERROR_AND_STATUS_CODES = { '401': _('A password is required'), '403': _('You are banned from the room'), '404': _('The room does\'nt exist'), '405': _('Your are not allowed to create a new room'), '406': _('A reserved nick must be used'), '407': _('You are not in the member list'), '409': _('This nickname is already in use or has been reserved'), '503': _('The maximum number of users has been reached'), } SHOW_NAME = { 'dnd': _('busy'), 'away': _('away'), 'xa': _('not available'), 'chat': _('chatty'), '': _('available') } resize_lock = threading.Lock() class Core(object): """ User interface using ncurses """ def __init__(self, xmpp): # All uncaught exception are given to this callback, instead # of being displayed on the screen and exiting the program. sys.excepthook = self.on_exception self.running = True self.stdscr = curses.initscr() self.init_curses(self.stdscr) self.xmpp = xmpp # a unique buffer used to store global informations # that are displayed in almost all tabs, in an # information window. self.information_buffer = TextBuffer() self.information_win_size = config.get('info_win_height', 2, 'var') default_tab = tabs.InfoTab(self, "Info") if self.xmpp.anon\ else tabs.RosterInfoTab(self) default_tab.on_gain_focus() self.tabs = [default_tab] self.resize_timer = None self.previous_tab_nb = 0 self.own_nick = config.get('own_nick', self.xmpp.boundjid.bare) # global commands, available from all tabs # a command is tuple of the form: # (the function executing the command. Takes a string as argument, # a string representing the help message, # a completion function, taking a Input as argument. Can be None) # The completion function should return True if a completion was # made ; False otherwise self.commands = { 'help': (self.command_help, '\_o< KOIN KOIN KOIN', None), '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"), self.completion_join), 'exit': (self.command_quit, _("Usage: /exit\nExit: Just disconnect from the server and exit poezio."), None), 'next': (self.rotate_rooms_right, _("Usage: /next\nNext: Go to the next room."), None), 'n': (self.rotate_rooms_right, _("Usage: /n\nN: Go to the next room."), None), 'prev': (self.rotate_rooms_left, _("Usage: /prev\nPrev: Go to the previous room."), None), 'p': (self.rotate_rooms_left, _("Usage: /p\nP: Go to the previous room."), None), 'win': (self.command_win, _("Usage: /win \nWin: Go to the specified room."), None), 'w': (self.command_win, _("Usage: /w \nW: Go to the specified room."), None), 'show': (self.command_show, _("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 [status] argument will be your status message"), None), '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]'"), None), '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]'"), None), '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]'"), None), '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]'"), None), '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)"), None), 'set': (self.command_set, _("Usage: /set