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()
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))