async def rp(ctx: Context, dice: str, history: Dict[Union[str, Guild], np.ndarray]): """ Roll a dice in NdN format hidden, no info is shown """ LOGGER.debug("Rolled and passed") result = await _r(ctx, dice, history) if not result: return await ctx.send(f"{ctx.message.author.mention} rolled hidden and passed on!")
async def ro(ctx: Context, dice: str, history: Dict[Union[str, Guild], np.ndarray]): """ Roll a dice in NdN format openly """ LOGGER.debug("Rolling open") result = await _r(ctx, dice, history) if not result: return await ctx.send(result)
def render_GET(self, request): LOGGER.info('Rendering TimelineView %s' % request.path) request.setHeader('content-type', 'text/html') processes = [] # This array will hold all of the data for the timeline view. data = [['Timestamp']] # Add the list of processes to the timeline table. for row in self.db.get_process_cmdlines(name=self.process_name_filter): processes.append(row[0]) data[0].append(row[1].strip()) LOGGER.debug('got process data: %s' % data) # Now add the top-level PSS values for the processes to the table. for row in self.db.get_process_stats(name=self.process_name_filter): timestamp = row[0] if timestamp != data[-1][0]: # Moved onto a new snapshot data.append([0] * (len(processes) + 1)) data[-1][0] = timestamp # Add process for this snapshot pos = 1 + processes.index(row[2]) data[-1][pos] = int(row[4]) flattenString(None, TimelineElement('static/timeline.html', data)).addCallback(self.renderOutput) request.write(self.output) return ""
async def rh(ctx: Context, dice: str, history: Dict[Union[str, Guild], np.ndarray]): """ Roll a dice in NdN format hidden (PM) """ LOGGER.debug("Rolling hidden") result = await _r(ctx, dice, history) if not result: return await ctx.send(f"{ctx.message.author.mention} rolled hidden!") await ctx.message.author.send(result)
def post(self) -> HTMLResponse: """Make post request to page.""" LOGGER.debug(msg=f"POSTing to url: {self.url}") response: HTMLResponse = \ self.session.post(url=self.url, headers=self.session.headers, data=self.payload) return response
def __init__(self, bot: Bot, guild: Guild, choices: List[Tuple[int, str]]): self.bot = bot self.guild = guild self.voters = set() self.open = not any(choices) self.choices = list(map(lambda choice: [*choice, 0], choices)) LOGGER.debug(self.choices)
async def shutdown(): if SHUTDOWN_VARIABLES['killed']: os._exit(1) SHUTDOWN_VARIABLES['killed'] = True LOGGER.warning('Exiting') for t in TASKS: t.cancel() if TASKS: await asyncio.wait(TASKS) LOGGER.debug(f'{TASKS=}') SHUTDOWN_VARIABLES['event'].set()
def parse_smaps_memory_region(pid, lines, has_header=True): """Parse a whole smaps region, which may look like: 7f5c8550e000-7f5c85554000 r--p 00000000 08:06 1309629 /fonts/Arial_Bold.ttf Size: 280 kB Rss: 152 kB Pss: 86 kB Shared_Clean: 132 kB Shared_Dirty: 12 kB Private_Clean: 20 kB Private_Dirty: 1 kB Referenced: 152 kB Anonymous: 2 kB AnonHugePages: 3 kB Shared_Hugetlb: 4 kB Private_Hugetlb: 5 kB Swap: 6 kB SwapPss: 7 kB KernelPageSize: 8 kB MMUPageSize: 9 kB Locked: 10 kB VmFlags: rd mr mw me sd""" has_header = is_memory_region_header(lines[0]) if has_header: region = parse_smaps_header(lines[0]) if region.name == '[vsyscall]': return None lines = lines[1:] else: region = MemoryRegion(free=False) region.pid = pid global _smaps_string_mappings for line in lines: LOGGER.debug('Parsing line: %s' % line) parts = re.split('[ :]+', line.strip()) if len(parts) < 2: LOGGER.debug('Skipping smaps line that is too short: %s' % line) elif 'Size' == parts[0]: # We calculate the size from the address ranges instead. pass elif 'VmFlags' == parts[0]: region.vm_flags = parts[1:] else: # All other lines should be an amount of some type of memory. try: region.__dict__[_smaps_string_mappings[parts[0]]] = int( parts[1]) * 1024 except KeyError: LOGGER.warn("Line not recognised: '%s'" % line) return region
async def main(): """ Main function """ env = Env() env.read_env() setup_logger(env.int("LOG_LEVEL", logging.INFO), env.path("LOG_FILE", None)) async with aiohttp.ClientSession() as session: bot = create_bot(env, session) LOGGER.debug("Starting bot") await bot.start(env.str("BOT_TOKEN"))
def parse(self, data, out): out['meminfo'] = MemoryStats() for line in data.split('\n'): parts = re.split('[ :]+', line.strip()) if len(parts) < 2: LOGGER.debug('Skipping meminfo line that is too short: %s' % line) elif len(parts) == 2: # This is a number. eg HugePages_Total, HugePages_Free, # HugePages_Rsvd, HugePages_Surp out['meminfo'].meminfo[parts[0]] = int(parts[1]) else: # These are sizes, with unit kB in the third column. # eg. AnonHugePages: 2355200 kB out['meminfo'].meminfo[parts[0]] = int(parts[1]) * 1024 return out
def parse_meminfo(stats, data): if not isinstance(stats, MemoryStats): raise TypeError('%s is not of type MemoryStats' % type(stats)) for line in data.split('\n'): parts = re.split('[ :]+', line.strip()) if len(parts) < 2: LOGGER.debug('Skipping meminfo line that is too short: %s' % line) elif len(parts) == 2: # This is a number. eg HugePages_Total, HugePages_Free, # HugePages_Rsvd, HugePages_Surp stats.meminfo[parts[0]] = int(parts[1]) else: # These are sizes, with unit kB in the third column. # eg. AnonHugePages: 2355200 kB stats.meminfo[parts[0]] = int(parts[1]) * 1024
async def _r(ctx: Context, dice: str, history: Dict[Union[str, Guild], np.ndarray]): """ String parsing and rolling for all dice rolling functions """ try: rolls, limit = map(int, dice.split("d")) except Exception: await ctx.send("Format has to be in NdN!") return None if rolls > 200 or limit > 200: await ctx.send("Pls use smaller numbers '_'") return None result = np.random.randint(low=1, high=limit + 1, size=rolls) result = np.sort(result)[::-1] LOGGER.debug(result) guild = ctx.guild if ctx.guild else "default" LOGGER.debug(guild) history[guild] = result result = ", ".join(map(str, result)) return result
def expect_address_connections(self, tmp_path, component_tests_config, protocol, edge_ip_version, assert_address_type): config = component_tests_config( self._extra_config(protocol, edge_ip_version)) config_path = write_config(tmp_path, config.full_config) LOGGER.debug(config) with CloudflaredCli(config, config_path, LOGGER): wait_tunnel_ready(tunnel_url=config.get_url(), require_min_connections=4) cfd_cli = CloudflaredCli(config, config_path, LOGGER) tunnel_id = config.get_tunnel_id() info = cfd_cli.get_tunnel_info(tunnel_id) connector_id = get_tunnel_connector_id() connector = next( (c for c in info["conns"] if c["id"] == connector_id), None) assert connector, f"Expected connection info from get tunnel info for the connected instance: {info}" conns = connector["conns"] assert conns == None or len( conns) == 4, f"There should be 4 connections registered: {conns}" for conn in conns: origin_ip = conn["origin_ip"] assert origin_ip, f"No available origin_ip for this connection: {conn}" assert_address_type(origin_ip)
async def vote(self, ctx: Context, *choices: str, time=20): """ Create a vote. (Alt command: v) """ # Check if voting is possible guild = ctx.guild if ctx.guild is None: await ctx.send("This feature is only supported in guilds") return vote = self.votes.get(guild) if vote: await ctx.send("There is already a vote running") return # Attach a number to each choice choice_enum: List[Tuple[int, str]] = list( enumerate( map(lambda choice: choice.strip(" ,\n").lower(), choices), 1)) vote = Vote(self.bot, guild, choice_enum) self.votes[guild] = vote LOGGER.debug("Started voting listener") self.bot.add_listener(vote.on_vote, name="on_message") choice_text = ("\n".join( map(lambda choice: f"{choice[0]}\t\u21D2 \t{choice[1]}", choice_enum)) if choice_enum else "Open voting") await ctx.send(f"Voting started for {time}s.\n{choice_text}") await asyncio.sleep(time) self.bot.remove_listener(vote.on_vote, name="on_message") LOGGER.debug("Removed voting listener") results = vote.format_results() hist = vote.termogram() if hist is not None: await ctx.send(f"Voting finished!\n{hist}") else: await ctx.send(f"Voting finished!\n{results}") del self.votes[guild]
def parse_smaps_header(header): info = MemoryRegion(free=False) # Example line is: # 011e6000-01239000 rw-p 00000000 00:00 0 [heap] # 8ec00000-8ec01000 rw-s 00000000 00:14 20 /dev/shm/NS2371 (deleted) # All numbers are hex except for the inode parts = header.split() LOGGER.debug('Parsing smaps header %s' % header) # Parse the address range info.start_addr, info.end_addr = [long(x, 16) for x in parts[0].split('-')] # Parse the permissions permissions = parts[1] info.permissions.readable = "r" in permissions info.permissions.writable = "w" in permissions info.permissions.executable = "x" in permissions info.permissions.private = "p" in permissions info.permissions.shared = "s" in permissions info.offset = long(parts[2], 16) # eg. 08:06 info.major_dev, info.minor_dev = [int(x, 16) for x in parts[3].split(':')] # The inode isn't a hex number info.inode = int(parts[4]) # eg. [heap] # or /dev/shm/NS2371 if len(parts) > 5: info.name = parts[5] info.deleted = header.endswith('(deleted)') return info
async def on_vote(self, message): """ React to a message sent in the guild """ if message.author == self.bot.user: LOGGER.debug("Own message") return if message.content.startswith(self.bot.command_prefix): LOGGER.debug("Detected command") return if message.author in self.voters: LOGGER.debug("Already voted %s", message.author) return self.voters.add(message.author) content = message.content.strip(" ,\n").lower() LOGGER.debug(content) if self.open: choice = list(filter(lambda choice: choice[1] == content, self.choices)) if choice: LOGGER.debug("Incrementing existing choice") choice[0][2] += 1 else: LOGGER.debug("Creating new choice") self.choices.append([len(self.choices) + 1, content, 1]) return try: index = int(content) choice = next(filter(lambda choice: choice[0] == index, self.choices)) LOGGER.debug("Got integer") choice[2] += 1 except: try: LOGGER.debug("Got name") choice = next(filter(lambda choice: choice[1] == content, self.choices)) choice[2] += 1 except: LOGGER.debug("Not found") return
def get(self) -> HTMLResponse: LOGGER.debug(msg=f"GETing url: {self.url}") response: HTMLResponse = self.session.get(url=self.url, headers=self.session.headers) return response
def read_tailed_files(stream): section_name = '' data = '' processes = ProcessList() current_process = None current_thread = None out = {} out['stats'] = SystemStats() out['meminfo'] = MemoryStats() for line in stream: LOGGER.debug('Got line: %s' % line) if line == '': continue # tail gives us lines like: # # ==> /proc/99/smaps <== # # between files elif line.startswith('==>'): _parse_section(section_name, current_process, current_thread, data, out) data = '' section_name = '' current_process = None current_thread = None if '/proc/loadavg' in line: section_name = 'loadavg' continue elif '/proc/uptime' in line: section_name = 'uptime' continue elif '/proc/vmstat' in line: section_name = 'vmstat' continue elif '/proc/net/stat' in line: # We don't care about this entry. Skip it. continue # Now parse the new line. match = re.match(r'==> /proc/([0-9]+)/([\w]+) <==', line) if match is None: if any(x in line for x in ['/proc/stat', '/proc/self/', '/proc/thread-self/']): # We just ignore these entries, interetesting as they are, # for now. pass elif '/proc/meminfo' in line: section_name = 'meminfo' else: match = re.match( r'==> /proc/([0-9]+)/task/([0-9]+)/stat <==', line) if match is None: # The line might not be parsed here. There are a few LOGGER.warn('Unrecognised line, skipping: %s' % line) else: section_name = 'stat' pid = int(match.group(1)) # process id tid = int(match.group(2)) # thread id current_thread = processes.get(pid).get_thread(tid) else: section_name = match.group(2) current_process = processes.get(pid=int(match.group(1))) elif current_process and section_name == 'smaps' and is_memory_region_header( line): # We get here on reaching a new memory region in a smaps file. _save_smaps_region(current_process.maps, out['meminfo'], current_process.pid, data) data = line elif section_name != '': data += "\n" + line else: LOGGER.debug('Skipping line: %s' % line) # We've hit the end, parse the section we were in. _parse_section(section_name, current_process, current_thread, data, out) return out['stats'], processes, out['meminfo']