예제 #1
0
    def onStartup(self):
        if not self.allGoodToStart:
            self.info("Not starting Telnet service")
            return

        self.telnetClients = b3.clients.Clients(self.console)
        self.telnetClients_ids = 0
        self.telnetClients.newClient = self._newClient
        self.telnetClients.disconnect = self._disconnect

        self.console.createEvent("EVT_CONSOLE_SAY", "console say")
        self.console.createEvent("EVT_CONSOLE_SAYBIG", "console bigsay")

        forwarded_events_names = (
            "EVT_CLIENT_SAY",
            "EVT_CONSOLE_SAY",
            "EVT_CONSOLE_SAYBIG",
            "EVT_CLIENT_CONNECT",
            "EVT_CLIENT_DISCONNECT",
            "EVT_CLIENT_NAME_CHANGE",
            "EVT_CLIENT_KICK",
            "EVT_CLIENT_BAN",
            "EVT_CLIENT_BAN_TEMP",
            "EVT_CLIENT_UNBAN",
            "EVT_GAME_ROUND_START",
            "EVT_GAME_MAP_CHANGE",
            "EVT_STOP",
            "EVT_EXIT",
        )

        self.forwarded_events = []
        for v in forwarded_events_names:
            event = self.console.Events.getId(v)
            if event:
                self.forwarded_events.append(event)
                self.registerEvent(event)

        original_say = self.console.say

        def _say(msg):
            self.console.queueEvent(self.console.getEvent("EVT_CONSOLE_SAY", msg))
            original_say(msg)

        self.console.say = _say

        original_saybig = self.console.saybig

        def _saybig(msg):
            self.console.queueEvent(self.console.getEvent("EVT_CONSOLE_SAYBIG", msg))
            original_saybig(msg)

        self.console.saybig = _saybig

        self.telnetService = TelnetServiceThread(self, self.telnetIp, self.telnetPort)
        self.telnetService.start()
