def Ts3_connect(self, host, port, user, password, vserver, clientname, channels): ''' This funcion does the connect, login etc .. part. if it dosent fail, it will start the Ts3_collect_loop function ''' ######################################## # try and connect n times. reconnect = 0 while reconnect < 4: reconnect = reconnect + 1 # -------------------------- # Connect.. try: self.ts3_server = TS3Server(host, port) self.ts3_connected = True reconnect = 4 Logstring = CT().GetTime( ) + ' : Ts3 ServerQuery connecting to server : ' + str( host) + ":" + str(port) self.bec.colorprint.default(Logstring) break except Exception, Ts3_connect_error: Logstring = CT().GetTime( ) + ' : Ts3 ServerQuery connection failed, retry ' + str( reconnect) + '/4' self.bec.colorprint.system(Logstring) pass time.sleep(4)
def upload(self, ftpadd, ftpprt, ftpuser, ftppw, dir, file): ''' will uploade the file to a ftp server.. this function is called from create_xmlfile once the xml file is created.''' retrys = 0 while retrys < 3: try: ftpclient = ftplib.FTP() ftpclient.connect(ftpadd, ftpprt) ftpclient.login(ftpuser, ftppw) # if using home dir. change the location. if self.Ftp_Dir: ftpclient.cwd(dir) ftp_cmd = 'STOR ' + dir + '/' + file.split("\\")[-1] else: ftp_cmd = 'STOR ' + file.split("\\")[-1] xmlfile = open(os.getcwd() + "\\" + file, 'rb') ftpclient.storbinary(ftp_cmd, xmlfile) xmlfile.close() ftpclient.quit() retrys = 3 break except Exception, error: print CT().GetTime() + ' : Status Plugin, Ftp Error :', error retrys += 1 if debug: print CT().GetTime() + ' :', error pass
def sniff_badnames(self): while True: try: sniff_old = os.stat( self.bec.Bec_Cfg_Misc_NickFilterFile ).st_mtime time.sleep( self.checkinterval ) sniff_new = os.stat( self.bec.Bec_Cfg_Misc_NickFilterFile ).st_mtime except: # so many issue. ifile removed etc.. sniff_old = False sniff_new = False if Debug: Logstring = CT().GetTime()+" Error in checking Badnames file" print Logstring,":\n",WatchDog_fileread_error FL().LogBecError(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) if sniff_old != sniff_new: try: self.bec._Bec_unvalidnicks = FL().ReadFile( self.bec.Bec_Cfg_Misc_NickFilterFile ) if Debug: Logstring = CT().GetTime()+' : Badnames file changed. reloading data...' FL().LogBeClient(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) print Logstring except Exception, WatchDog_fileread_error: self.bec._Bec_unvalidnicks = False if Debug: Logstring = CT().GetTime()+" Error loading Badnames file" print Logstring,":\n",WatchDog_fileread_error FL().LogBecError(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) pass
def sniff_be_filters(self): # Append the mission prefix to the list of filters. befilters = BE_FILTER_FILES[:] bemf = [] if len(MISSIONS) > 0: for mission in MISSIONS: for filter in befilters: missionfilter = mission + "\\" + filter bemf.append(missionfilter) # Validate the file path. see which exists.. befilters = befilters + bemf vaild_befilters = [] for file in befilters: if os.path.isfile(self.bec.Bec_Cfg_Main_BePath + "\\" + file): vaild_befilters.append(file) run = True if len(vaild_befilters) == 0: run = False Logstring = CT().GetTime( ) + " : No BE filter files found or is not defined.. Skipping watchdog for BE filter files." print Logstring FL().LogBecError(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) while run: check_list = {} for file in vaild_befilters: try: sniff_old = os.stat(self.bec.Bec_Cfg_Main_BePath + "\\" + file).st_mtime check_list[file] = sniff_old except: check_list[file] = False time.sleep(self.checkinterval) for file in vaild_befilters: try: sniff_old = os.stat(self.bec.Bec_Cfg_Main_BePath + "\\" + file).st_mtime except: sniff_old = False if sniff_old != check_list[file]: if file.endswith("scripts.txt"): self.bec._Bec_queuelist.append("loadScripts") else: self.bec._Bec_queuelist.append("loadEvents") if Debug: Logstring = CT().GetTime( ) + ' : BE Filter file:' + file + ' was changed. reloading data...' FL().LogBeClient(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) print Logstring
def sniff_commands(self): while True: try: sniff_old = os.stat(self.bec.Bec_Cfg_Main_Commands).st_mtime time.sleep(self.checkinterval) sniff_new = os.stat(self.bec.Bec_Cfg_Main_Commands).st_mtime except: # so many issue. ifile removed etc.. sniff_old = False sniff_new = False if Debug: Logstring = CT().GetTime( ) + " Error in checking Command file" print Logstring, ":\n", WatchDog_fileread_error FL().LogBecError(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) if sniff_old != sniff_new: try: # Get the updated command file test = XP()._commands(self.bec.Bec_Cfg_Main_Commands) # If we have commands, continue... if len(test) > 0: self.bec._Bec_commands = test if Debug: Logstring = CT().GetTime( ) + ' : Command file changed. reloading data...' FL().LogBeClient(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) print Logstring # We have removed all commands form the commands.xml file. else: # set the dict empty... self.bec._Bec_commands = {} if Debug: Logstring = CT().GetTime( ) + ' : Command file changed. But no commands defined...' FL().LogBeClient(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) print Logstring except Exception, WatchDog_fileread_error: if Debug: Logstring = CT().GetTime( ) + " Error Parsing Command file" print Logstring, ":\n", WatchDog_fileread_error FL().LogBecError(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) pass
def sniff_admins(self): while True: try: sniff_old = os.stat( self.bec.Bec_Cfg_Main_Admins ).st_mtime time.sleep( self.checkinterval ) sniff_new = os.stat( self.bec.Bec_Cfg_Main_Admins ).st_mtime except: # so many issue. ifile removed etc.. sniff_old = False sniff_new = False if Debug: Logstring = CT().GetTime()+" Error in checking Admin file" print Logstring,":\n",WatchDog_fileread_error FL().LogBecError(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) if sniff_old != sniff_new: try: # Get the updated file. test = XP()._admin( self.bec.Bec_Cfg_Main_Admins ) # If we have admins, continue... if len(test) > 0: # if we removed an admin from the file that was online. update this too. for key in self.bec.Bec_adminsconnected.keys(): guid = self.bec.Bec_adminsconnected[key][1] if not guid in test.keys(): del self.bec.Bec_adminsconnected[key] self.bec._Bec_admins = test if Debug: Logstring = CT().GetTime()+' : Admin file changed. reloading data...' FL().LogBeClient(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) print Logstring # we removed all our admins from the admins.xml file... else: # set the dict empty... self.bec._Bec_admins = {} self.bec.Bec_adminsconnected = {} if Debug: Logstring = CT().GetTime()+' : Admin file changed. But no admins defined...' FL().LogBeClient(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) print Logstring except Exception, WatchDog_fileread_error: if Debug: Logstring = CT().GetTime()+" Error Parsing Admin file" print Logstring,":\n",WatchDog_fileread_error FL().LogBecError(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) pass
def extended_data(*args, **kwargs): try: return func(*args, **kwargs) finally: self = args[0] beid = args[1] name = args[2] guid = args[3] pip = args[4] reason = args[5] if self.ts3_connected: sendts3msg = True for bemsg in self.BE_msg_ignores: # Reasons on battleye has a max length of 64 chars.. its suppose to increase in future. if len(bemsg) > 64: bemsg = bemsg[0:64] if reason.decode("utf-8").startswith(bemsg): sendts3msg = False break if sendts3msg: if len(self.adminlist_kick) > 0: msg = name + " : Was Kicked : " + reason self.ts3_stack.append([self.adminlist_kick, msg]) if debug: print CT().GetTime() + ' :', msg
def sniff_be_filters(self): '''todo''' while True: check_list = {} for file in BE_FILTER_FILES: try: sniff_old = os.stat(self.bec.Bec_Cfg_Main_BePath + "\\" + file).st_mtime check_list[file] = sniff_old except: check_list[file] = False time.sleep(self.checkinterval) for file in BE_FILTER_FILES: try: sniff_old = os.stat(self.bec.Bec_Cfg_Main_BePath + "\\" + file).st_mtime except: sniff_old = False if sniff_old != check_list[file]: if file.startswith("scripts"): self.bec._Bec_queuelist.append("loadScripts") else: self.bec._Bec_queuelist.append("loadEvents") if Debug: Logstring = CT().GetTime( ) + ' : BE Filter file:' + file + ' was changed. reloading data...' FL().LogBeClient(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) print Logstring
def dogs_sniff_my_files(self): ############################### # Admins.xml try: thread.start_new_thread(self.sniff_admins,()) if Debug: Logstring = CT().GetTime()+' : Creating watchdog for admin file...' FL().LogBeClient(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) print Logstring except Exception, WatchDog_admins_threadtask_error: if Debug: Logstring = CT().GetTime()+" : Can't create watchdog for admin file" print Logstring,":\n",WatchDog_admins_threadtask_error FL().LogBecError(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) pass
def Ts3_threadtask(self): ''' start new work thread to collect ts3 info on socket..''' try: thread.start_new_thread(self.Ts3_collect, ()) except Exception, Ts3_threadtask_error: if debug: print CT().GetTime() + ' :', Ts3_threadtask_error pass
def limiter(self): ''' this function is started and run by a looping task''' x = self.connections_total - self.connections_total_delta if x >= self.consec: self.server_locked = True self.server_lock_time = datetime.datetime.now() self.bec._Bec_queuelist.append("#lock") print CT().GetTime()+" : Bec Activating Flood Control : Server Locked" else: if self.server_locked: checktime = self.server_lock_time + timedelta(seconds=self.locktime) if checktime < datetime.datetime.now(): self.server_locked = False self.bec._Bec_queuelist.append("#unlock") print CT().GetTime()+" : Bec Deactivating Flood Control : Server Unlocked" self.connections_total_delta = self.connections_total
def sniff_whitelist(self): while True: try: sniff_old = os.stat( self.bec.Bec_Cfg_Misc_WhiteListFile).st_mtime time.sleep(self.checkinterval) sniff_new = os.stat( self.bec.Bec_Cfg_Misc_WhiteListFile).st_mtime except: # so many issue. ifile removed etc.. sniff_old = False sniff_new = False if Debug: Logstring = CT().GetTime( ) + " Error in checking Whitelist file" print Logstring, ":\n", WatchDog_fileread_error FL().LogBecError(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) if sniff_old != sniff_new: try: self.bec._Bec_whitelist = FL().ReadWhiteListFile( self.bec.Bec_Cfg_Misc_WhiteListFile) if Debug: Logstring = CT().GetTime( ) + ' : Whitelist file changed. reloading data...' FL().LogBeClient(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) print Logstring except Exception, WatchDog_fileread_error: # if an error occures when reading the whitelist file. # disable the whitelist system until the file is valid. # self.bec._Bec_whitelist = False # we may not want to do that since the list may already contain guids of players... # and the data from the file is read to mem. the onconnect will use this as the checkpoint. # we can validate the list instead. if Debug: Logstring = CT().GetTime( ) + " Error in reading Whitelist file" print Logstring, ":\n", WatchDog_fileread_error FL().LogBecError(self.bec.Bec_Cfg_Main_LogDirPath, Logstring)
def sniff_whitelist(self): while True: try: sniff_old = os.stat( self.bec.Bec_Cfg_Misc_WhiteListFile).st_mtime time.sleep(self.checkinterval) sniff_new = os.stat( self.bec.Bec_Cfg_Misc_WhiteListFile).st_mtime except: # so many issue. ifile removed etc.. sniff_old = False sniff_new = False if Debug: Logstring = CT().GetTime( ) + " Error in checking Whitelist file" print Logstring, ":\n", WatchDog_fileread_error FL().LogBecError(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) if sniff_old != sniff_new: try: self.bec._Bec_whitelist = FL().ReadWhiteListFile( self.bec.Bec_Cfg_Misc_WhiteListFile) # If no guids in the list. we force a false guid to the variable, # This is done as a workaround for the whitelist bug when the file is empty... # Thanks Claus Lauridsen for reporting this... if not self.bec._Bec_whitelist: self.bec._Bec_whitelist = [ u'ffffffffffffffffffffffffffffffff' ] if Debug: Logstring = CT().GetTime( ) + ' : Whitelist file changed. reloading data...' FL().LogBeClient(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) print Logstring except Exception, WatchDog_fileread_error: self.bec._Bec_whitelist = False if Debug: Logstring = CT().GetTime( ) + " Error in reading Whitelist file" print Logstring, ":\n", WatchDog_fileread_error FL().LogBecError(self.bec.Bec_Cfg_Main_LogDirPath, Logstring)
class WatchDogs(object): def __init__(self, instance): self.bec = instance self.checkinterval = 5 # never set 0 self.dogs_sniff_my_files() # function to start the monitor threads. # we create one thread for each file we want to monitor. def dogs_sniff_my_files(self): ############################### # Admins.xml try: thread.start_new_thread(self.sniff_admins, ()) if Debug: Logstring = CT().GetTime( ) + ' : Creating watchdog for admin file...' FL().LogBeClient(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) print Logstring except Exception, WatchDog_admins_threadtask_error: if Debug: Logstring = CT().GetTime( ) + " : Can't create watchdog for admin file" print Logstring, ":\n", WatchDog_admins_threadtask_error FL().LogBecError(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) pass ############################### # Commands.xml try: thread.start_new_thread(self.sniff_commands, ()) if Debug: Logstring = CT().GetTime( ) + ' : Creating watchdog for command file...' FL().LogBeClient(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) print Logstring except Exception, WatchDog_commands_threadtask_error: if Debug: Logstring = CT().GetTime( ) + " : Can't create watchdog for command file" print Logstring, ":\n", WatchDog_commands_threadtask_error FL().LogBecError(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) pass
def get_arma_info(self): '''Return the time when the server was started. if not possible, return False. ''' if self.bec.armapid: try: proc = psutil.Process(self.bec.armapid) arma_time = proc.create_time except Exception, error: arma_time = None if debug: print CT().GetTime() + ' : Status Plugin, Error :', error pass finally:
def extended_data(*args, **kwargs): try: return func(*args, **kwargs) finally: ''' it will notify a ts3 admins who are set to get "nfu" messages. ''' self = args[0] chat_channel = args[1].groups()[0] name = args[1].groups()[1] chat_text = args[1].groups()[2] beid = "-1" # default, set to all. if chat_text.startswith(self.ts3settings['ts3_triggerword'] ) and self.ts3_connected: # Get the beid of the player.. players get id once they are unverified/verified for guid in self.bec.Bec_playersconnected.keys(): if self.bec.Bec_playersconnected[guid][1] == name: beid = self.bec.Bec_playersconnected[guid][0] break if len(chat_text) >= len( self.ts3settings['ts3_triggerword']) + 5: msg = str(name) + " : " + chat_text[4::] if len(self.adminlist_chat) > 0: self.ts3_stack.append([self.adminlist_chat, msg]) cmd = "say " + str( beid ) + " Your Ts3 message has been sent to the Ts3 Admins. Thank you!" self.bec._Bec_queuelist.append(cmd) if debug: print CT().GetTime() + ' :', cmd else: cmd = "say " + str( beid ) + " Your Ts3 message is to short. use atleast 4 letters." self.bec._Bec_queuelist.append(cmd) if debug: print CT().GetTime() + ' :', cmd
def Ts3_collect(self): ''' This function will request ts3 user info, connected arma3 players. and do its stuff according to what the settings are like. Basic task of this function is to kick or send Arma3 players messages about getting on the Ts3 server ''' def get_clientinfo(): clients = None try: clients = self.ts3_server.clientinfo() self.get_clientinfo_ret = 0 except Exception, Ts3_clientinfo_error: pass if clients: return clients else: # if we could not get the clients retry 3 times before we reconnect. self.get_clientinfo_ret += 1 if self.get_clientinfo_ret >= 3: Logstring = CT().GetTime( ) + ' : Ts3 ServerQuery connection has most likely been lost' self.bec.colorprint.system(Logstring) # reinit self.ts3_channelid_deny = [] self.ts3_channelid_allow = [] self.ts3_player_warning = {} self.ts3_clients = {} self.ts3_server = False self.ts3_channels = False self.ts3_connected = False # and reconnect !! #try: # self.Ts3CollectLoopTask.stop() #except: # pass self.Ts3_connect(self.ts3settings['ts3_host'], self.ts3settings['ts3_port'], self.ts3settings['ts3_user'], self.ts3settings['ts3_password'], self.ts3settings['ts3_vserv'], self.ts3settings['ts3_clientname'], self.ts3settings['ts3_channles']) else: get_clientinfo()
def extended_data(*args, **kwargs): try: return func(*args, **kwargs) finally: self = args[0] beid = args[1] name = args[2] guid = args[3] pip = args[4] reason = args[5] if self.ts3_connected: if len(self.adminlist_hack) > 0: msg = str(name) + " : Was Kicked For: " + reason self.ts3_stack.append([self.adminlist_hack, msg]) if debug: print CT().GetTime() + ' :', msg
def Ts3_msg_stack(self): ''' a thread that will work as loop , all messages sendt to admins are handled by this thread. messages will be sent with 1.5 sec delay This is done incase multiple things happen, ie chat and kick at same time if packets are sendt with little to no delay. they may not be recived by the server. ''' while True: time.sleep(1.5) try: if len(self.ts3_stack) > 0: admins = self.ts3_stack[0][0] msg = self.ts3_stack[0][1] self.ts3_server.send_admin_message(admins, msg) self.ts3_stack.pop(0) except Exception, Ts3_msgstack_error: if debug: Logstring = CT().GetTime() + ' : Ts3 msg stack error' self.bec.colorprint.system(Logstring) pass
Logstring = CT().GetTime()+" : Can't create watchdog for command file" print Logstring,":\n",WatchDog_commands_threadtask_error FL().LogBecError(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) pass ############################### # Whitelist file if self.bec.Bec_Cfg_Misc_WhiteListFile: if not self.bec._Bec_whitelist: self.bec._Bec_whitelist.append('ffffffffffffffffffffffffffffffff') try: thread.start_new_thread(self.sniff_whitelist,()) if Debug: Logstring = CT().GetTime()+' : Creating watchdog for whitelist file...' FL().LogBeClient(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) print Logstring except Exception, WatchDog_whitelist_threadtask_error: if Debug: Logstring = CT().GetTime()+" : Can't create watchdog for whitelist file" print Logstring,":\n",WatchDog_whitelist_threadtask_error FL().LogBecError(self.bec.Bec_Cfg_Main_LogDirPath, Logstring) pass ############################### # Badwords file if self.bec._Bec_unwantedwords: try: thread.start_new_thread(self.sniff_badwords,()) if Debug:
class BecTs3(object): ''' A Ts3 Plugin for Bec. This plugin will extend some function in Bec Feel Free to modify it.. ''' def __init__(self, instance): self.bec = instance self.Bec_ConfigFile = self.bec.cfgval.options.filename # Get the config file the current Bec instance uses. self.Ts3Settings = Ts3_Settings.Ts3Servers( self.Bec_ConfigFile) # Get the settings for this config file. self.ts3_stack = [] if self.Ts3Settings: self.Collect_Loop_Time = 20 # sec for each time a ts3 query request. # settings from the settings.py file self.ts3settings = { 'ts3_host': self.Ts3Settings[0], 'ts3_port': self.Ts3Settings[1], 'ts3_user': self.Ts3Settings[2], 'ts3_password': self.Ts3Settings[3], 'ts3_vserv': self.Ts3Settings[4], 'ts3_clientname': self.Ts3Settings[5], 'ts3_required_connection': self.Ts3Settings[6], 'ts3_required_numwarnings': self.Ts3Settings[7], 'ts3_required_kick_message': self.Ts3Settings[8], 'ts3_required_warn_message': self.Ts3Settings[9], 'ts3_channles': self.Ts3Settings[10], 'ts3_triggerword': self.Ts3Settings[11], 'ts3_admins': self.Ts3Settings[12] } # This are kick messages we like to ignore. no need to send them to ts3 admins # Note. BE kick messages are max 64 chars long, the items in this list will be truncated to 64 chars if they are longer. self.BE_msg_ignores = ( "Client not responding", "Invalid GUID", "Ping too high (", "Unknown Game Version", "Corrupted Memory #", "Global Ban #", "Failed to update", "Bad Player Name", "Admin Kick (BEC : Invalid Name)", "Admin Kick (BEC : Fix your player name, it needs to be ASCII chars only)", "Admin Kick (BEC : Lobby idling to long)", "Admin Kick (BEC : Only Reserved Slots Left)", "Admin Kick (BEC : Your player name is to long)", "Admin Kick (BEC : Your guid is not white-listed on this server)", "Admin Kick (BEC : Your player name is not allowed on this server)", "Admin Kick (BEC : Your player name can not contain any of the chars:", "Admin Kick (" + self.bec.Bec_Cfg_Misc_WhileListKickMsg + ")", "Admin Kick (" + self.bec.Bec_Cfg_Misc_SlotLimit_Msg + ")", "Admin Kick (" + self.ts3settings['ts3_required_kick_message'], "Admin Kick (BEC : This name is not allowed to be used to this server)" ) # Normaly the trigger word would be enough, but since Bec might have some restrictions on channels, # to avoid giving warning, add the triggerword to the commandlist. # for the command dict, the 1st item must be 100. the last item is the desctription of the command. # all other items in the list is set as a empty string. self.bec._Bec_commands[self.ts3settings['ts3_triggerword']] = [ 100, "", "", "", "Notify a ts3 admin about a problem." ] self.ts3_channelid_deny = [] self.ts3_channelid_allow = [] self.ts3_player_warning = {} self.ts3_clients = {} self.ts3_server = None self.ts3_channels = False self.ts3_connected = False self.get_clientinfo_ret = 0 ## Make copy. self.org_func_connected = self.bec._be_connected self.org_func_disconnected = self.bec._be_disconnected self.org_func_be_kick = self.bec._be_kick self.org_func_be_ban = self.bec._be_ban self.org_func_be_hack = self.bec._be_hack self.org_func_chat = self.bec._be_chat ## Extend self.bec._be_connected = self.player_connected self.bec._be_disconnected = self.player_disconnected self.bec._be_kick = self.player_kick self.bec._be_ban = self.player_ban self.bec._be_hack = self.player_hack self.bec._be_chat = self.player_chat # Start the work threads self.Ts3CollectLoopTask = task.LoopingCall(self.Ts3_threadtask) #self.Ts3CollectLoopTask.start(self.Collect_Loop_Time, False) thread.start_new_thread(self.Ts3_msg_stack, ()) def admin_settings(admins, type): a = {} for uid in admins: if admins[uid][type] == 1: a[uid] = admins[uid] return a self.adminlist_kick = admin_settings( self.ts3settings['ts3_admins'], 1) self.adminlist_ban = admin_settings(self.ts3settings['ts3_admins'], 2) self.adminlist_hack = admin_settings( self.ts3settings['ts3_admins'], 3) self.adminlist_chat = admin_settings( self.ts3settings['ts3_admins'], 4) # Connect function. self.Ts3_connect(self.ts3settings['ts3_host'], self.ts3settings['ts3_port'], self.ts3settings['ts3_user'], self.ts3settings['ts3_password'], self.ts3settings['ts3_vserv'], self.ts3settings['ts3_clientname'], self.ts3settings['ts3_channles']) else: Logstring = CT().GetTime( ) + ' : The Ts3 Plugin is not Configured for this server, Recheck settings' self.bec.colorprint.system(Logstring) if debug: print CT().GetTime() + ' :', self.Bec_ConfigFile, ':', SERVERS ## ----------------------- ## # Ts3 functions... def Ts3_connect(self, host, port, user, password, vserver, clientname, channels): ''' This funcion does the connect, login etc .. part. if it dosent fail, it will start the Ts3_collect_loop function ''' ######################################## # try and connect n times. reconnect = 0 while reconnect < 4: reconnect = reconnect + 1 # -------------------------- # Connect.. try: self.ts3_server = TS3Server(host, port) self.ts3_connected = True reconnect = 4 Logstring = CT().GetTime( ) + ' : Ts3 ServerQuery connecting to server : ' + str( host) + ":" + str(port) self.bec.colorprint.default(Logstring) break except Exception, Ts3_connect_error: Logstring = CT().GetTime( ) + ' : Ts3 ServerQuery connection failed, retry ' + str( reconnect) + '/4' self.bec.colorprint.system(Logstring) pass time.sleep(4) ######################################## # if we got connected. if self.ts3_connected: # -------------------------- # Log in.. try: self.ts3_server.login(str(user), str(password)) Logstring = CT().GetTime() + ' : Ts3 ServerQuery logged in' self.bec.colorprint.default(Logstring) except Exception, Ts3_login_error: Logstring = CT().GetTime() + ' : Ts3 ServerQuery login failed' self.bec.colorprint.system(Logstring) # -------------------------- # Set virtual server try: self.ts3_server.use_vs(vserver) except Exception, Ts3_VServer_error: Logstring = CT().GetTime( ) + ' : Ts3 ServerQuery virtual server selection failed' self.bec.colorprint.system(Logstring) self.ts3_connected = False
def __init__(self, instance): self.bec = instance self.Bec_ConfigFile = self.bec.cfgval.options.filename # Get the config file the current Bec instance uses. self.Ts3Settings = Ts3_Settings.Ts3Servers( self.Bec_ConfigFile) # Get the settings for this config file. self.ts3_stack = [] if self.Ts3Settings: self.Collect_Loop_Time = 20 # sec for each time a ts3 query request. # settings from the settings.py file self.ts3settings = { 'ts3_host': self.Ts3Settings[0], 'ts3_port': self.Ts3Settings[1], 'ts3_user': self.Ts3Settings[2], 'ts3_password': self.Ts3Settings[3], 'ts3_vserv': self.Ts3Settings[4], 'ts3_clientname': self.Ts3Settings[5], 'ts3_required_connection': self.Ts3Settings[6], 'ts3_required_numwarnings': self.Ts3Settings[7], 'ts3_required_kick_message': self.Ts3Settings[8], 'ts3_required_warn_message': self.Ts3Settings[9], 'ts3_channles': self.Ts3Settings[10], 'ts3_triggerword': self.Ts3Settings[11], 'ts3_admins': self.Ts3Settings[12] } # This are kick messages we like to ignore. no need to send them to ts3 admins # Note. BE kick messages are max 64 chars long, the items in this list will be truncated to 64 chars if they are longer. self.BE_msg_ignores = ( "Client not responding", "Invalid GUID", "Ping too high (", "Unknown Game Version", "Corrupted Memory #", "Global Ban #", "Failed to update", "Bad Player Name", "Admin Kick (BEC : Invalid Name)", "Admin Kick (BEC : Fix your player name, it needs to be ASCII chars only)", "Admin Kick (BEC : Lobby idling to long)", "Admin Kick (BEC : Only Reserved Slots Left)", "Admin Kick (BEC : Your player name is to long)", "Admin Kick (BEC : Your guid is not white-listed on this server)", "Admin Kick (BEC : Your player name is not allowed on this server)", "Admin Kick (BEC : Your player name can not contain any of the chars:", "Admin Kick (" + self.bec.Bec_Cfg_Misc_WhileListKickMsg + ")", "Admin Kick (" + self.bec.Bec_Cfg_Misc_SlotLimit_Msg + ")", "Admin Kick (" + self.ts3settings['ts3_required_kick_message'], "Admin Kick (BEC : This name is not allowed to be used to this server)" ) # Normaly the trigger word would be enough, but since Bec might have some restrictions on channels, # to avoid giving warning, add the triggerword to the commandlist. # for the command dict, the 1st item must be 100. the last item is the desctription of the command. # all other items in the list is set as a empty string. self.bec._Bec_commands[self.ts3settings['ts3_triggerword']] = [ 100, "", "", "", "Notify a ts3 admin about a problem." ] self.ts3_channelid_deny = [] self.ts3_channelid_allow = [] self.ts3_player_warning = {} self.ts3_clients = {} self.ts3_server = None self.ts3_channels = False self.ts3_connected = False self.get_clientinfo_ret = 0 ## Make copy. self.org_func_connected = self.bec._be_connected self.org_func_disconnected = self.bec._be_disconnected self.org_func_be_kick = self.bec._be_kick self.org_func_be_ban = self.bec._be_ban self.org_func_be_hack = self.bec._be_hack self.org_func_chat = self.bec._be_chat ## Extend self.bec._be_connected = self.player_connected self.bec._be_disconnected = self.player_disconnected self.bec._be_kick = self.player_kick self.bec._be_ban = self.player_ban self.bec._be_hack = self.player_hack self.bec._be_chat = self.player_chat # Start the work threads self.Ts3CollectLoopTask = task.LoopingCall(self.Ts3_threadtask) #self.Ts3CollectLoopTask.start(self.Collect_Loop_Time, False) thread.start_new_thread(self.Ts3_msg_stack, ()) def admin_settings(admins, type): a = {} for uid in admins: if admins[uid][type] == 1: a[uid] = admins[uid] return a self.adminlist_kick = admin_settings( self.ts3settings['ts3_admins'], 1) self.adminlist_ban = admin_settings(self.ts3settings['ts3_admins'], 2) self.adminlist_hack = admin_settings( self.ts3settings['ts3_admins'], 3) self.adminlist_chat = admin_settings( self.ts3settings['ts3_admins'], 4) # Connect function. self.Ts3_connect(self.ts3settings['ts3_host'], self.ts3settings['ts3_port'], self.ts3settings['ts3_user'], self.ts3settings['ts3_password'], self.ts3settings['ts3_vserv'], self.ts3settings['ts3_clientname'], self.ts3settings['ts3_channles']) else: Logstring = CT().GetTime( ) + ' : The Ts3 Plugin is not Configured for this server, Recheck settings' self.bec.colorprint.system(Logstring) if debug: print CT().GetTime() + ' :', self.Bec_ConfigFile, ':', SERVERS
def create_xmlfile(self): '''create xml file every N sec, interval spesified in the settings file. ''' while True: # aprox sleep time.sleep(self.Interval) #============================================================ # Create xml string. xml_content = False try: # Set new update time. lastupdate_time = datetime.datetime.now().strftime(self.tf) nextupdate_time = (datetime.datetime.now() + timedelta(seconds=self.Interval)).strftime( self.tf) # Get uptime for the ArmA server. aupt = self.get_arma_uptime() # Get Bec uptime. currenttime = datetime.datetime.now().strftime(self.tf) bec_session_time = datetime.datetime.strptime( currenttime, self.tf) - datetime.datetime.strptime( self.start_time, self.tf) # Get number of players online, We use battleye here instead of gamespy info about players.. numplayers = len(self.bec.Bec_playersconnected) xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\n' xml = xml + '<?xml-stylesheet href="reports.xsl" type="text/xsl" ?>\n' xml = xml + '<BecStatus>\n' xml = xml + '\t<hostname>' + self.html_escape( self.gsquery.serveinfo['hostname']) + '</hostname>\n' xml = xml + '\t<gamever>' + self.gsquery.serveinfo[ 'gamever'] + '</gamever>\n' xml = xml + '\t<mapname>' + self.html_escape( self.gsquery.serveinfo['mapname']) + '</mapname>\n' xml = xml + '\t<mission>' + self.html_escape( self.gsquery.serveinfo['mission']) + '</mission>\n' xml = xml + '\t<difficulty>' + self.gsquery.serveinfo[ 'difficulty'] + '</difficulty>\n' xml = xml + '\t<numplayers>' + str( numplayers) + '/' + self.gsquery.serveinfo[ 'maxplayers'] + '</numplayers>\n' xml = xml + '\t<lastupdate>' + str( lastupdate_time) + '</lastupdate>\n' xml = xml + '\t<nextupdate>' + str( nextupdate_time) + '</nextupdate>\n' xml = xml + '\t<becversion>' + self.bec.becversion + '</becversion>\n' xml = xml + '\t<beversion>' + self.bec.beversion + '</beversion>\n' xml = xml + '\t<becuptime>' + str( bec_session_time) + '</becuptime>\n' xml = xml + '\t<becreporter>' + str( self.bec.reporteraccount) + '</becreporter>\n' xml = xml + '\t<serveruptime>' + str( aupt) + '</serveruptime>\n' xml = xml + '\t<kts>' + str(self.kts) + '</kts>\n' xml = xml + '\t<bts>' + str(self.bts) + '</bts>\n' xml = xml + '\t<hts>' + str(self.hts) + '</hts>\n' xml = xml + '\t<cts>' + str(self.cts) + '</cts>\n' xml = xml + '\t<uts>' + str(self.uts) + '</uts>\n' xml = xml + '\t<numadmins>' + str( len(self.bec.Bec_adminsconnected)) + '</numadmins>\n' xml = xml + '\t<numtmpadmins>' + str( len(self.bec.Bec_tempadminsconnected) ) + '</numtmpadmins>\n' xml = xml + '\t<gametype>' + self.gsquery.serveinfo[ 'gametype'] + '</gametype>\n' xml = xml + '\t<gamemode>' + self.gsquery.serveinfo[ 'gamemode'] + '</gamemode>\n' xml = xml + '\t<gameState>' + self.gsquery.serveinfo[ 'gameState'] + '</gameState>\n' xml = xml + '\t<mod>' + self.html_escape( self.gsquery.serveinfo['mod']) + '</mod>\n' xml = xml + '\t<password>' + self.gsquery.serveinfo[ 'password'] + '</password>\n' xml = xml + '\t<equalModRequired>' + self.gsquery.serveinfo[ 'equalModRequired'] + '</equalModRequired>\n' xml = xml + '\t<verifySignatures>' + self.gsquery.serveinfo[ 'verifySignatures'] + '</verifySignatures>\n' xml = xml + '\t<requiredVersion>' + self.gsquery.serveinfo[ 'requiredVersion'] + '</requiredVersion>\n' xml = xml + '\t<reqSecureId>' + self.gsquery.serveinfo[ 'reqSecureId'] + '</reqSecureId>\n' xml = xml + '\t<players>\n' # populate the players node if we got players online... if numplayers > 0: for guid in self.bec.Bec_playersconnected.keys(): ptag = [] nick = self.bec.Bec_playersconnected[guid][1] bid = self.bec.Bec_playersconnected[guid][0] lobby = self.bec.Bec_playersconnected[guid][4] admin = "0" # 0 = none, 1 = admin, 2 = tmp admin wrn = "0" # warnings given to player chatwrn = "0" # chat warnings given to player # if players is admin or tmp admin. if self.bec.Bec_adminsconnected.has_key(nick): admin = "1" elif self.bec.Bec_tempadminsconnected.has_key(nick): admin = "2" # number of warnings given to the player if self.bec.Bec_player_warnings.has_key(nick): if self.bec.Bec_player_warnings[nick] > 0: wrn = str(self.bec.Bec_player_warnings[nick]) # total chat warnings given to player, sums up from all channels. if self.bec.Bec_player_chat_warning.has_key(nick): sum = 0 for e in self.bec.Bec_player_chat_warning[nick]: sum = sum + e if sum > 0: chatwrn = str(sum) cpy_nick = "" try: cpy_nick = nick.decode("ascii") except: try: cpy_nick = nick.decode("utf-8") except Exception, enc_error1: cpy_nick = "N/A" if debug: print CT().GetTime( ) + ' : Status Plugin, ', enc_error1 pass xml = xml + '\t\t<player guid="' + guid + '" bid="' + bid + '" wrn="' + wrn + '" chatwrn="' + chatwrn + '" ingame="' + str( lobby ) + '" admin="' + admin + '">' + self.html_escape( cpy_nick) + '</player>\n' xml = xml + u'\t</players>\n</BecStatus>\n' xml_content = True except Exception, err1: Logstring = CT().GetTime( ) + " : Status Plugin, Error in creating xml string" self.bec.colorprint.system if debug: print CT().GetTime() + ' :', err1 pass
class BecSessionStatus(object): def __init__(self, instance): self.bec = instance self.cfgname = self.bec.cfgval.options.filename self.settings = Status_Settings.Servers(self.cfgname) if self.settings: # format for time. self.tf = '%H:%M:%S - %Y/%m/%d' # Set time when this plugin was loaded. "good enough for Bec start time." self.start_time = datetime.datetime.now().strftime(self.tf) # Get time when the Arma server was started. self.arma_starttime = self.get_arma_info() if self.arma_starttime == None: self.arma_starttime = "N/A" self.kts = 0 # Number of kicks this session self.bts = 0 # Number of bans this session self.hts = 0 # Number of hacks this session self.cts = 0 # Number of connetions this section self.unique_guids = [ ] # list of unique guid that connected this bec session. self.uts = 0 # len of self.unique_guids. self.Use_Ftp = self.settings[0] # Enable ftp or not self.Interval = self.settings[1] self.Ftp_Host = self.settings[2] # ftp add self.Ftp_Port = self.settings[3] # ftp port self.Ftp_User = self.settings[4] # ftp user self.Ftp_Password = self.settings[5] # ftp passw self.Ftp_Dir = self.settings[ 6] # ftp uploade dir. starts with /dirname or is set to None #-------------------------------------- ## Make copy fnc. self.org_func_be_kick = self.bec._be_kick self.org_func_be_ban = self.bec._be_ban self.org_func_be_hack = self.bec._be_hack self.org_func_connected = self.bec._be_connected self.org_func_unverified = self.bec._be_unverified #self.org_func_verified = self.bec._be_verified ## Extend fnc. self.bec._be_kick = self.player_kick self.bec._be_ban = self.player_ban self.bec._be_hack = self.player_hack self.bec._be_connected = self.connected self.bec._be_unverified = self.unverified #self.bec._be_verified = self.verified #-------------------------------------- # Table of chars that will be replaced. this is to avoid issues with xml. self.html_escape_table = { "&": "&", '"': """, "'": "'", ">": ">", "<": "<", "¬": "¬", "": "­", "®": "®", "¯": "¯", "°": "°", "±": "±", "²": "²", "³": "³", "´": "´", "µ": "µ", "¶": "¶", "·": "·", "¸": "¸", "¹": "¹", "º": "º", "»": "»", "¼": "¼", "½": "½", "¾": "¾", "¿": "¿", "À": "À", "Á": "Á", "Â": "Â", "Ã": "Ã", "Ä": "Ä", "Å": "Å", "Æ": "Æ", "Ç": "Ç", "È": "È", "É": "É", "Ê": "Ê", "Ë": "Ë", "Ì": "Ì", "Í": "Í", "Î": "Î", "Ï": "Ï", "Ð": "Ð", "Ñ": "Ñ", "Ò": "Ò", "Ó": "Ó", "Ô": "Ô", "Õ": "Õ", "Ö": "Ö", "×": "×", "Ø": "Ø", "Ù": "Ù", "Ú": "Ú", "Û": "Û", "Ü": "Ü", "Ý": "Ý", "Þ": "Þ", "ß": "ß", "à": "à", "á": "á", "â": "â", "ã": "ã", "ä": "ä", "å": "å", "æ": "æ", "ç": "ç", "è": "è", "é": "é", "ê": "ê", "ë": "ë", "ì": "ì", "í": "í", "î": "î", "ï": "ï", "ð": "ð", "ñ": "ñ", "ò": "ò", "ó": "ó", "ô": "ô", "õ": "õ", "ö": "ö", "÷": "÷", "ø": "ø", "ù": "ù", "ú": "ú", "û": "û", "ü": "ü", "ý": "ý", "þ": "þ", "¡": "¡", "¢": "¢", "£": "£", "¤": "¤", "¥": "¥", "¦": "¦", "§": "§", "¨": "¨", "©": "©", "ª": "ª", "€": "€" } # create a instance of out gs class. self.gsquery = GameSpy(instance) # create a task for the gamespy querying. self.GsCollect = task.LoopingCall(self.gsquery.gsquery) # set the query interval for 10 sec between each request. self.GsCollect.start(10, False) # Start a seperate theread for creating the xml file (and ftp uploade if set to use it) thread.start_new_thread(self.create_xmlfile, ()) def html_escape(self, text): return "".join(self.html_escape_table.get(c, c) for c in text) def create_xmlfile(self): '''create xml file every N sec, interval spesified in the settings file. ''' while True: # aprox sleep time.sleep(self.Interval) #============================================================ # Create xml string. xml_content = False try: # Set new update time. lastupdate_time = datetime.datetime.now().strftime(self.tf) nextupdate_time = (datetime.datetime.now() + timedelta(seconds=self.Interval)).strftime( self.tf) # Get uptime for the ArmA server. aupt = self.get_arma_uptime() # Get Bec uptime. currenttime = datetime.datetime.now().strftime(self.tf) bec_session_time = datetime.datetime.strptime( currenttime, self.tf) - datetime.datetime.strptime( self.start_time, self.tf) # Get number of players online, We use battleye here instead of gamespy info about players.. numplayers = len(self.bec.Bec_playersconnected) xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\n' xml = xml + '<?xml-stylesheet href="reports.xsl" type="text/xsl" ?>\n' xml = xml + '<BecStatus>\n' xml = xml + '\t<hostname>' + self.html_escape( self.gsquery.serveinfo['hostname']) + '</hostname>\n' xml = xml + '\t<gamever>' + self.gsquery.serveinfo[ 'gamever'] + '</gamever>\n' xml = xml + '\t<mapname>' + self.html_escape( self.gsquery.serveinfo['mapname']) + '</mapname>\n' xml = xml + '\t<mission>' + self.html_escape( self.gsquery.serveinfo['mission']) + '</mission>\n' xml = xml + '\t<difficulty>' + self.gsquery.serveinfo[ 'difficulty'] + '</difficulty>\n' xml = xml + '\t<numplayers>' + str( numplayers) + '/' + self.gsquery.serveinfo[ 'maxplayers'] + '</numplayers>\n' xml = xml + '\t<lastupdate>' + str( lastupdate_time) + '</lastupdate>\n' xml = xml + '\t<nextupdate>' + str( nextupdate_time) + '</nextupdate>\n' xml = xml + '\t<becversion>' + self.bec.becversion + '</becversion>\n' xml = xml + '\t<beversion>' + self.bec.beversion + '</beversion>\n' xml = xml + '\t<becuptime>' + str( bec_session_time) + '</becuptime>\n' xml = xml + '\t<becreporter>' + str( self.bec.reporteraccount) + '</becreporter>\n' xml = xml + '\t<serveruptime>' + str( aupt) + '</serveruptime>\n' xml = xml + '\t<kts>' + str(self.kts) + '</kts>\n' xml = xml + '\t<bts>' + str(self.bts) + '</bts>\n' xml = xml + '\t<hts>' + str(self.hts) + '</hts>\n' xml = xml + '\t<cts>' + str(self.cts) + '</cts>\n' xml = xml + '\t<uts>' + str(self.uts) + '</uts>\n' xml = xml + '\t<numadmins>' + str( len(self.bec.Bec_adminsconnected)) + '</numadmins>\n' xml = xml + '\t<numtmpadmins>' + str( len(self.bec.Bec_tempadminsconnected) ) + '</numtmpadmins>\n' xml = xml + '\t<gametype>' + self.gsquery.serveinfo[ 'gametype'] + '</gametype>\n' xml = xml + '\t<gamemode>' + self.gsquery.serveinfo[ 'gamemode'] + '</gamemode>\n' xml = xml + '\t<gameState>' + self.gsquery.serveinfo[ 'gameState'] + '</gameState>\n' xml = xml + '\t<mod>' + self.html_escape( self.gsquery.serveinfo['mod']) + '</mod>\n' xml = xml + '\t<password>' + self.gsquery.serveinfo[ 'password'] + '</password>\n' xml = xml + '\t<equalModRequired>' + self.gsquery.serveinfo[ 'equalModRequired'] + '</equalModRequired>\n' xml = xml + '\t<verifySignatures>' + self.gsquery.serveinfo[ 'verifySignatures'] + '</verifySignatures>\n' xml = xml + '\t<requiredVersion>' + self.gsquery.serveinfo[ 'requiredVersion'] + '</requiredVersion>\n' xml = xml + '\t<reqSecureId>' + self.gsquery.serveinfo[ 'reqSecureId'] + '</reqSecureId>\n' xml = xml + '\t<players>\n' # populate the players node if we got players online... if numplayers > 0: for guid in self.bec.Bec_playersconnected.keys(): ptag = [] nick = self.bec.Bec_playersconnected[guid][1] bid = self.bec.Bec_playersconnected[guid][0] lobby = self.bec.Bec_playersconnected[guid][4] admin = "0" # 0 = none, 1 = admin, 2 = tmp admin wrn = "0" # warnings given to player chatwrn = "0" # chat warnings given to player # if players is admin or tmp admin. if self.bec.Bec_adminsconnected.has_key(nick): admin = "1" elif self.bec.Bec_tempadminsconnected.has_key(nick): admin = "2" # number of warnings given to the player if self.bec.Bec_player_warnings.has_key(nick): if self.bec.Bec_player_warnings[nick] > 0: wrn = str(self.bec.Bec_player_warnings[nick]) # total chat warnings given to player, sums up from all channels. if self.bec.Bec_player_chat_warning.has_key(nick): sum = 0 for e in self.bec.Bec_player_chat_warning[nick]: sum = sum + e if sum > 0: chatwrn = str(sum) cpy_nick = "" try: cpy_nick = nick.decode("ascii") except: try: cpy_nick = nick.decode("utf-8") except Exception, enc_error1: cpy_nick = "N/A" if debug: print CT().GetTime( ) + ' : Status Plugin, ', enc_error1 pass xml = xml + '\t\t<player guid="' + guid + '" bid="' + bid + '" wrn="' + wrn + '" chatwrn="' + chatwrn + '" ingame="' + str( lobby ) + '" admin="' + admin + '">' + self.html_escape( cpy_nick) + '</player>\n' xml = xml + u'\t</players>\n</BecStatus>\n' xml_content = True except Exception, err1: Logstring = CT().GetTime( ) + " : Status Plugin, Error in creating xml string" self.bec.colorprint.system if debug: print CT().GetTime() + ' :', err1 pass #============================================================ # Write the content to the xml file!.. xml_created = False try: if xml_content: filepath = 'Plugins\\Status\\Report\\Bec_' + self.bec.Bec_Cfg_Main_LogDirName + '.xml' file = codecs.open(filepath, u'wb', encoding='utf-8-sig', errors='ignore') file.write(xml) file.close() xml_created = True except Exception, err2: Logstring = CT().GetTime( ) + " : Status Plugin, Error in writing to status.xml file" self.bec.colorprint.system(Logstring) if debug: print CT().GetTime() + ' :', err2 pass
import thread from threading import Lock from twisted.internet import task from Lib.BecClasses import Timec as CT sys.path.append(os.getcwd() + "\\Plugins\\Ts3") import Ts3_Settings from Ts3Classes import * #------------------------------------------------------------------------------------------------- # You do not need to edit anything below this line unless you plan on changing/improving the plugin. SERVERS = Ts3_Settings.SERVERS debug = False if debug: print CT().GetTime() + ' : Ts3 Debug Mode On!!!' class BecTs3(object): ''' A Ts3 Plugin for Bec. This plugin will extend some function in Bec Feel Free to modify it.. ''' def __init__(self, instance): self.bec = instance self.Bec_ConfigFile = self.bec.cfgval.options.filename # Get the config file the current Bec instance uses. self.Ts3Settings = Ts3_Settings.Ts3Servers( self.Bec_ConfigFile) # Get the settings for this config file.