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 _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 test_bot_parse_routine(self): """ Tests whether all links inside of the file can be successfully parsed """ links = get_links() xml_keys = file_loader.get_pastebin_keys() for link in links: if "https://pastebin.com/" in link: key = link.split("/")[-1] if key not in xml_keys: log.warning(f"Downloading xml from pastebin for key={key}") PastebinHelper.fetch_pastebin(key) xml_file_paths = file_loader.get_pastebin_file_dir_files() for file_path in xml_file_paths: test_path = get_test_path( os.path.join(file_loader.pastebin_xmls_file, file_path)) with open(test_path, "r") as f: demo_author = None log.info(f"Testing whether we can parse '{test_path}'") xml_tree = ET.fromstring(f.read()) build_embed = PoBCog._generate_embed( None, xml_tree, demo_author, f"https://pastebin.com/{file_path.split('.xml')[0]}") self.assertTrue(isinstance(build_embed, Embed))
def _detect_paste_key(content: str, author): paste_key = None 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}") return paste_key
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))
async def pob(self, ctx, *, key): if not self.allow_pming and ctx.message.channel.is_private: return embed = self._parse_pob(ctx.message.author, ctx.message.content) try: if embed: await ctx.message.channel.send(embed=embed) except discord.Forbidden: log.info("Tried pasting in channel without access.")
def append_stat(self, key, val, stat_owner): # remove "Stat" from the string stat_owner = StatOwner.from_string(stat_owner) if not stat_owner in self.stats: self.stats[stat_owner] = {} try: self.stats[stat_owner][key] = float(val) except ValueError: log.info(f"Unable to convert '{val}' to float.")
async def pob(self, ctx, *, key): if not self.allow_pming and ctx.message.channel.is_private: return xml, web_poe_token, paste_key = self._fetch_xml( ctx.message.author, ctx.message.content) if xml and web_poe_token: embed = self._generate_embed(web_poe_token, xml, ctx.message.author, paste_key) try: if embed: await ctx.message.channel.send(embed=embed) except discord.Forbidden: log.info("Tried pasting in channel without access.")
def load_xml_by_pastebin_key(pastebin_url) -> ET: key = pastebin_url.split("/")[-1] xml_keys = get_pastebin_keys() if key not in xml_keys: log.warning(f"Downloading xml from pastebin for key={key}") PastebinHelper.fetch_pastebin(key) matches = [file for file in get_pastebin_file_dir_files() if key in file] build_xml_file = matches[0] if len(matches) > 0 else None path_to_build_xml = get_pastebin_file(build_xml_file) with open(path_to_build_xml, "r") as f: demo_author = None log.info(f"Testing whether we can parse '{build_xml_file}'") xml_tree = ET.fromstring(f.read()) return xml_tree
def parse_build(xml_root) -> Build: """ Completely parse the given pob xml into a build. :param xml_root: root node of pob xml :return: completely parsed build """ xml_build = xml_root.find('Build') xml_items = xml_root.find('Items') xml_skills = xml_root.find('Skills') xml_tree = xml_root.find('Tree') selected_tree = _get_tree_link(xml_tree) # parse items item_slots = _parse_item_slots(xml_items) skills = _parse_skills(xml_skills) active_skill = get_attrib_if_exists(xml_build, 'mainSocketGroup') build = Build(xml_build.attrib['level'], xml_build.attrib['targetVersion'], get_attrib_if_exists(xml_build, 'bandit'), xml_build.attrib['className'], xml_build.attrib['ascendClassName'], selected_tree, skills, active_skill, item_slots) for player_stat in xml_build: if 'stat' in player_stat.attrib and 'value' in player_stat.attrib: build.append_stat(player_stat.attrib['stat'], player_stat.attrib['value'], player_stat.tag) else: log.info( f"Encountered unsupported player stat: k={player_stat.tag}, v={player_stat.attrib}" ) # parse config config = xml_root.find('Config') if not config == None: for input in xml_root.find('Config'): if input.tag == "Input": extracted = [val for (key, val) in input.attrib.items()] if len(extracted) < 1: continue build.append_conf(extracted[0], extracted[1]) # keystones tree = poe_tree_codec.codec.decode_url(selected_tree) build.keystones = tree.get_keystones(poe_tree_codec.codec.keystones) return build
async def on_ready(): bot.add_cog(PoBCog(bot, config.active_channels, config.allow_pming)) log.info(f'Logged in: uname={bot.user.name}, id={bot.user.id}') if config.presence_message: await bot.change_presence(activity=discord.Activity(name=config.presence_message))
from instance import config from poediscordbot.discord_bot import bot from poediscordbot.util.logging import log if __name__ == '__main__': token = config.token # create config.py file and enter a new string! if token: # initialize_logging() log.info("Starting pob discord bot...") bot.run(token) else: log.warning( "Missing token from config file. Please generate a bot and the token as described: " "https://www.writebots.com/discord-bot-token/")