def __init__(self, *args, **kwargs): Plugin.__init__(self, *args, **kwargs) command_handler.event.connect(get_dispatcher(self)) self.pre_lo3 = Signal() self.post_lo3 = Signal() self.performing_lo3 = False
class CommandHandler(object): #============================== def __init__(self): self._init_signals() #============================== def _init_signals(self): self.event = Signal() #============================== def process(self, command, extra=None, silent=False, **kwargs): command = command.split(' ') params = ' '.join(command[1:]) command = command[0] stop = False try: stop = self.event.send( sender=self.__class__, command=command, params=params, extra=extra, silent=silent, **kwargs ) except CommandInterrupt: pass except: raise
def _init_signals(self): self.pre_connect = Signal() self.post_connect = Signal() self.pre_receive = Signal() self.post_receive = Signal() self.pre_send = Signal() self.post_send = Signal() self.post_accept = Signal() self.ready = Signal()
def _init_signals(self): self.event = Signal()
class SignalSocket(Thread): """A threaded socket class based on signals. It can become a client or a server. Hook into the signals in order to do useful things with the class.""" #============================== def __init__(self, host, port, protocol="tcp"): self.daemon = True Thread.__init__(self) self._init_signals() self.host = socket.gethostbyname(host) self.port = port self.protocol = protocol self._close = False self.max_packet_size = 8192 self.sock = False self.clientsock = False # The socket we are communicating with. It will either # be self.sock or self.clientsock depending on our socket # configuration (protocol+mode) self.commsock = False #============================== def _init_signals(self): self.pre_connect = Signal() self.post_connect = Signal() self.pre_receive = Signal() self.post_receive = Signal() self.pre_send = Signal() self.post_send = Signal() self.post_accept = Signal() self.ready = Signal() #============================== def send(self, data): self.pre_send.send(sender=self.__class__) self.commsock.send(data) self.post_send.send(sender=self.__class__, data=data) #============================== def recv(self): self.pre_receive.send(sender=self.__class__) data = self.commsock.recv(self.max_packet_size) self.post_receive.send(sender=self.__class__, data=data) return data #============================== def close(self): self._close = True if self.sock: self.sock.close() self.sock = False if self.clientsock: self.clientsock.close() self.clientsock = False self.commsock = False #============================== def set_protocol(self, protocol=None): self.close() if not protocol: protocol = self.protocol self.protocol = protocol if protocol == "tcp": self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) elif protocol == "udp": self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) #============================== def client(self): while self.isAlive(): self.close() time.sleep(0.05) self.set_protocol() self.mode = "client" self.pre_connect.send(sender=self.__class__) self.sock.connect((self.host, self.port)) self.post_connect.send(sender=self.__class__) self.start() #============================== def server(self): while self.isAlive(): self.close() time.sleep(0.05) self.set_protocol() self.mode = "server" self.sock.bind((self.host, self.port)) if self.protocol == "tcp": self.sock.listen(5) self.start() #============================== def run(self): self._close = False data = False self.commsock = self.sock if self.mode == "server" and self.protocol == "tcp": # this mode and protocol is ready at this point self.ready.send(sender=self.__class__) self.clientsock, addr = self.sock.accept() self.commsock = self.clientsock self.post_accept.send(sender=self.__class__) else: # all other modes and protocols are ready at this point self.ready.send(sender=self.__class__) while not self._close: data = self.recv() if not data: self.close()
class ExePlugin(Plugin): """Supported commands: exec, execr, lo3""" #============================== def __init__(self, *args, **kwargs): Plugin.__init__(self, *args, **kwargs) command_handler.event.connect(get_dispatcher(self)) self.pre_lo3 = Signal() self.post_lo3 = Signal() self.performing_lo3 = False #============================== @command('exec', 'execr') def on_command(self, command, params, silent, **kwargs): extra = kwargs.get('extra', {}) uniqueid = extra.get('uniqueid', '') # We don't have access. Return. if not has_access(uniqueid, 'admin'): # Keep processing other plugins. return True if (command == 'exec' or command == 'execr') and params: self.exec_(params) if command == 'execr': rcon_client.cvar('sv_restart', '1') # Keep processing other plugins. return True #============================== def exec_(self, name): if not name: return # Grab the location of our scripts path = cget('plugins', 'exec', 'scripts_path', default=os.path.join(os.path.dirname(__file__), 'scripts')) # Iterate through the scripts dir and try to find any file matching name. list = os.listdir(path) for file in list: file_name = os.path.splitext(file)[0] if name == file_name: fp = open(os.path.join(path, file), 'r') for line in fp: rcon_client.command(line, deferred=False) fp.close() break #============================== @command('lo3') def on_lo3(self, command, params, silent, **kwargs): extra = kwargs.get('extra', {}) uniqueid = extra.get('uniqueid', '') if not has_access(uniqueid, 'admin'): return True if command == 'lo3': # Don't do lo3 if we're already doing lo3. if self.performing_lo3: return True self.performing_lo3 = True self.pre_lo3.send(sender=self.__class__) self.exec_(cget('plugins', 'exec', 'exec_on_lo3')) # Get the configuration options for going lo3. default_lo3_messages = ['[ Going live on 3 restarts ]', '[ Two more restarts ]', '[ Last restart ]'] default_lo3_delays = ['2', '2', '5'] lo3_messages = cget('plugins', 'exec', 'lo3_messages', default=default_lo3_messages) lo3_delays = cget('plugins', 'exec', 'lo3_delays', default=default_lo3_delays) lo3_live_message = cget('plugins', 'exec', 'lo3_live_message', default='[* LIVE LIVE LIVE *]') #============================== def do_restarts(index): if index < len(lo3_messages): message = lo3_messages[index] delay = lo3_delays[index] rcon_client.hsay('', message) rcon_client.command('sv_restart', delay) index += 1 reactor.callLater(int(delay)+0.9, do_restarts, index) else: self.performing_lo3 = False rcon_client.hsay('', lo3_live_message) self.post_lo3.send(sender=self.__class__) do_restarts(0)
def _init_signals(self): self.data = Signal() self.ready = Signal() self.event = Signal() self.unhandled_event = Signal()
class RconProcessor(object): #============================== def __init__(self): self._init_signals() self.events = { 'user_connected': { 'regex': re.compile(r'^"(?P<name>.*?)<(?P<userid>\d+)><(?P<uniqueid>.*?)><(?P<team>.*?)>" connected, address "(?P<ip>.*?):(?P<port>.*?)"') }, 'user_validated': { 'regex': re.compile(r'^"(?P<name>.*?)<(?P<userid>\d+)><(?P<uniqueid>.*?)><(?P<team>.*?)>" STEAM USERID validated') }, 'user_entered': { 'regex': re.compile(r'^"(?P<name>.*?)<(?P<userid>\d+)><(?P<uniqueid>.*?)><(?P<team>.*?)>" entered the game') }, 'user_joined_team': { 'regex': re.compile(r'^"(?P<name>.*?)<(?P<userid>\d+)><(?P<uniqueid>.*?)><.*?>" joined team "(?P<team>.*?)"') }, 'user_say': { 'regex': re.compile(r'^"(?P<name>.*?)<(?P<userid>\d+)><(?P<uniqueid>.*?)><(?P<team>.*?)>" say(_(?P<to>.*?))? "(?P<message>.*)"( \((?P<status>.*?)\))?') }, 'user_changed_name': { 'regex': re.compile(r'^"(?P<name>.*?)<(?P<userid>\d+)><(?P<uniqueid>.*?)><.*?>" changed name to "(?P<new_name>.*?)"') }, 'user_triggered': { 'regex': re.compile(r'^"(?P<name>.*?)<(?P<userid>\d+)><(?P<uniqueid>.*?)><(?P<team>.*?)>" triggered "(?P<event>.*?)"') }, 'world_triggered': { 'regex': re.compile(r'^World triggered "(?P<event>.*?)"( \(CT "(?P<ct_score>\d+)"\) \(T "(?P<t_score>\d+)"\))?') }, 'server_say': { 'regex': re.compile(r'^Server say "(?P<message>.*?)"') }, 'server_cvar': { 'regex': re.compile(r'^Server cvar "(?P<cvar>.*?)" = "(?P<value>.*?)"') }, 'team_scored': { 'regex': re.compile(r'^Team "(?P<team>.*?)" scored "(?P<score>.*?)" with "(?P<players>.*?)" players') }, 'team_triggered': { 'regex': re.compile(r'^Team "(?P<team>.*?)" triggered "(?P<event>.*?)"( \(CT "(?P<ct_score>\d+)"\) \(T "(?P<t_score>\d+)"\))?') } } #============================== def _init_signals(self): self.data = Signal() self.ready = Signal() self.event = Signal() self.unhandled_event = Signal() #============================== def run(self): self.sock = SignalSocket(config['rcon']['local']['host'], int(config['rcon']['local']['port']), 'udp') self.sock.post_receive.connect(self._on_sock_receive) self.sock.ready.connect(self._on_sock_ready) self.sock.server() #============================== def add_event(self, name, regex): if name in self.events: raise EventError('Event already exists') if isinstance(regex, str): regex = re.compile(str) self.events[name] = { 'regex': regex } #============================== def _on_sock_ready(self, **kwargs): self.ready.send(sender=self.__class__) #============================== def _on_sock_receive(self, data, **kwargs): self.data.send(sender=self.__class__, data=data) #log L date - time: response null, null, date, null, time, response = data[4:-2].split(' ', 5) #log.debug(response) found_event = False for event in self.events: m = self.events[event]['regex'].match(response) if m: self.event.send(sender=self.__class__, event=event, data=m.groupdict()) found_event = True break # If the event wasn't found, then fire the unhandled_event in case some plugin wants to handle it. # Though, you could just use add_event instead. if not found_event: self.unhandled_event.send(sender=self.__class__, data=response)