예제 #2
0
class TelnetPlugin(b3.plugin.Plugin):
    telnetIp = None
    telnetPort = None
    telnetService = None
    telnetClients = None

    def __init__(self, console, config=None):
        self.forwarded_events = []
        b3.plugin.Plugin.__init__(self, console, config=config)

    def onLoadConfig(self):
        # get the admin plugin so we can register commands
        self._adminPlugin = self.console.getPlugin("admin")
        if not self._adminPlugin:
            # something is wrong, can't start without admin plugin
            self.error("Could not find admin plugin")
            self.disable()
            return

        self.allGoodToStart = True
        try:
            self.telnetIp = self.config.get("general_preferences", "ip")
            if self.telnetIp in ("", None):
                self.telnetIp = "0.0.0.0"
        except NoOptionError:
            self.info(
                "no ip found in the general_preferences section of the config file. Listening on all network interfaces instead"
            )
            self.telnetIp = "0.0.0.0"

        try:
            self.telnetPort = self.config.getint("general_preferences", "port")
        except ValueError:
            self.allGoodToStart = False
            self.error("The port value found in the general_preferences section of the config file must be a number")
        except NoOptionError:
            self.allGoodToStart = False
            self.error(
                "no port found in the general_preferences section of the config file. You need to set the port for the Telnet plugin to work"
            )

        if not self.allGoodToStart:
            self.disable()

        if "commands" in self.config.sections():
            for cmd in self.config.options("commands"):
                level = self.config.get("commands", cmd)
                sp = cmd.split("-")
                alias = None
                if len(sp) == 2:
                    cmd, alias = sp

                func = self._getCmd(cmd)
                if func:
                    self._adminPlugin.registerCommand(self, cmd, level, func, alias)

    def _getCmd(self, cmd):
        cmd = "cmd_%s" % cmd
        if hasattr(self, cmd):
            func = getattr(self, cmd)
            return func

    def onStartup(self):
        if not self.allGoodToStart:
            self.info("Not starting Telnet service")
            return

        self.telnetClients = b3.clients.Clients(self.console)
        self.telnetClients_ids = 0
        self.telnetClients.newClient = self._newClient
        self.telnetClients.disconnect = self._disconnect

        self.console.createEvent("EVT_CONSOLE_SAY", "console say")
        self.console.createEvent("EVT_CONSOLE_SAYBIG", "console bigsay")

        forwarded_events_names = (
            "EVT_CLIENT_SAY",
            "EVT_CONSOLE_SAY",
            "EVT_CONSOLE_SAYBIG",
            "EVT_CLIENT_CONNECT",
            "EVT_CLIENT_DISCONNECT",
            "EVT_CLIENT_NAME_CHANGE",
            "EVT_CLIENT_KICK",
            "EVT_CLIENT_BAN",
            "EVT_CLIENT_BAN_TEMP",
            "EVT_CLIENT_UNBAN",
            "EVT_GAME_ROUND_START",
            "EVT_GAME_MAP_CHANGE",
            "EVT_STOP",
            "EVT_EXIT",
        )

        self.forwarded_events = []
        for v in forwarded_events_names:
            event = self.console.Events.getId(v)
            if event:
                self.forwarded_events.append(event)
                self.registerEvent(event)

        original_say = self.console.say

        def _say(msg):
            self.console.queueEvent(self.console.getEvent("EVT_CONSOLE_SAY", msg))
            original_say(msg)

        self.console.say = _say

        original_saybig = self.console.saybig

        def _saybig(msg):
            self.console.queueEvent(self.console.getEvent("EVT_CONSOLE_SAYBIG", msg))
            original_saybig(msg)

        self.console.saybig = _saybig

        self.telnetService = TelnetServiceThread(self, self.telnetIp, self.telnetPort)
        self.telnetService.start()

    def onEvent(self, event):
        if event.type in (b3.events.EVT_STOP, b3.events.EVT_EXIT):
            if self.telnetService:
                self.telnetService.stop()
        if event.type in self.forwarded_events:
            thread.start_new_thread(self._dispatchEvent, (event,))

    # ===============================================================================
    #
    #    Commands implementations
    #
    # ===============================================================================

    def cmd_telnetlist(self, data, client, cmd=None):
        """\
        Show connected telnet users
        """
        response = []
        for k, v in self.telnetClients.iteritems():
            tmp = datetime.now() - v.connection_datetime
            since = timedelta(seconds=int(tmp.total_seconds()))
            response.append("[%s] %s from %s since %s" % (k, v.name, v.cid, since))
        cmd.sayLoudOrPM(client, ", ".join(response))

    def cmd_telnetkick(self, data, client, cmd=None):
        """\
        <telnet session id> - kick a telnet user
        """
        m = self._adminPlugin.parseUserCmd(data)
        if not m:
            client.message("^7Invalid parameters")
            return False

        cid, keyword = m
        reason = self._adminPlugin.getReason(keyword)

        if not reason and client.maxLevel < self._adminPlugin.config.getint("settings", "noreason_level"):
            client.message("^1ERROR: ^7You must supply a reason")
            return False

        sclient = self.findClientPrompt(cid, client)
        if sclient:
            if sclient.cid == client.cid:
                self.console.say(self._adminPlugin.getMessage("kick_self", client.exactName))
            elif sclient.maxLevel >= client.maxLevel:
                if sclient.maskGroup:
                    client.message("^7%s ^7is a masked higher level player, can't kick" % client.exactName)
                else:
                    self.console.say(
                        self._adminPlugin.getMessage(
                            "kick_denied", sclient.exactName, client.exactName, sclient.exactName
                        )
                    )
            else:
                if reason:
                    sclient.message("you were kicked by %s (@%s) : %s" % (client.name, client.id, reason))
                else:
                    sclient.message("you were kicked by %s (@%s)" % (client.name, client.id))
                sclient.session.working = False
                sclient.session.server.shutdown_request(sclient.session.request)

    # ===============================================================================
    #
    #    others
    #
    # ===============================================================================

    def findClientPrompt(self, client_id, client=None):
        matches = self.telnetClients.getByMagic(client_id)
        if matches:
            if len(matches) > 1:
                names = []
                for _p in matches:
                    names.append("[^2%s^7] %s" % (_p.cid, _p.name))

                if client:
                    client.message(self._adminPlugin.getMessage("players_matched", client_id, ", ".join(names)))
                return None
            else:
                return matches[0]
        else:
            if client:
                client.message(self._adminPlugin.getMessage("no_players", client_id))
            return None

    # ===============================================================================
    #
    # managing telnet sessions
    #
    # ===============================================================================

    def _newClient(self, client):
        me = self.telnetClients
        self.telnetClients_ids += 1
        client.cid = self.telnetClients_ids
        client.console = me.console
        client.timeAdd = me.console.time()
        client.connection_datetime = datetime.now()
        client.authed = True
        client.showChat = True

        me[client.cid] = client
        me.resetIndex()
        self.debug("Telnet Client Connected: [%s] %s - %s", client.cid, client.name, client.ip)
        return client

    def _disconnect(self, client):
        if not client:
            return
        me = self.telnetClients
        client.connected = False
        if client.cid == None:
            return
        cid = client.cid
        if me.has_key(cid):
            me[cid] = None
            del me[cid]
            del client
        me.resetIndex()

    def _dispatchEvent(self, event):
        try:
            for k in self.telnetClients.keys():
                self._onB3Event(self.telnetClients[k], event)
        except:
            self.exception(sys.exc_info())

    def _onB3Event(self, client, event):
        if type(event.data) is unicode:
            data = event.data.encode("UTF-8")
        else:
            data = event.data
        if event.type in (b3.events.eventManager.getId("EVT_EXIT"), b3.events.eventManager.getId("EVT_STOP")):
            client.disconnect()
        elif event.type == b3.events.eventManager.getId("EVT_CONSOLE_SAY"):
            client.message("  console: %s" % data)
        elif event.type == b3.events.eventManager.getId("EVT_CONSOLE_SAYBIG"):
            client.message("  CONSOLE: %s" % data)
        elif event.type == b3.events.eventManager.getId("EVT_CLIENT_CONNECT"):
            client.message("  client connection : %s" % event.client)
        elif event.type == b3.events.eventManager.getId("EVT_CLIENT_DISCONNECT"):
            client.message("  client disconnection : %s" % data)
        elif event.type == b3.events.eventManager.getId("EVT_CLIENT_NAME_CHANGE"):
            client.message("  %s renamed to %s" % (event.client, data))
        elif event.type == b3.events.eventManager.getId("EVT_CLIENT_KICK"):
            client.message("  %s kicked (%r)" % (event.client, data))
        elif event.type == b3.events.eventManager.getId("EVT_CLIENT_BAN"):
            client.message("  %s banned (%r)" % (event.client, data))
        elif event.type == b3.events.eventManager.getId("EVT_CLIENT_BAN_TEMP"):
            client.message("  %s tempbanned (%r)" % (event.client, data))
        elif event.type == b3.events.eventManager.getId("EVT_CLIENT_UNBAN"):
            client.message("  %s unbanned (%r)" % (event.client, data))
        elif event.type == b3.events.eventManager.getId("EVT_GAME_ROUND_START"):
            client.message("  round started %s" % data)
        elif event.type == b3.events.eventManager.getId("EVT_GAME_MAP_CHANGE"):
            client.message("  map change %s" % data)
        elif event.type == b3.events.eventManager.getId("EVT_CLIENT_SAY") and client.showChat:
            client.message("  %s: %s" % (event.client.name, data))