async def checkPermission(self, rctx, cmd): try: cmd = "command_{}".format(cmd) pr = self.PermissionConfig.cfgPermissions_Roles role = "@everyone" #check if everybody can use it if (cmd in pr[role] and pr[role][cmd]): #anyone can use the cmd return True #check if user can use it #Lookup user in linked accounts: for user_id, data in self.user_data.items(): log.info("{} {}".format(data["account_arma3"], rctx.user_guid)) if ("account_arma3" in data and data["account_arma3"][0] == rctx.user_guid): #check if user has permission: server = self.bot.guilds[0] user = discord.utils.get(server.members, id=int(user_id)) if (user): #get user roles, and check if role has permission for role in user.roles: if str(role) in pr.keys(): if (cmd in pr[str(role)] and pr[str(role)][cmd]): return True return False except Exception as e: log.print_exc() log.error(e) return False
def pre_scan(self): try: if (self.maxMissions <= 0): return #disable Event handlers, so they dont trigger self.EH.disabled = True logs = self.getLogs() tempdataMissions = deque(maxlen=self.maxMissions) #scan most recent log. Until enough data is collected #go from newest to oldest log until the data buffer is filled for _log in reversed(logs): log.info("Pre-scanning: " + _log) self.scanfile(_log) if (len(tempdataMissions) + len(self.Missions) <= self.maxMissions): tempdataMissions.extendleft(reversed(self.Missions)) self.Missions = deque(maxlen=self.maxMissions) self.Missions.append({"dict": {}, "data": []}) else: break if (len(tempdataMissions) >= self.maxMissions): break self.Missions = tempdataMissions self.EH.disabled = False except Exception as e: log.print_exc() log.error(e)
def processMission(self, event, data): try: #new mission is being started if (event == "Mission readname"): self.Missions.append({ "dict": { "Server sessionID": self.server_sessionID, event: data }, "data": [] }) elif (event == "Server sessionID"): self.server_sessionID = data[2].group(2) #mission is complete, switching to between mission block elif (event == "Mission finished" or event == "Mission restarted"): log.info("{} {}".format( self.Missions[-1]["dict"]["Mission id"][0], self.Missions[-1]["dict"]["Mission id"][1])) self.Missions[-1]["dict"][event] = data self.Missions.append({ "dict": { "Server sessionID": self.server_sessionID }, "data": [] }) #process data within a mission elif ("Mission" in event): self.Missions[-1]["dict"][event] = data self.Missions[-1]["data"].append(data) except Exception as e: log.print_exc() log.error(e)
def add_role(self, data): role = data["add_role"][0] log.info("Created new role: '{}'".format(role)) self.cfgPermissions_Roles[role] = type(self).cfg.new( type(self).path + "/permissions_{}.json".format(role)) for command in type(self).bot.commands: self.cfgPermissions_Roles[role]["command_" + str(command)] = False
async def genStats(self, ctx): await ctx.send("Generating Player stats...") log.info("[JMW] Updating Player stats") t = threading.Thread(target=self.psg.generateStats()) t.start() self.psg_updated = datetime.datetime.now(datetime.timezone.utc) t.join() await ctx.send("Stats Updated")
def _generateGame(self, gameindex=None): if(gameindex == None): gameindex = 0 log.info("Generating Game, index: '{}'".format(gameindex)) game = self.buildGameBlock(gameindex) dict, game = self.processGameBlock(game) meta, pdata = self.processGameData(game) return [meta, pdata, dict]
async def on_ready(self): await self.bot.wait_until_ready() if ("CommandRcon" not in self.bot.cogs): log.info( "[module] 'CommandRcon' required, but not found in '{}'. Module unloaded" .format(type(self).__name__)) del self return self.CommandRcon = self.bot.cogs["CommandRcon"]
def upgrade_database(self): try: json_f = self.path + "/player_db.json" if (not os.path.isfile(json_f)): return #get the count of tables with the name self.c.execute( ''' SELECT count(name) FROM sqlite_master WHERE type='table' AND name='users' ''' ) if self.c.fetchone()[0] == 0: #load old table with open(json_f) as json_file: data_db = json.load(json_file) data = [] for key, item in data_db.items(): for _item in item: id = None name = None beid = None ip = None date = None if "ID" in _item: id = int(_item["ID"]) if "name" in _item: name = _item["name"] if "beid" in _item: beid = _item["beid"] if "ip" in _item: ip = _item["ip"] if "last-seen" in _item: date = _item["last-seen"] data.append((id, name, beid, ip, date)) self.c.execute(""" CREATE TABLE users ( id INTEGER NOT NULL, name TEXT, beid TEXT, ip TEXT, stamp DATETIME, profileid INTEGER ); """) #date yyyy-MM-dd HH:mm:ss sql = 'INSERT INTO users (id, name, beid, ip, stamp) values(?, ?, ?, ?, ?)' self.c.executemany(sql, data) self.con.commit() json_f_new = json_f.replace(".json", "_old.json") os.rename(json_f, json_f_new) log.info("*** Database has been upgraded! ***") except Exception as e: log.print_exc() log.error(e)
async def task_setStatus(self): while True: try: await asyncio.sleep(60) await self.setStatus() except (KeyboardInterrupt, asyncio.CancelledError): log.info("[asyncio] exiting", task_setStatus) except Exception as e: log.error("setting status failed", e) log.print_exc()
def test(self, msg): try: print(log) print(log.info) log.info(msg) log.warning(msg) log.error(msg) print(log.handlers) return "Sucess" except Exception as e: print(e)
def stop_server(self, pid=-1): if(self.server_pid != None): self.server_pid.kill() self.server_pid = None elif(pid>=0): try: os.kill(pid, 0) except SystemError as e: pass log.info("Terminated process '{}'".format(pid)) else: return False
async def dm_users_new_game(self): if (self.bot.is_closed()): return False msg = "A game just ended, now is the best time to join for a new game!" for user in self.user_data: if "nextgame" in self.user_data[user] and self.user_data[user][ "nextgame"] == True: log.info("sending DM to: " + str(user)) puser = self.bot.get_user(int(user)) await puser.send(msg) self.user_data[user]["nextgame"] = False await self.set_user_data() #save changes
async def bans_watchdog(self): #watches for changes that are not noted in the log (e.g. removal of bans) #on every check the full ban list will be copied, #for large ban lists its recommended to keep the update rate >60s #bans format: ["ID", "GUID", "Time", "Reason"] log.info("Starting ban watchdog") try: while True: await asyncio.sleep(60) await self.check_newBan() except (KeyboardInterrupt, asyncio.CancelledError): log.info("[asyncio] exiting {}".format(bans_watchdog))
async def task_updatePlayerStats(self): await asyncio.sleep(60 * 2) while True: try: log.info("[JMW] Updating Player stats") t = threading.Thread(target=self.psg.generateStats()) t.start() self.psg_updated = datetime.datetime.now(datetime.timezone.utc) except (KeyboardInterrupt, asyncio.CancelledError): pass except Exception as e: log.error("Failed to update player stats", e) log.print_exc() await asyncio.sleep(60 * 60 * 24)
async def watch_log(self): try: update_counter = 0 while (True): #Wait till a log file exsists logs = self.getLogs() if (len(logs) > 0): self.current_log = logs[-1] log.info("current log: " + self.current_log) self.currentLinePos = 0 file = open(self.log_path + self.current_log, "r") for i, l in enumerate(file): pass self.currentLinePos = i + 1 #file.seek(0, 2) #jump to the end of the file try: while (True): #where = file.tell() try: line = file.readline() update_counter += 1 except: line = None if not line: await asyncio.sleep(1) #file.seek(where) if ( update_counter >= 60 ): #only check for new log files every 60s, to reduce IOPS update_counter = 0 if (self.current_log != self.getLogs()[-1]): old_log = self.current_log self.current_log = self.getLogs()[ -1] #update to new recent log self.currentLinePos = 0 file = open( self.log_path + self.current_log, "r") log.info("current log: " + self.current_log) self.EH.check_Event( "Log new", old_log, self.current_log) else: self.currentLinePos += 1 self.line = line #access to last read line (debugging) self.processLogLine(line) except (KeyboardInterrupt, asyncio.CancelledError): log.info("[asyncio] exiting {}".format(watch_log)) except Exception as e: log.error(e) log.print_exc() else: await asyncio.sleep(10 * 60) except (KeyboardInterrupt, asyncio.CancelledError): log.info("[asyncio] exiting {}".format(watch_log)) except Exception as e: log.print_exc() log.error(e)
async def main(): utils.Modules.loadCogs(bot) try: await bot.login(cfg["TOKEN"]) await bot.connect() except (KeyboardInterrupt, asyncio.CancelledError): sys.exit("Bot Terminated (KeyboardInterrupt)") except (KeyError, discord.errors.LoginFailure): log.info("PROMPT: Please configure the bot") input( "\nPlease configure the bot on the settings page. [ENTER to terminte the bot]\n" )
def _start_server(self, port=8000): s_port = port with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: while (s.connect_ex(('localhost', port)) == 0): port += 1 if (port >= 65535): raise ConnectionAbortedError( "Unable to find free port".format(port)) if (s_port != port): log.info("[WARNING] Port '{}' already in use, using '{}' instead.". format(s_port, port)) log.info("Settings page online on: http://localhost:{}/".format(port)) self.httpd = HTTPServer(('localhost', port), SimpleHTTPRequestHandler) self.httpd.serve_forever()
def verifyAccount(self, verifyCode, link_id): try: verifyCode = self.account_verify_codes.index(verifyCode) except ValueError: log.info("Account not found ({}, {})".format(verifyCode, link_id)) verifyCode = None else: verifyCode = self.account_verify_codes[verifyCode] if (verifyCode): log.info("[ingcmd] Linked account '{}' with arma 3 '{}'".format( verifyCode.authorID, link_id)) self.set_user_data(str(verifyCode.authorID), "account_arma3", link_id) return True return False
def alter_database(self): try: ## Alter table (upgrade by adding the profileid column) self.c.execute( "SELECT COUNT(*) AS CNTREC FROM pragma_table_info('users') WHERE name='profileid'" ) if self.c.fetchone()[0] == 0: sql = """ ALTER TABLE users ADD COLUMN profileid INTEGER;""" self.c.execute(sql) self.con.commit() log.info("Altered DB Table: 'Added COLUMN profileid'") except Exception as e: log.print_exc() log.error(e)
async def on_ready(self): await self.bot.wait_until_ready() self.channel = self.bot.get_channel(self.cfg["post_channel"]) if ("CommandRcon" not in self.bot.cogs): log.info( "[module] 'CommandRcon' required, but not found in '{}'. Module unloaded" .format(type(self).__name__)) del self return try: self.CommandRcon = self.bot.cogs["CommandRcon"] self.CommandRcon.arma_rcon.add_Event("received_ServerMessage", self.rcon_on_msg_received) except Exception as e: log.print_exc() log.error(e)
async def query(self, ctx, *query): try: query = " ".join(query) log.info(query) result = self.c.execute(query) result = list(result) self.con.commit() msg = "" for row in result[:15]: msg += "{}\n".format(row) if (msg == ""): msg = "Query returned nothing" except Exception as e: msg = str(e) await ctx.send(msg)
async def rcon_on_disconnect(self): await asyncio.sleep(10) # cleanup old records try: while self.lastReconnect[0] < datetime.datetime.now() - datetime.timedelta(seconds=60): self.lastReconnect.popleft() except IndexError: pass # there are no records in the queue. if len(self.lastReconnect) > self.rcon_settings["max_reconnects_per_minute"]: log.warning("Stopped Reconnecting - Too many reconnects!") if(self.streamChat): await self.streamChat.send(":warning: Stopped Reconnecting - Too many reconnects!\n Reconnect with '!reconnect'") else: self.lastReconnect.append(datetime.datetime.now()) log.info("Reconnecting to BEC Rcon") self.setupRcon(self.arma_rcon.serverMessage) #restarts form scratch (due to weird behaviour on reconnect)
def loadCogs(bot): Modules.module_list = sorted(list(glob.glob("modules/*"))) for module in Modules.module_list: module = module.replace("\\", "/") try: cfg = Modules.loadCfg(module) if (cfg): CoreConfig.modules[module] = { Modules.general_settings_file: cfg } if (cfg["load_module"] == True): bot.load_extension( module.replace("/", ".") + ".module") else: log.info("[Modules] Skipped Cogs in '{}'".format(module)) except (discord.ClientException, ModuleNotFoundError) as e: log.print_exc() log.error(f'Failed to load extension: {module} ({e})') Modules.fix_wrappers()
def __init__(self, log_path, maxMisisons=20): self.maxMisisons = maxMisisons #max amount of Missions stored in the buffer #also contains datablock between the mission #(e.g 2 scenarios played --> 5 Missions blocks) self.path = os.path.dirname(os.path.realpath(__file__)) self.log_path = log_path self.currentLinePos = 0 self.current_log = None self.multiEventLock = None self.multiEventLockData = [] if (len(self.getLogs()) == 0): log.info("[WARNNING] No log files found in '{}'".format( self.log_path)) #all data rows are stored in here, limited to prevent memory leaks self.Missions = deque(maxlen=self.maxMisisons) self.Missions.append({"dict": {}, "data": []}) self.define_line_types()
async def on_ready(self): await self.bot.wait_until_ready() #await asyncio.sleep(60) #wait addional time for everything to be ready try: if ("CommandRcon" not in self.bot.cogs): log.info( "[module] 'CommandRcon' required, but not found in '{}'. Module unloaded" .format(type(self).__name__)) del self return self.CommandRcon = self.bot.cogs["CommandRcon"] self.post_channel = self.bot.get_channel( self.cfg["post_channel"]) #channel id self.CommandRcon.arma_rcon.add_Event("received_ServerMessage", self.rcon_on_msg_received) await self.init_bans_watchdog() except (KeyboardInterrupt, asyncio.CancelledError): log.info("[asyncio] exiting {}".format(on_ready)) except Exception as e: log.print_exc() log.error(e)
async def linkAccount(self, ctx): code = AccountVerificationCode(ctx.author.id, timelimit=60 * 5) asyncio.ensure_future(code.destruct(code)) self.account_verify_codes.append(code) log.info("[ingcmd] Generated code '{}' for user {} [{}]".format( code, ctx.author.name, ctx.author.id)) msg = "To verify your account, use the in game command '{}link {}'\nThe code is valid for 5min.".format( RconCommandEngine.command_prefix, code) if (str(ctx.author.id) in self.user_data and "account_arma3" in self.user_data[str(ctx.author.id)]): msg = "You account is already linked.\n" + msg await ctx.author.send( msg ) #handle the case that the user blocked the bot / does not have DM enabled await asyncio.sleep(60 * 5) if (not (str(ctx.author.id) in self.user_data and "account_arma3" in self.user_data[str(ctx.author.id)])): await ctx.author.send("Code expired")
def processLogLine(self, timestamp, line): #check if line contains a datapacket m = re.match('^(\[\["CTI_DataPacket","(.*?)"],.*])', line) if(m): type = m.group(2) try: datarow = self.parseLine(line) #convert string into array object if(type == "Header"): datarow["timestamp"] = timestamp return datarow elif("Data_" in type): index = int(re.match('.*_([0-9]*)', type).group(1)) if(len(self.databuilder)>0): index_db = int(re.match('.*_([0-9]*)', self.databuilder["CTI_DataPacket"]).group(1)) #check if previous 'Data_x' is present if(index_db+1 == index): self.databuilder = self.updateDicArray(self.databuilder, datarow) #If last element "Data_EOD" is present, if("EOD" in type): self.databuilder["CTI_DataPacket"] = "Data" datarow = self.databuilder.copy() self.databuilder = {} return datarow elif(type == "Data_1"): #add first element self.databuilder = self.updateDicArray(self.databuilder, datarow) elif(type == "EOF"): pass #raise Exception("Read mission EOF") #return datarow #return EOF (should usually never be called) elif(type == "GameOver"): datarow["timestamp"] = timestamp #finish time return datarow #return Gameover / End except Exception as e: log.error(e) log.info(line) log.print_exc()
async def on_ready(): log.info('Logged in as {} [{}]'.format(bot.user.name, bot.user.id)) log.info(bot.guilds) log.info('------------') roles = [] for guild in list(bot.guilds): roles += await guild.fetch_roles() bot.CoreConfig.load_role_permissions(roles)
def set_module_settings(file, data): #log.info(data) #for key,row in data.items(): key = data["name"][0] if ("value" not in data): new_val = "" else: new_val = data["value"][0] keys = key.split(".") if (len(keys) == 3): old_val = WebServer.bot.CoreConfig.modules[keys[0]][keys[1]][ keys[2]] if (isinstance(old_val, str)): new_val = str(new_val) elif (isinstance(old_val, bool)): if (new_val.lower() in [ 'true', '1', 't', 'y', 'yes', 'yeah', 'yup', 'certainly', 'uh-huh' ]): new_val = True else: new_val = False elif (isinstance(old_val, int)): if (new_val == ""): new_val = 0 else: new_val = int(new_val) else: raise Exception("Unkown datatype '{}'".format(type(value))) WebServer.bot.CoreConfig.modules[keys[0]][keys[1]][ keys[2]] = new_val log.info("{}, to {}".format(keys, new_val)) WebServer.bot.CoreConfig.modules[keys[0]][keys[1]].json_save() else: raise Exception("Invalid data structure for '{}'".format(data))
def check_log_events(self, line, events): if (self.multiEventLock): try: m = re.match(self.multiEventLock[2], line) if m: self.multiEventLockData.append(line) result = (self.multiEventLock[0], self.multiEventLockData) self.multiEventLock = None tmpB = self.multiEventLockData.copy() self.multiEventLockData = [] return result self.multiEventLockData.append(line) if (len(self.multiEventLockData) > 5): #max multi line lenght log.info( "Warning Exceeded 'multiEventLock' length! For '{}'". format( (self.multiEventLock[0], self.multiEventLockData))) self.multiEventLock = None self.multiEventLockData = [] except Exception as e: log.print_exc() raise Exception( "Error processing MultiEventLock: '{}' '{}'".format( self.multiEventLock, e)) else: try: for event in events: m = re.match(event[1], line) if m: if (len(event) > 2): self.multiEventLock = event self.multiEventLockData.append(line) else: return event[0], m except Exception as e: raise Exception("Invalid Regex: '{}' '{}'".format(event, e)) return None, None