예제 #1
0
파일: core.py 프로젝트: hades/ja
 def __init__(self, storage):
     self._lock = Lock()
     self.storage = storage
     self.log = []
     self.password_cb = []
     self.plugins = {}
     self.commands = {}
     self.connections = []
     self.exiting = False
     self.people = People()
     self.chats = []
     self.current_chat = None
     self.print("This is ja version {}".format(version))
     self.print("Copyright © 2012 Edward Toroshchin <*****@*****.**>")
예제 #2
0
파일: core.py 프로젝트: hades/ja
class Ja(object):
    def __init__(self, storage):
        self._lock = Lock()
        self.storage = storage
        self.log = []
        self.password_cb = []
        self.plugins = {}
        self.commands = {}
        self.connections = []
        self.exiting = False
        self.people = People()
        self.chats = []
        self.current_chat = None
        self.print("This is ja version {}".format(version))
        self.print("Copyright © 2012 Edward Toroshchin <*****@*****.**>")

    @threadprotect
    def __input(self):
        input = self.inputview.get_edit_text()
        self.inputview.set_edit_text("")
        return input

    def __setup_ui(self):
        self.sysview = SystemMessagesWidget(self)
        self.inputview = Edit("> ")
        self.view = Frame(self.sysview, footer=self.inputview, focus_part="footer")
        self.loop = MainLoop(self.view, unhandled_input=self.keypress)
        setupLogging(self)
        self.__update_inputview()

    def __setup_commands(self):
        for p in dir(self):
            if getattr(getattr(self, p), "__command", False):
                self.add_command(p, getattr(self, p))
        for pname in self.plugins:
            plugin = self.plugins[pname]
            self.__setup_plugin_commands(plugin, pname)

    def __setup_plugin_commands(self, plugin, pname):
        for cn in dir(plugin):
            cc = getattr(plugin, cn)
            if getattr(cc, "__command", False):
                self.add_command("{}.{}".format(pname, cn), cc)

    @threadprotect
    @redraw_screen
    def __refresh_sysview(self):
        try:
            self.sysview.update()
        except AttributeError:
            pass

    @threadprotect
    def __update_inputview(self):
        if self.password_cb:
            self.inputview.set_caption("{}: ".format(self.password_cb[-1][0]))
        else:
            self.inputview.set_caption("> ")

    def add_command(self, name, proc):
        if name in self.commands:
            self.print("command {} conflicts with existing command".format(name))
        else:
            self.commands[name] = proc

    def add_connection(self, connection):
        self.connections.append(connection)

    def add_contact(self, contact, connection):
        self.people.add_contact(contact, connection)

    def ask_password(self, question, callback):
        self.password_cb.insert(0, (question, callback))
        self.__update_inputview()

    def execute(self, lines):
        if self.password_cb:
            question, cb = self.password_cb.pop()
            cb(lines)
            self.__update_inputview()
            return
        if lines.startswith("/"):
            args = lines[1:].split(" ", 1)
            command = args[0]
            arg = args[1] if len(args) > 1 else None
            if command in self.commands:
                try:
                    self.commands[command](arg)
                except Exception as e:
                    self.print("error executing command {}: {}".format(command, type(e)))
                    raise
            else:
                self.print("unknown command {}".format(command))
        else:
            if not self.current_chat:
                self.print("this is not a chat window")
            else:
                self.current_chat.send(lines)
        if self.exiting:
            raise ExitMainLoop()

    @command
    def help(self, arg):
        """help on ja commands"""
        self.print("available commands:")
        maxlength = max(map(lambda x: len(x), self.commands.keys()))
        for name in sorted(self.commands.keys()):
            doc = self.commands[name].__doc__
            if not doc:
                doc = "no documentation available"
            else:
                doc = doc.split("\n", 1)[0]
            self.print("  {} -- {}".format(name.ljust(maxlength), doc))

    def keypress(self, key):
        if key == "enter":
            self.execute(self.__input())
        else:
            self.print("unhandled key press {}".format(key))

    @command
    def load(self, arg):
        """load ja plugin"""
        if not arg:
            self.print("load: specify a plugin to load")
            return
        args = arg.split(" ", 1)
        modname = args[0]
        arg = args[1] if len(args) > 1 else None
        try:
            __import__(modname)
            plugin = sys.modules[modname].instance(self, arg)
            if plugin:
                name = plugin.name
                if name in self.plugins:
                    self.print("plugin {} already loaded".format(name))
                else:
                    self.plugins[name] = plugin
                    self.__setup_plugin_commands(plugin, name)
                    self.print("loaded plugin {} from {}".format(name, modname))
        except ImportError as e:
            self.print("cannot find plugin {}: {}".format(modname, e))
        except AttributeError as e:
            self.print("{} is not a ja plugin: {}".format(modname, e))

    def print(self, text, level=TWITTER):
        self.log.append((datetime.now(), level, text))
        self.__refresh_sysview()

    @command
    def quit(self, arg):
        """quit ja"""
        for c in self.connections:
            c.disconnect()
        del self.connections
        self.exiting = True

    @redraw_screen
    def receive_message(self, message):
        for chat in self.chats:
            if chat.accept_message(message):
                return
        chat = Chat(ja=self, message=message)
        chat.widget = ChatWidget(chat)
        self.chats.append(chat)
        self.print("created new window {} for chat with {}".format(len(self.chats) - 1, chat.contact))

    def run(self, args):
        self.__setup_ui()
        self.__setup_commands()
        return self.loop.run()

    def select_connection(self, contact):
        pass  # TODO

    @command
    @redraw_screen
    def window(self, arg):
        """switch to window with given number"""
        if arg == "system":
            self.view.set_body(self.sysview)
            self.current_chat = None
        else:
            try:
                wid = int(arg)
                self.view.set_body(self.chats[wid].widget)
                self.current_chat = self.chats[wid]
            except (ValueError, IndexError):
                self.print("{} is not a window".format(arg))