async def on_message(self, message): """ Handle message events :param message: received :return: None """ react_to_dms = isinstance(message.channel, discord.abc.PrivateChannel) and self.allow_pming if message.author.bot: return if 'help' in message.content.lower() and react_to_dms: await message.channel.send("Paste your pastebin here for a quick overview or use '!pob <pastebin>' for a " "detailed response.") return if (react_to_dms or message.channel.name in self.active_channels) \ and not util.starts_with("!pob", message.content[:4]) \ and "pastebin.com/" in message.content: # check if valid xml # send message log.debug(f"A| {message.channel}: {message.content}") try: embed = self._parse_pob(message.author, message.content, minify=True) if embed: await message.channel.send(embed=embed) except HTTPError as err: log.error(f"Pastebin: Invalid pastebin-url msg={err}") except pastebin.CaptchaError as err: log.error(f"Pastebin: Marked as spam msg={err}") await message.channel.send(err.message)
def get_config(self, path_to_pob_conf): loaded_conf = None file_path = config.ROOT_DIR + path_to_pob_conf try: loaded_conf = json.load(open(file_path)) except FileNotFoundError as err: log.error( f'{path_to_pob_conf} is missing, trying to obtain a new copy... err was "{err}"' ) if loaded_conf: week_ago_date = datetime.now() - timedelta(days=7) # json_date = datetime.fromisoformat(loaded_conf['utc-date']) todo: enable when pypy 3.7 exists json_date = datetime.strptime(loaded_conf['utc-date'], "%Y-%m-%dT%H:%M:%S.%f") # if json date is older than a week, update if json_date < week_ago_date: self.fetch_config(file_path) log.info( f"finished creating new {path_to_pob_conf}.json in resources..." ) loaded_conf = json.load(open(file_path)) if not loaded_conf: self.fetch_config(path_to_pob_conf) log.info( f"finished creating new {path_to_pob_conf}.json in resources..." ) loaded_conf = json.load(open(file_path)) return loaded_conf
def fetch_config(path_to_pob_conf): """ Read the current PoB master branch configoptions and create a json file for it. """ url = f"{PobConfig.COMMUNITY_POB_RAW_GITHUB_URL}src/Modules/ConfigOptions.lua" url = request.urlopen(url) content = url.read().decode('utf-8') conditions = [line.strip() for line in content.split('{ var') if "condition" in line.lower() or "ifflag" in line.lower()] keywords = ['var', 'label', 'ifOption', 'ifSkill', 'ifSkillList'] regex = r'(\w+)\s*=\s*((?:"[^"]+")|{(?:\s*"[^"]+",?\s*)+})' attributes = {} for condition in conditions: attribute = {} condition = "var " + re.sub(r'{ label(.|\s)+$', '', condition) matches = re.findall(regex, condition) for m in matches: key = m[0].strip() val = m[1].strip() if val.startswith('"'): val = val.replace('"', '') elif val.startswith('{'): val = list( map(lambda v: v.replace('"', '').replace('{', '').replace('}', '').strip(), val.split(','))) if key not in attribute and key in keywords: attribute[key] = val if any(key in keywords for key in attribute): attributes[attribute['var']] = attribute pob_config_content = {'utc-date': datetime.utcnow().isoformat(), 'conf': attributes} try: with open(path_to_pob_conf, 'r') as file: file_content = json.load(file) if 'conf' in file_content: # we need to do this to keep manually entered values in our file such as category for confkey in file_content['conf']: print(f">> {file_content['conf'][confkey]}") if confkey in attributes: file_content['conf'][confkey].update(attributes[confkey]) else: log.error(f"Skipped config key: Please inform the bot author that the key '{confkey}' " f"could not be parsed.") new_keys = [key for key in attributes if not any(k == key for k in file_content['conf'])] print(new_keys) for key in new_keys: file_content['conf'][key] = attributes[key] pob_config_content = {'utc-date': datetime.utcnow().isoformat(), 'conf': file_content['conf']} except FileNotFoundError: pass with open(path_to_pob_conf, 'w') as file: json.dump(pob_config_content, file, indent=4)
def decode_base64_and_inflate(b64string): try: decoded_data = base64.b64decode(b64string) return zlib.decompress(decoded_data) except zlib.error as err: log.error(f"ZLib Error in paste: err={err}. Data={b64string}") except ValueError as err: log.error(f"Value Error in paste: err={err}")
def __init__(self, path_to_spectres=POB_SPECTRES): file_path = config.ROOT_DIR + path_to_spectres try: self.spectres = json.load(open(file_path)) except FileNotFoundError as err: log.error(f'{path_to_spectres} is missing, trying to obtain a new copy... err was "{err}"') self.fetch_spectres(file_path) log.info(f"finished creating new {path_to_spectres} in resources...") self.spectres = json.load(open(file_path))
def _generate_embed(web_poe_token, xml, author, paste_key, minify=False): if xml: build = pob_xml_parser.parse_build(xml) try: embed = pob_output.generate_response( author, build, minified=minify, pastebin_key=paste_key, non_dps_skills=poe_consts, web_poe_token=web_poe_token) log.debug(f"embed={embed}; thumbnail={embed.thumbnail}") return embed except Exception as e: ex_msg = ''.join( traceback.format_exception(etype=type(e), value=e, tb=e.__traceback__)) log.error( f"Could not parse pastebin={paste_key} - Exception={ex_msg}" )
def _parse_pob(author, content, minify=False): """ Trigger the parsing of the pastebin link, pass it to the output creating object and send a message back :param minify: show minified version of the embed :param content: of the message :param author: user sending the message :return: Embed """ paste_keys = pastebin.fetch_paste_key(content) if paste_keys: paste_key = random.choice(paste_keys) log.info(f"Parsing pastebin with key={paste_key} from author={author}") raw_data = pastebin.get_as_xml(paste_key) if not raw_data: log.error(f"Unable to obtain raw data for pastebin with key {paste_key}") return xml = pastebin.decode_to_xml(raw_data) if not xml: log.error(f"Unable to obtain xml data for pastebin with key {paste_key}") return web_poe_token = util.fetch_xyz_pob_token(raw_data) build = pob_xml_parser.parse_build(xml) try: embed = pob_output.generate_response(author, build, minified=minify, pastebin_key=paste_key, non_dps_skills=poe_consts, web_poe_token=web_poe_token) log.debug(f"embed={embed}; thumbnail={embed.thumbnail}") return embed except Exception as e: ex_msg = ''.join(traceback.format_exception(etype=type(e), value=e, tb=e.__traceback__)) log.error(f"Could not parse pastebin={paste_key} - Exception={ex_msg}")
def _fetch_xml(author, content): """ Trigger the parsing of the pastebin link, pass it to the output creating object and send a message back :param minify: show minified version of the embed :param content: of the message :param author: user sending the message :return: Embed """ paste_key = PoBCog._detect_paste_key(content, author) if paste_key: raw_data = pastebin.get_as_xml(paste_key) if not raw_data: log.error( f"Unable to obtain raw data for pastebin with key {paste_key}" ) return xml = pastebin.decode_to_xml(raw_data) if not xml: log.error( f"Unable to obtain xml data for pastebin with key {paste_key}" ) return web_poe_token = util.fetch_xyz_pob_token(raw_data) return xml, web_poe_token, paste_key else: log.error(f"No Paste key found") return
def urllib_error_retry(attempt_number, ms_since_first_attempt): delay = 1 * (2**(attempt_number - 1)) log.error( f"An error occurred during get_url_data(). Sleeping for {delay:.0f}s before retrying..." ) return delay * 1000