# Copyright 2010-2011 Florent Le Coz # # This file is part of Poezio. # # Poezio is free software: you can redistribute it and/or modify # it under the terms of the MIT license. See the COPYING file. from gettext import gettext as _ import os import re import sys import time import curses import threading import traceback from datetime import datetime import common import theme import logging import singleton import collections from sleekxmpp.xmlstream.stanzabase import JID log = logging.getLogger(__name__) import multiuserchat as muc import tabs import xhtml import pubsub import windows import connection import timed_events from data_forms import DataFormsTab from config import config, options 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': _('Permission denied'), '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'), } possible_show = {'available':None, 'chat':'chat', 'away':'away', 'afk':'away', 'dnd':'dnd', 'busy':'dnd', 'xa':'xa' } resize_lock = threading.Lock() Status = collections.namedtuple('Status', 'show message') class Core(object): """ User interface using ncurses """ def __init__(self): # All uncaught exception are given to this callback, instead # of being displayed on the screen and exiting the program. self.connection_time = time.time() self.status = Status(show=None, message='') sys.excepthook = self.on_exception self.running = True self.xmpp = singleton.Singleton(connection.Connection) # 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') self.information_win = windows.TextWin(20) self.tab_win = windows.GlobalInfoBar() self.information_buffer.add_window(self.information_win) self.tabs = [] self.previous_tab_nb = 0 self.own_nick = config.get('default_nick', '') or self.xmpp.boundjid.user # 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', self.completion_help), '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), 'quit': (self.command_quit, _("Usage: /quit\nQuit: Just disconnect from the server and exit poezio."), None), 'next': (self.rotate_rooms_right, _("Usage: /next\nNext: Go to the next room."), None), 'prev': (self.rotate_rooms_left, _("Usage: /prev\nPrev: Go to the previous room."), None), 'win': (self.command_win, _("Usage: /win \nWin: Go to the specified room."), self.completion_win), 'w': (self.command_win, _("Usage: /w \nW: Go to the specified room."), self.completion_win), 'show': (self.command_status, _('Usage: /show [status message]\nShow: Sets your availability and (optionaly) your status message. The argument is one of \"available, chat, away, afk, dnd, busy, xa\" and the optional [status] argument will be your status message.'), self.completion_status), 'status': (self.command_status, _('Usage: /status [status message]\nStatus: Sets your availability and (optionaly) your status message. The argument is one of \"available, chat, away, afk, dnd, busy, xa\" and the optional [status] argument will be your status message.'), self.completion_status), 'away': (self.command_away, _("Usage: /away [message]\nAway: Sets your availability to away and (optionaly) your status message. This is equivalent to '/status away [message]'"), None), 'busy': (self.command_busy, _("Usage: /busy [message]\nBusy: Sets your availability to busy and (optionaly) your status message. This is equivalent to '/status busy [message]'"), None), 'available': (self.command_avail, _("Usage: /available [message]\nAvailable: Sets your availability to available and (optionaly) your status message. This is equivalent to '/status 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