async def raiddata(self, ctx, level=None): """Show all raid Pokemon, showing only the raid level if provided.""" data = [] title = None if level: title = f"Pokemon Data for Raid {level}" try: for pkmn in self.raid_info['raid_eggs'][level]["pokemon"]: pkmn = Pokemon.get_pokemon(self.bot, pkmn) data.append(f"#{pkmn.id} - {pkmn.name}") except KeyError: return await ctx.send('Invalid raid level specified.') except: return await ctx.send('Error processing command') else: title = f"Pokemon Data for All Raids" data = [] for pkmnlvl, vals in self.raid_info['raid_eggs'].items(): if not vals["pokemon"]: continue leveldata = [] try: for pkmn in vals["pokemon"]: pkmn = Pokemon.get_pokemon(self.bot, pkmn) leveldata.append(f"#{pkmn.id} - {pkmn.name}") except: return await ctx.send('Error processing command') leveldata = '\n'.join(leveldata) data.append(f"**Raid {pkmnlvl} Pokemon**\n{leveldata}\n") data_str = '\n'.join(data) await ctx.send(f"**{title}**\n{data_str}")
def _check_galarian(self, pokemon_name): if pokemon_name in Pokemon.get_galarians_list(): raid_pokemon = Pokemon.get_pokemon(self.bot, pokemon_name) if not raid_pokemon.is_raid: raid_pokemon = Pokemon.get_pokemon(self.bot, "galarian" + pokemon_name) else: raid_pokemon = Pokemon.get_pokemon(self.bot, pokemon_name) return raid_pokemon
async def _build_hideout_embed(self, ctx, hideout): location_matching_cog = self.bot.cogs.get('LocationMatching') stop = location_matching_cog.get_stop_by_id(ctx.guild.id, hideout.location_id) inv_embed = discord.Embed(title=f'**Pokestop**: {stop.name}', url=stop.maps_url, colour=discord.Colour.red()) desc = "" if hideout.leader: desc += f"\nRocket Leader {hideout.leader.capitalize()}\n" inv_embed.set_thumbnail( url= f"https://github.com/tehstone/Kyogre/blob/master/images/misc/{hideout.leader.lower()}.png?raw=true" ) else: inv_embed.set_thumbnail( url= "https://github.com/tehstone/Kyogre/blob/master/images/misc/rocket_logo.png?raw=true" ) desc += "\n Unknown Rocket Leader\n" names, img_url = '', '' pokemon_list = [ hideout.first_pokemon, hideout.second_pokemon, hideout.third_pokemon ] for pk_id in pokemon_list: if pk_id: pokemon = Pokemon.get_pokemon(self.bot, pk_id) if pokemon: names += f"{pokemon.name.capitalize()} " if pokemon_list[0]: pokemon = Pokemon.get_pokemon(self.bot, pokemon_list[0]) img_url = pokemon.img_url img_url = img_url.replace('007_', '007normal_') img_url = img_url.replace('025_', '025normal_') if len(names) > 0: names = "\n**Lineup**:\n" + names else: names = "\n**Unknown Lineup**" desc += names inv_embed.description = desc created_time = datetime.datetime.utcfromtimestamp( hideout.created) + datetime.timedelta(hours=self.bot.guild_dict[ ctx.guild.id]['configure_dict']['settings']['offset']) timestamp = created_time.strftime('%Y-%m-%d %H:%M:%S') trainer = ctx.guild.get_member(hideout.trainer) inv_embed.set_footer( text=f'Reported by {trainer.display_name} - {timestamp}', icon_url=img_url) return inv_embed
def get_raidtext(Kyogre, guild, guild_dict, raid_dict, gym, report_channel, raid_channel, report): if 'type' in raid_dict: type = raid_dict['type'] if 'pokemon' in raid_dict: pkmn = raid_dict['pokemon'] if 'egglevel' in raid_dict: level = raid_dict['egglevel'] if 'reporter' in raid_dict: member = raid_dict['reporter'] if 'exp' in raid_dict: raidexp = raid_dict['exp'] member = guild.get_member(member) pkmn = Pokemon.get_pokemon(Kyogre, pkmn) if report: raidtext = build_raid_report_message(Kyogre, gym, type, pkmn, level, raidexp, report_channel, guild_dict) else: if type == "raid": raidtext = "{pkmn} raid reported by {member} in {channel}! Coordinate here!\n\nFor help, react to this message with the question mark and I will DM you a list of commands you can use!".format( pkmn=pkmn.name(), member=member.display_name, channel=raid_channel.mention) elif type == "egg": raidtext = "Level {level} raid egg reported by {member} in {channel}! Coordinate here!\n\nFor help, react to this message with the question mark and I will DM you a list of commands you can use!".format( level=level, member=member.display_name, channel=raid_channel.mention) elif type == "exraid": raidtext = "EX raid reported by {member} in {channel}! Coordinate here!\n\nFor help, react to this message with the question mark and I will DM you a list of commands you can use!".format( member=member.display_name, channel=raid_channel.mention) return raidtext
def get_raidtext(Kyogre, guild, raid_dict, raid_channel, report): ctype, member, pokemon_str, level, raidtext = None, '', '', '', '' if 'ctype' in raid_dict: ctype = raid_dict['type'] if 'pokemon' in raid_dict: pokemon_str = raid_dict['pokemon'] pkmn = Pokemon.get_pokemon(Kyogre, pokemon_str) pokemon_str = pkmn.name if 'egglevel' in raid_dict: level = raid_dict['egglevel'] if 'reporter' in raid_dict: member = raid_dict['reporter'] member = guild.get_member(member) member = member.display_name if report: raidtext = build_raid_report_message(Kyogre, raid_channel, raid_dict) else: if ctype == "raid": raidtext = ( f"{pokemon_str} raid reported by {member} in {raid_channel.mention}! " f"Coordinate here!\n\nFor help, react to this message with the question mark " "and I will DM you a list of commands you can use!") elif ctype == "egg": raidtext = ( f"Level {level} raid egg reported by {member} in {raid_channel.mention}!" f" Coordinate here!\n\nFor help, react to this message with the question mark " f"and I will DM you a list of commands you can use!") elif ctype == "exraid": raidtext = ( f"EX raid reported by {member} in {raid_channel.mention}! " f"Coordinate here!\n\nFor help, react to this message with the question mark " f"and I will DM you a list of commands you can use!") return raidtext
async def regional(self, ctx, regional): """Changes server regional pokemon.""" regional = regional.lower() if regional == "reset" and checks.is_dev_or_owner(): msg = "Are you sure you want to clear all regionals?" question = await ctx.channel.send(msg) try: timeout = False res, reactuser = await utils.simple_ask(self.bot, question, ctx.message.channel, ctx.message.author.id) except TypeError: timeout = True await question.delete() if timeout or res.emoji == '❎': return elif res.emoji == '✅': pass else: return guild_dict_copy = copy.deepcopy(self.bot.guild_dict) for guildid in guild_dict_copy.keys(): self.bot.guild_dict[guildid]['configure_dict']['settings']['regional'] = None return elif regional == 'clear': regional = None self._set_regional(ctx.guild, regional) await ctx.message.channel.send("Regional raid boss cleared!") return regional = Pokemon.get_pokemon(self.bot, regional) if regional.is_raid: self._set_regional(ctx.guild, regional) await ctx.message.channel.send(f"Regional raid boss set to **{regional.name}**!") else: await ctx.message.channel.send("That Pokemon doesn't appear in raids!") return
async def remove_rd(self, ctx, *, raid_pokemon=None): """Removes all pokemon provided as comma-separated arguments from the raid data. Example: !raiddata remove Mr Mime, Jynx, Alolan Raichu """ results = [] # remove level if erroneously provided raid_pokemon = re.sub(r'^\d+\s+', '', raid_pokemon) raid_pokemon = re.split(r'\s*,\s*', raid_pokemon) for pokemon in raid_pokemon: pkmn = Pokemon.get_pokemon(self.bot, pokemon) if not pkmn: self.bot.help_logger.info( f"User: {ctx.author.name}, channel: {ctx.channel}, error: Invalid pokemon name: {pokemon}." ) return await ctx.send('Invalid Pokemon Name') hit_key = [] name = pkmn.name.lower() for k, v in self.raid_info['raid_eggs'].items(): if name in v['pokemon']: hit_key.append(k) self.raid_info['raid_eggs'][k]['pokemon'].remove(name) if hit_key: hits = '\n'.join(hit_key) result_text = f"#{pkmn.id} {pkmn.name} from {hits}" else: result_text = f"#{pkmn.id} {pkmn.name} not found in raid data" results.append(result_text) results_st = '\n'.join(results) await ctx.send(f"**Pokemon removed from raid data**\n{results_st}")
async def wanted_pokemon(self): listingmsg = await self.get_listmsg() ctx = await self.bot.get_context(listingmsg) return [ Pokemon.get_pokemon(ctx, want) for want in self._data['wanted_pokemon'] ]
async def _mark_helper(self, ctx, pokemon, attr): all_by_name = Pokemon.get_pkmn_dict_all_by_name() poke_instance = None try: pokemon = int(pokemon) poke_instance = PokemonTable[pokemon] except (ValueError, IndexError, Exception): try: poke_instance = PokemonTable[all_by_name[pokemon]["id"]] except KeyError: pass if poke_instance: if attr == "shiny": poke_instance.shiny = True elif attr == "released": poke_instance.released = True poke_instance.save() else: await ctx.channel.send(embed=discord.Embed( colour=discord.Colour.red(), description=f"Could not find Pokemon {pokemon}."), delete_after=12) return await ctx.message.add_reaction(self.bot.failed_react) await ctx.channel.send(embed=discord.Embed( colour=discord.Colour.green(), description=f"Successfully marked {pokemon} as {attr}."), delete_after=12) return await ctx.message.add_reaction(self.bot.success_react)
async def _save_rd(self, ctx): """Saves the current raid data state to the json file.""" for pkmn_lvl in self.raid_info['raid_eggs']: data = self.raid_info['raid_eggs'][pkmn_lvl]["pokemon"] pkmn_names = [ Pokemon.get_pokemon(self.bot, p).name.lower() for p in data ] self.raid_info['raid_eggs'][pkmn_lvl]["pokemon"] = pkmn_names with open(ctx.bot.raid_json_path, 'w') as fd: json.dump(self.raid_info, fd, indent=4) return await ctx.message.add_reaction('\u2705')
async def _rewards_remove(self, ctx, *, info): """Removes a reward to reward pool for a given quest using provided comma-separated values. Usage: !rewards remove <ID>, <reward_type>, <value> ID must correspond to a valid db entry. If reward_type is not encounters, stardust, or xp, it will be assumed to be an item.""" channel = ctx.channel try: reward_id, reward_type, value = re.split(r',', info) reward_id = int(reward_id) reward_type = reward_type.lower() except: return await channel.send( "Error parsing input. Please check the format and try again") try: quest = QuestTable[reward_id] except: return await channel.send( f"Unable to get quest with reward_id {reward_id}") pool = quest.reward_pool if reward_type.startswith("encounter"): encounters = [x.lower() for x in pool["encounters"]] pokemon = Pokemon.get_pokemon(self.bot, value) name = pokemon.name.lower() if pokemon: try: encounters.remove(name) except: return await channel.send(f"Unable to remove {value}") pool["encounters"] = encounters else: if not value.isnumeric(): return await channel.send("Value must be a numeric quantity") try: if reward_type == "stardust": pool["stardust"].remove(int(value)) elif reward_type == "xp": pool["xp"].remove(int(value)) else: pool["items"][reward_type].remove(int(value)) if len(pool["items"][reward_type]) == 0: del pool["items"][reward_type] except: return await channel.send(f"Unable to remove {value}") quest.reward_pool = pool quest.save() await channel.send("Successfully removed reward from pool")
def __init__(self): super().__init__(command_prefix=_prefix_callable, case_insensitive=True, activity=discord.Game(name="Pokemon Go")) self.logger = init_loggers() self.help_logger = init_logger("help", "logs/kyogre_help.log") self.user_logger = init_logger("user", "logs/kyogre_user.log") self.gcv_logger = init_logger("gcv", "logs/gcv_api.log") self.scan_fail_log = init_logger("scanfail", "logs/gcv_api.log") custom_error_handling(self, self.logger) self.guild_dict = {} self.vision_api_enabled = False self.api_usage_limit = 20 self._load_data() self.raid_json_path = self._load_config() self.active_ex = [] self.active_raids = [] self.active_wilds = [] self.active_pvp = [] self.active_lures = [] self.active_invasions = {} self.success_react = '✅' self.failed_react = '❌' self.thumbsup_react = '👍' self.empty_str = '\u200b' self.team_color_map = {'Mystic': discord.Colour.blue(), 'Valor': discord.Colour.red(), 'Instinct': discord.Colour.from_rgb(255, 255, 0)} self.saved_files = {} self.session = None self.port = 8000 for ext in default_exts: try: self.load_extension(f"kyogre.exts.{ext}") except Exception as e: print(f'**Error when loading extension {ext}:**\n{type(e).__name__}: {e}') else: if 'debug' in sys.argv[1:]: print(f'Loaded {ext} extension.') self.boss_list = Pokemon.get_raidlist(self) for b in self.boss_list: if b.lower().startswith('alolan'): self.boss_list.append(b.split()[1]) self._setup_folders()
async def save(self, guildid): try: with open('config.json', 'w') as fd: json.dump(self.bot.config, fd, indent=4) except Exception as e: self.bot.logger.error(f"Failed to save config. Error: {str(e)}") try: with tempfile.NamedTemporaryFile( 'wb', dir=os.path.dirname(os.path.join('data', 'serverdict')), delete=False) as tf: pickle.dump(self.bot.guild_dict, tf, 4) tempname = tf.name try: os.remove(os.path.join('data', 'serverdict_backup')) except OSError: pass try: os.rename(os.path.join('data', 'serverdict'), os.path.join('data', 'serverdict_backup')) except OSError as e: if e.errno != errno.ENOENT: raise os.rename(tempname, os.path.join('data', 'serverdict')) except Exception as e: self.bot.logger.error( f"Failed to save serverdict. Error: {str(e)}") location_matching_cog = self.bot.cogs.get('LocationMatching') if not location_matching_cog: await self._print(self.bot.owner, 'Pokestop and Gym data not saved!') return None stop_save = location_matching_cog.save_stops_to_json(guildid) gym_save = location_matching_cog.save_gyms_to_json(guildid) pkmn_save = Pokemon.save_pokemon_to_json() if stop_save is not None: await self._print( self.bot.owner, f'Failed to save pokestop data with error: {stop_save}!') if gym_save is not None: await self._print( self.bot.owner, f'Failed to save gym data with error: {gym_save}!')
def add_raid_pkmn(self, level, raid_pokemon): """Add raid pokemon to relevant level.""" added = [] failed = [] raid_pokemon = re.split(r'\s*,\s*', raid_pokemon) raid_list = self.raid_info['raid_eggs'][level]['pokemon'] for pokemon in raid_pokemon: pkmn = Pokemon.get_pokemon(self.bot, pokemon) if not pkmn: failed.append(pokemon) continue in_level = self.in_list(pkmn) name = pkmn.name.lower() if in_level: if in_level == level: continue self.raid_info['raid_eggs'][in_level]['pokemon'].remove(name) raid_list.append(name) added.append(f"#{pkmn.id} {pkmn.name}") return (added, failed)
async def _rewards_add(self, ctx, *, info): """Adds a reward to reward pool for a given quest using provided comma-separated values. Usage: !rewards add <ID>, <type>, <value> ID must correspond to a valid db entry. If type is not encounters, stardust, or xp, it will be assumed to be an item.""" channel = ctx.channel try: reward_id, reward_type, value = re.split(r',', info) reward_id = int(reward_id.strip()) reward_type = reward_type.lower().strip() value = value.strip() except: return await channel.send( "Error parsing input. Please check the format and try again") try: quest = QuestTable[reward_id] except: return await channel.send( f"Unable to get quest with id {reward_id}") pool = quest.reward_pool if reward_type.startswith("encounter"): pokemon = Pokemon.get_pokemon(self.bot, value) if pokemon: pool.setdefault("encounters", []).append(pokemon.name.lower()) else: if not value.isnumeric(): return await channel.send("Value must be a numeric quantity") if reward_type == "stardust": pool.setdefault("stardust", []).append(int(value)) elif reward_type == "xp": pool.setdefault("xp", []).append(int(value)) else: pool.setdefault("items", {}).setdefault(reward_type, []).append(int(value)) quest.reward_pool = pool quest.save() await channel.send("Successfully added reward to pool")
async def _invasion(self, ctx, *, info=None): """**Usage**: `!rocket <pokestop name> [,rocket leader, pokemon names]` Report a Team Rocket Leader invasion at a pokestop!. Rocket Leader and their Pokemon Lineup are optional and can be updated later.""" message = ctx.message channel = message.channel author = message.author guild = message.guild info = re.split(r',+\s+', info) stopname = info[0] report_time = message.created_at + \ datetime.timedelta(hours=self.bot.guild_dict[guild.id]['configure_dict']['settings']['offset']) epoch = datetime.datetime(1970, 1, 1) report_time_int = (report_time - epoch).total_seconds() utilities_cog = self.bot.cogs.get('Utilities') subscriptions_cog = self.bot.cogs.get('Subscriptions') location_matching_cog = self.bot.cogs.get('LocationMatching') utils_cog = self.bot.cogs.get('Utilities') regions = utils_cog.get_channel_regions(channel, 'hideout') stops = location_matching_cog.get_stops(guild.id, regions) stop = await location_matching_cog.match_prompt( channel, author.id, stopname, stops) if not stop: self.bot.help_logger.info( f"User: {ctx.author.name}, channel: {ctx.channel}, error: No Pokestop found {stopname}." ) return await channel.send(embed=discord.Embed( colour=discord.Colour.red(), description=f"No pokestop found with name '**{stopname}**' " f"either. Try reporting again using the exact pokestop name!"), delete_after=15) existing = await self._check_existing(stop) if existing: if existing.leader and existing.second_pokemon and existing.third_pokemon: return await channel.send(embed=discord.Embed( colour=discord.Colour.red(), description= f"Hideout for **{stop.name}** has been completely reported already." ), delete_after=15) if not existing: existing = HideoutInstance(None, report_time_int, stop.id, stop.name, None, None, None, None, stop.latitude, stop.longitude, message.id, message.author.id) regions = [stop.region] leader = None pokemon_names = [None] pokemon_ids = [None] # Check through all the info sent in, pull out any leader names and pokemon names we find if len(info) > 1: for i in info[1:]: # if we find a leader name then we can also set the first pokemon # this assumption may change in the future if i.lower() in self.leader_strings: leader = i p_id = self.leader_map[leader.lower()] pkmn = Pokemon.get_pokemon(self.bot, p_id) pokemon_names[0] = pkmn.name pokemon_ids[0] = pkmn.id else: pkmn = Pokemon.get_pokemon(self.bot, i) if pkmn is not None: # if the name found is the one already known to be in the first slot then ignore if pkmn.id not in self.leader_map.values(): pokemon_names.append(pkmn.name) pokemon_ids.append(pkmn.id) # pad the id and names lists if len(pokemon_names) < 3: pokemon_names = (pokemon_names + 3 * [None])[:3] if len(pokemon_ids) < 3: pokemon_ids = (pokemon_ids + 3 * [None])[:3] # if there was a pre-existing report, make sure not to override leader set before if existing.leader: if leader and leader != existing.leader: await channel.send( f"**{existing.leader.capitalize()}** has already been reported for **{stop.name}**.", delete_after=30) leader = existing.leader pkmn = Pokemon.get_pokemon(self.bot, self.leader_map[leader.lower()]) pokemon_names[0] = pkmn.name pokemon_ids[0] = pkmn.id # don't override 2nd slot if already set if existing.second_pokemon: if pokemon_ids[1]: if pokemon_ids[1] != existing.second_pokemon: if pokemon_ids[2]: await channel.send( f"The second lineup slot has already been reported for **{stop.name}**.", delete_after=30) else: # but if the third slot was previously not set, we can fill that in now if not existing.third_pokemon: existing.third_pokemon = pokemon_ids[1] pkmn = Pokemon.get_pokemon(self.bot, existing.second_pokemon) pokemon_names[1] = pkmn.name pokemon_ids[1] = pkmn.id # don't override 3rd slot if already set. this may be unreachable if existing.third_pokemon: if pokemon_ids[2]: if pokemon_ids[2] != existing.second_pokemon: await channel.send( f"The third lineup slot has already been reported for **{stop.name}**", delete_after=30) pkmn = Pokemon.get_pokemon(self.bot, existing.third_pokemon) pokemon_names[2] = pkmn.name pokemon_ids[2] = pkmn.id if leader: leader = leader.lower() if existing.id: report = TrainerReportRelation.get_by_id(existing.id) HideoutTable.update(rocket_leader=leader, first_pokemon=pokemon_ids[0], second_pokemon=pokemon_ids[1], third_pokemon=pokemon_ids[2])\ .where(HideoutTable.trainer_report == report.id).execute() updated = True else: report = TrainerReportRelation.create(guild=ctx.guild.id, created=report_time_int, trainer=author.id, location=stop.id, cancelled=False) HideoutTable.create(trainer_report=report, rocket_leader=leader, first_pokemon=pokemon_ids[0], second_pokemon=pokemon_ids[1], third_pokemon=pokemon_ids[2]) updated = False hideout = self.get_single_hideout(report.id) inv_embed = await self._build_hideout_embed(ctx, hideout) listmgmt_cog = self.bot.cogs.get('ListManagement') if updated: hideout = self.get_single_hideout(report.id) message = await channel.fetch_message(hideout.message) try: await message.delete() except: pass invasionreportmsg = await channel.send( f'**Team Rocket Hideout** report at *{hideout.location_name}* updated!', embed=inv_embed) await utilities_cog.reaction_delay(invasionreportmsg, ['\u270f', '🚫']) TrainerReportRelation.update(message=invasionreportmsg.id) \ .where(TrainerReportRelation.id == report.id).execute() await listmgmt_cog.update_listing_channels(guild, 'hideout', edit=True, regions=regions) else: invasionreportmsg = await channel.send( f'**Team Rocket Hideout** reported at *{stop.name}*', embed=inv_embed) await utilities_cog.reaction_delay(invasionreportmsg, ['\u270f', '🚫']) details = {'regions': regions, 'type': 'hideout', 'location': stop} TrainerReportRelation.update(message=invasionreportmsg.id).where( TrainerReportRelation.id == report.id).execute() send_channel = subscriptions_cog.get_region_list_channel( guild, stop.region, 'invasion') if send_channel is None: send_channel = message.channel await subscriptions_cog.send_notifications_async( 'hideout', details, send_channel, [message.author.id]) await asyncio.sleep(1) await listmgmt_cog.update_listing_channels(guild, 'hideout', edit=False, regions=regions) clean_list = self.bot.guild_dict[ ctx.guild.id]['configure_dict'].setdefault('channel_auto_clean', []) if ctx.channel.id in clean_list: await ctx.message.delete()
async def _wild(self, ctx, pokemon, *, location): """**Usage**: `!wild <pokemon> <location>` Location can be a pokestop name, gym name, Google or Apple Maps link.""" content = f"{pokemon} {location}" message = ctx.message guild = message.guild channel = message.channel author = message.author utilities_cog = self.bot.cogs.get('Utilities') location_matching_cog = self.bot.cogs.get('LocationMatching') timestamp = (message.created_at + datetime.timedelta(hours=self.bot.guild_dict[guild.id]['configure_dict']['settings']['offset']))\ .strftime('%I:%M %p (%H:%M)') if len(content.split()) <= 1: self.bot.help_logger.info(f"User: {ctx.author.name}, channel: {ctx.channel}, error: Insufficient wild report info provided.") return await channel.send( embed=discord.Embed(colour=discord.Colour.red(), description='Give more details when reporting! ' 'Usage: **!wild <pokemon name> <location>**')) utils_cog = self.bot.cogs.get('Utilities') channel_regions = utils_cog.get_channel_regions(channel, 'wild') rgx = r'\s*((100(\s*%)?|perfect)(\s*ivs?\b)?)\s*' content, count = re.subn(rgx, '', content.strip(), flags=re.I) is_perfect = count > 0 entered_wild, wild_details = content.split(' ', 1) if Pokemon.has_forms(entered_wild): prompt = 'Which form of this Pokemon are you reporting?' choices_list = [f.capitalize() for f in Pokemon.get_forms_for_pokemon(entered_wild)] match = await utils.ask_list(self.bot, prompt, channel, choices_list, user_list=author.id) content = ' '.join([match, content]) pkmn = Pokemon.get_pokemon(self.bot, entered_wild if entered_wild.isdigit() else content) if not pkmn: self.bot.help_logger.info(f"User: {ctx.author.name}, channel: {ctx.channel}, error: Pokemon not found with name: {content}.") return await channel.send( embed=discord.Embed(colour=discord.Colour.red(), description="Unable to find that pokemon. Please check the name and try again!")) wild_number = pkmn.id wild_img_url = pkmn.img_url expiremsg = '**This {pokemon} has despawned!**'.format(pokemon=pkmn.full_name) if len(pkmn.name.split(' ')) > 1: entered_wild, entered_wild, wild_details = content.split(' ', 2) else: wild_details = re.sub(pkmn.name.lower(), '', content, flags=re.I) wild_gmaps_link = None locations = location_matching_cog.get_all(guild.id, channel_regions) location_id = None if locations and not ('http' in wild_details or '/maps' in wild_details): location = await location_matching_cog.match_prompt(channel, author.id, location, locations) if location: wild_gmaps_link = location.maps_url wild_details = location.name location_id = location.id if wild_gmaps_link is None: if 'http' in wild_details or '/maps' in wild_details: wild_gmaps_link = utilities_cog.create_gmaps_query(wild_details, channel, type="wild") wild_details = 'Custom Map Pin' else: self.bot.help_logger.info(f"User: {ctx.author.name}, channel: {ctx.channel}, error: Invalid location provided.") return await channel.send( embed=discord.Embed( colour=discord.Colour.red(), description="Please use the name of an existing pokestop or gym, " "or include a valid Google Maps link.")) wild_embed = discord.Embed(title='Click here for my directions to the wild {perfect}{pokemon}!' .format(pokemon=pkmn.full_name, perfect="💯 " if is_perfect else ""), description="Ask {author} if my directions aren't perfect!" .format(author=author.name), url=wild_gmaps_link, colour=guild.me.colour) wild_embed.add_field(name='**Details:**', value='{emoji}{pokemon} ({pokemonnumber}) {type}' .format(emoji='💯' if is_perfect else '', pokemon=pkmn.full_name, pokemonnumber=str(wild_number), type=''.join(utils.types_to_str(guild, pkmn.types, self.bot.config))), inline=False) wild_embed.set_thumbnail(url=wild_img_url) wild_embed.add_field(name='**Reactions:**', value="{emoji}: I'm on my way!".format(emoji="🏎")) wild_embed.add_field(name='\u200b', value="{emoji}: The Pokemon despawned!".format(emoji="💨")) wild_embed.set_footer(text='Reported by {author} - {timestamp}' .format(author=author.display_name, timestamp=timestamp), icon_url=author.avatar_url_as(format=None, static_format='jpg', size=32)) wildreportmsg = await channel.send(content='Wild {perfect}{pokemon} reported by {member} at: {location_details}' .format(perfect="💯 " if is_perfect else "", pokemon=pkmn.full_name, member=author.display_name, location_details=wild_details), embed=wild_embed) await utilities_cog.reaction_delay(wildreportmsg, ['🏎', '💨']) wild_dict = copy.deepcopy(self.bot.guild_dict[guild.id].get('wildreport_dict', {})) wild_dict[wildreportmsg.id] = { 'exp': time.time() + 3600, 'expedit': {"content": wildreportmsg.content, "embedcontent": expiremsg}, 'reportmessage': message.id, 'reportchannel': channel.id, 'reportauthor': author.id, 'location': wild_details, 'location_id': location_id, 'url': wild_gmaps_link, 'pokemon': pkmn.full_name, 'pokemon_id': pkmn.id, 'perfect': is_perfect, 'omw': [] } self.bot.guild_dict[guild.id]['wildreport_dict'] = wild_dict wild_details = {'pokemon': pkmn, 'perfect': is_perfect, 'location': wild_details, 'regions': channel_regions} self.bot.event_loop.create_task(self.wild_expiry_check(wildreportmsg)) listmgmt_cog = self.bot.cogs.get('ListManagement') await listmgmt_cog.update_listing_channels(message.guild, 'wild', edit=False, regions=channel_regions) subscriptions_cog = self.bot.cogs.get('Subscriptions') send_channel = subscriptions_cog.get_region_list_channel(guild, channel_regions[0], 'wild') if send_channel is None: send_channel = message.channel points = await subscriptions_cog.send_notifications_async('wild', wild_details, send_channel, [message.author.id]) wild_reports = self.bot.guild_dict[guild.id] \ .setdefault('trainers', {}) \ .setdefault(channel_regions[0], {}) \ .setdefault(author.id, {}) \ .setdefault('wild_reports', 0) + points self.bot.guild_dict[guild.id]['trainers'][channel_regions[0]][author.id]['wild_reports'] = wild_reports await self._add_db_sighting_report(ctx, wildreportmsg)
async def research_multiple(self, ctx, *, details=None): """**Usage**: `!research_multiple / resl / resm task, reward, stop, [stop2, etc...]` Provide task name and reward and at least 1 pokestop.""" message = ctx.message channel = message.channel author = message.author guild = message.guild timestamp = (message.created_at + datetime.timedelta( hours=self.bot.guild_dict[message.channel.guild.id] ['configure_dict']['settings']['offset'])) to_midnight = 24 * 60 * 60 - (timestamp - timestamp.replace( hour=0, minute=0, second=0, microsecond=0)).seconds utilities_cog = self.bot.cogs.get('Utilities') location_matching_cog = self.bot.cogs.get('LocationMatching') questrewardmanagement_cog = self.bot.cogs.get('QuestRewardManagement') regions = utilities_cog.get_channel_regions(channel, 'research') stops = location_matching_cog.get_stops(guild.id, regions) research_split = details.split(",") if len(research_split) < 3: error = "entered an incorrect amount of arguments.\n\n" \ "**Usage**: `!research_multiple / resl / resm task, reward, stop, [stop2, etc...]`" return await channel.send(embed=discord.Embed( colour=discord.Colour.red(), description=error)) task, reward, report_stops = research_split[0], research_split[ 1], research_split[2:] quest = await questrewardmanagement_cog.get_quest(ctx, task.strip()) if not quest: self.bot.help_logger.info( f"User: {ctx.author.name}, channel: {ctx.channel}, error: No quest found with name: {task}." ) return await channel.send(embed=discord.Embed( colour=discord.Colour.red(), description=f"I couldn't find a quest named '{task}'")) reward = await questrewardmanagement_cog.check_reward( ctx, quest, reward) if not reward: return await channel.send(embed=discord.Embed( colour=discord.Colour.red(), description=f"I couldn't find a reward for '{task}'")) failed_stops = {"not_found": [], "already_reported": []} success_count = 0 confirmation = None if stops: for s in report_stops: stop = await location_matching_cog.match_prompt( channel, author.id, s.strip(), stops) if not stop: self.bot.help_logger.info( f"User: {ctx.author.name}, channel: {ctx.channel}, error: No Pokestop found with name: {s.strip()}." ) failed_stops["not_found"].append(s) continue if self.get_existing_research(guild, stop): failed_stops["already_reported"].append(s) continue location = stop.name loc_url = stop.maps_url regions = [stop.region] research_embed = discord.Embed( colour=message.guild.me.colour) \ .set_thumbnail( url='https://raw.githubusercontent.com/klords/Kyogre/master/images/misc/field-research.png?cache=0') research_embed.set_footer( text='Reported by {author} - {timestamp}'.format( author=author.display_name, timestamp=timestamp.strftime('%I:%M %p (%H:%M)')), icon_url=author.avatar_url_as(format=None, static_format='jpg', size=32)) research_msg = f'{quest.name} Field Research task, reward: {reward} reported at {location}' research_embed.title = 'Click here for my directions to the research!' research_embed.description = "Ask {author} if my directions aren't perfect!".format( author=author.name) research_embed.url = loc_url confirmation = await channel.send(research_msg, embed=research_embed) await utilities_cog.reaction_delay(confirmation, ['\u270f', '🚫']) research_dict = copy.deepcopy( self.bot.guild_dict[guild.id].get('questreport_dict', {})) research_dict[confirmation.id] = { 'regions': regions, 'exp': time.time() + to_midnight, 'expedit': "delete", 'reportmessage': message.id, 'reportchannel': channel.id, 'reportauthor': author.id, 'location': location, 'location_id': stop.id, 'url': loc_url, 'quest': quest.name, 'quest_id': quest.id, 'reward': reward } self.bot.guild_dict[ guild.id]['questreport_dict'] = research_dict success_count += 1 else: return await channel.send(embed=discord.Embed( colour=discord.Colour.red(), description="Failed to load Pokestops list.")) no_stop = len(failed_stops["not_found"]) reported = len(failed_stops["already_reported"]) if no_stop > 0: message = "Could not find the following stops:" for stop in failed_stops["not_found"]: message += f"\n{stop}" await channel.send(embed=discord.Embed(colour=discord.Colour.red(), description=message)) if reported > 0: message = "Task already reported for:" for stop in failed_stops["already_reported"]: message += f"\n{stop}" await channel.send(embed=discord.Embed(colour=discord.Colour.red(), description=message)) if success_count < 1: return listmgmt_cog = self.bot.cogs.get('ListManagement') await listmgmt_cog.update_listing_channels(guild, 'research', edit=False, regions=regions) subscriptions_cog = self.bot.cogs.get('Subscriptions') send_channel = subscriptions_cog.get_region_list_channel( guild, regions[0], 'research') if send_channel is None: send_channel = channel points = 1 if 'encounter' in reward.lower(): pkmn = reward.rsplit(maxsplit=1)[0] research_details = { 'pokemon': [ Pokemon.get_pokemon(self.bot, p) for p in re.split(r'\s*,\s*', pkmn) ], 'regions': regions, 'multi': True } points = await subscriptions_cog.send_notifications_async( 'research', research_details, send_channel, [message.author.id]) elif reward.split( ' ')[0].isdigit() and 'stardust' not in reward.lower(): item = ' '.join(reward.split(' ')[1:]) research_details = { 'item': item, 'regions': regions, 'multi': True } points = await subscriptions_cog.send_notifications_async( 'item', research_details, send_channel, [author.id]) points *= success_count research_reports = self.bot.guild_dict[ctx.guild.id] \ .setdefault('trainers', {}) \ .setdefault(regions[0], {}) \ .setdefault(author.id, {}) \ .setdefault('research_reports', 0) + points self.bot.guild_dict[ctx.guild.id]['trainers'][regions[0]][ author.id]['research_reports'] = research_reports await self._add_db_research_report(ctx, confirmation) clean_list = self.bot.guild_dict[ ctx.guild.id]['configure_dict'].setdefault('channel_auto_clean', []) if ctx.channel.id in clean_list: await ctx.message.delete()
async def raid_json(self, ctx, level=None, *, newlist=None): 'Edits or displays raid_info.json\n\n Usage: !raid_json [level] [list]' msg = '' if (not level) and (not newlist): for level in self.bot.raid_info['raid_eggs']: msg += '\n**Level {level} raid list:** `{raidlist}` \n'\ .format(level=level, raidlist=self.bot.raid_info['raid_eggs'][level]['pokemon']) for pkmn in self.bot.raid_info['raid_eggs'][level]['pokemon']: p = Pokemon.get_pokemon(self, pkmn) msg += '{name} ({number})'.format(name=str(p), number=p.id) msg += ' ' msg += '\n' return await ctx.channel.send(msg) elif level in self.bot.raid_info['raid_eggs'] and (not newlist): msg += '**Level {level} raid list:** `{raidlist}` \n'\ .format(level=level, raidlist=self.bot.raid_info['raid_eggs'][level]['pokemon']) for pkmn in self.bot.raid_info['raid_eggs'][level]['pokemon']: p = Pokemon.get_pokemon(self, pkmn) msg += '{name} ({number})'.format(name=str(p), number=p.id) msg += ' ' msg += '\n' return await ctx.channel.send(msg) elif level in self.bot.raid_info['raid_eggs'] and newlist: newlist = [ re.sub(r'\'', '', item).strip() for item in newlist.strip('[]').split(',') ] try: monlist = [ Pokemon.get_pokemon(self, name).name.lower() for name in newlist ] except: return await ctx.channel.send( "I couldn't understand the list you supplied! " "Please use a comma-separated list of Pokemon species names." ) msg += 'I will replace this:\n' msg += '**Level {level} raid list:** `{raidlist}` \n'\ .format(level=level, raidlist=self.bot.raid_info['raid_eggs'][level]['pokemon']) for pkmn in self.bot.raid_info['raid_eggs'][level]['pokemon']: p = Pokemon.get_pokemon(self, pkmn) msg += '{name} ({number})'.format(name=p.name, number=p.id) msg += ' ' msg += '\n\nWith this:\n' msg += '**Level {level} raid list:** `{raidlist}` \n'.format( level=level, raidlist=monlist) for p in monlist: p = Pokemon.get_pokemon(self, p) msg += '{name} ({number})'.format(name=p.name, number=p.id) msg += ' ' msg += '\n\nContinue?' question = await ctx.channel.send(msg) try: timeout = False res, reactuser = await utils.simple_ask( self, question, ctx.channel, ctx.author.id) except TypeError: timeout = True if timeout or res.emoji == self.failed_react: return await ctx.channel.send("Configuration cancelled!") elif res.emoji == self.success_react: with open(os.path.join('data', 'raid_info.json'), 'r') as fd: data = json.load(fd) data['raid_eggs'][level]['pokemon'] = monlist with open(os.path.join('data', 'raid_info.json'), 'w') as fd: json.dump(data, fd, indent=2, separators=(', ', ': ')) self.bot._load_config() await question.clear_reactions() await question.add_reaction(self.success_react) return await ctx.channel.send("Configuration successful!") else: return await ctx.channel.send( "I'm not sure what went wrong, but configuration is cancelled!" )
async def accept_offer(self, offer_id): offer = self.offers[offer_id] trader = self.guild.get_member(offer_id) lister = self.lister listingmsg = await self.get_listmsg() ctx = await self.bot.get_context(listingmsg) offer = Pokemon.get_pokemon(ctx, offer) offered_pokemon = await self.offered_pokemon() acceptedmsg = ( "{} has agreed to trade their {} for {}'s {}\n\n" "Please DM them to coordinate the trade! " "React with :ballot_box_with_check: when the trade has been " "completed! To reject or cancel this offer, react with " ":stop_button:").format(self.lister.display_name, offered_pokemon.full_name, trader.display_name, offer.full_name) special_check = [ offered_pokemon.shiny, offered_pokemon.legendary, offer.shiny, offer.legendary ] if any(special_check): acceptedmsg += ( "\n\nThis is a Special Trade! These can only be " "completed once per day and can cost up to 1 million " "stardust! Significant discounts can be earned by leveling " "up your friendship before the trade is made!") tradermsg = await trader.send(acceptedmsg) listermsg = await lister.send(acceptedmsg) await tradermsg.add_reaction('\u2611') await tradermsg.add_reaction('\u23f9') await listermsg.add_reaction('\u2611') await listermsg.add_reaction('\u23f9') for offerid in self.offers.keys(): if offerid != offer_id: reject = self.guild.get_member(offerid) try: await reject.send( ("{} accepted a competing offer for their {}." "").format(self.lister.display_name, offered_pokemon.full_name)) except discord.HTTPException: pass await listingmsg.edit(content="{} has accepted an offer!".format( self.lister.display_name), ) await listingmsg.clear_reactions() trader_confirms = False lister_confirms = False def check(r, u): user_check = [u == trader, u == lister] msg_check = [ r.message.id == tradermsg.id, r.message.id == listermsg.id ] emoji_check = [r.emoji == '\u2611', r.emoji == '\u23f9'] if not any(msg_check) or not any(user_check) or not any( emoji_check): return False else: return True while True: reaction, user = await self.bot.wait_for('reaction_add', check=check) if user.id == trader.id: if reaction.emoji == '\u2611': trader_confirms = True elif reaction.emoji == '\u23f9': await tradermsg.delete() return await self.withdraw_offer(trader.id) elif user.id == lister.id: if reaction.emoji == '\u2611': lister_confirms = True elif reaction.emoji == '\u23f9': await listermsg.delete() return await self.reject_offer(trader.id) if trader_confirms and lister_confirms: await listermsg.delete() await tradermsg.delete() return await self.confirm_trade() else: continue
async def offered_pokemon(self): listingmsg = await self.get_listmsg() ctx = await self.bot.get_context(listingmsg) return Pokemon.get_pokemon(ctx, self._data['offered_pokemon'])
async def build_raid_embeds(kyogre, ctx, raid_dict, enabled, assume=False): guild = ctx.guild author = raid_dict.get('reporter', None) if author: author = guild.get_member(author) utils_cog = kyogre.cogs.get('Utilities') location_matching_cog = kyogre.cogs.get('LocationMatching') ctype = raid_dict['type'] raid_embed = discord.Embed(colour=guild.me.colour) gym = location_matching_cog.get_gym_by_id(guild.id, raid_dict['gym']) if gym: gym_info = f"**{gym.name}**\n{'_EX Eligible Gym_' if gym.ex_eligible else ''}" if gym.note is not None: gym_info += f"\n**Note**: {gym.note}" raid_embed.add_field(name='**Gym:**', value=gym_info, inline=False) raid_gmaps_link = gym.maps_url waze_link = utils_cog.create_waze_query(gym.latitude, gym.longitude) apple_link = utils_cog.create_applemaps_query(gym.latitude, gym.longitude) raid_embed.add_field( name='Directions', value= f'[Google]({raid_gmaps_link}) | [Waze]({waze_link}) | [Apple]({apple_link})', inline=False) if raid_dict['exp']: end = datetime.datetime.utcfromtimestamp( raid_dict['exp']) + datetime.timedelta(hours=kyogre.guild_dict[ guild.id]['configure_dict']['settings']['offset']) exp_msg = f"{end.strftime('%I:%M %p')}" else: exp_msg = "Set with **!timerset**" if ctype == 'raid' or assume: raid_pokemon = raid_dict['pokemon'] pkmn = Pokemon.get_pokemon(kyogre, raid_pokemon) if enabled: min_cp, max_cp = pkmn.get_raid_cp_range(False) bmin_cp, bmax_cp = pkmn.get_raid_cp_range(True) cp_range = f"**CP Range:** {min_cp}-{max_cp}\n **Boosted:** {bmin_cp}-{bmax_cp}" weak_str = utils.types_to_str(guild, pkmn.weak_against.keys(), kyogre.config) raid_embed.add_field( name='**Details:**', value='**{pokemon}** ({pokemonnumber}) {type}{cprange}'.format( pokemon=str(pkmn), pokemonnumber=str(pkmn.id), type=utils.types_to_str(guild, pkmn.types, kyogre.config), cprange='\n' + cp_range, inline=True)) raid_embed.add_field( name='**Weaknesses:**', value='{weakness_list}'.format(weakness_list=weak_str)) raid_embed.add_field(name='**Next Group:**', value='Set with **!starttime**') if assume: raid_embed.add_field(name='**Hatches:**', value=exp_msg) else: raid_embed.add_field(name='**Expires:**', value=exp_msg) raid_img_url = pkmn.img_url else: egg_info = kyogre.raid_info['raid_eggs'][str(raid_dict['egglevel'])] egg_img = egg_info['egg_img'] boss_list = [] for entry in egg_info['pokemon']: p = Pokemon.get_pokemon(kyogre, entry) boss_list.append( str(p) + utils.types_to_str(guild, p.types, kyogre.config)) if enabled: raid_embed.add_field(name='**Next Group:**', value='Set with **!starttime**', inline=True) raid_embed.add_field(name='**Hatches:**', value=exp_msg, inline=True) raid_embed.add_field( name='**Possible Bosses:**', value='{bosslist}'.format(bosslist='\n'.join(boss_list)), inline=True) # if len(egg_info['pokemon']) > 1: # raid_embed.add_field(name='**Possible Bosses:**', value='{bosslist1}' # .format(bosslist1='\n'.join(boss_list[::2])), inline=True) # raid_embed.add_field(name='\u200b', value='{bosslist2}' # .format(bosslist2='\n'.join(boss_list[1::2])), inline=True) # else: # raid_embed.add_field(name='**Possible Bosses:**', value='{bosslist}' # .format(bosslist=''.join(boss_list)), inline=True) # raid_embed.add_field(name='\u200b', value='\u200b', inline=True) raid_img_url = 'https://raw.githubusercontent.com/klords/Kyogre/master/images/eggs/{}?cache=0' \ .format(str(egg_img)) if enabled: timestamp = (ctx.message.created_at + datetime.timedelta( hours=kyogre.guild_dict[guild.id]['configure_dict']['settings'] ['offset'])).strftime('%I:%M %p (%H:%M)') if author: raid_embed.set_footer( text='Reported by {author} - {timestamp}'.format( author=author.display_name, timestamp=timestamp), icon_url=author.avatar_url_as(format=None, static_format='jpg', size=32)) raid_embed.add_field( name='**Tips:**', value='`!i` if interested\n`!c` if on the way\n`!h` ' 'when you arrive\n`!x` to cancel your status\n' "`!s` to signal lobby start\n`!shout` to ping raid party", inline=True) raid_embed.set_thumbnail(url=raid_img_url) report_embed = raid_embed embed_indices = await get_embed_field_indices(report_embed) report_embed = await filter_fields_for_report_embed( report_embed, embed_indices, enabled) return report_embed, raid_embed
async def _sub_remove(self, ctx, *, content=None): """Remove a subscription **Usage**: `!sub remove <type> <target>` You will no longer be notified of the specified target for the given event type. You must remove subscriptions using the same type with which they were added. It may be helpful to do `!sub list` first to see your existing subscriptions. You can remove all subscriptions of a type: `!sub remove <type> all` Or remove all subscriptions: `!sub remove all all` Or started a guided session with: `!sub remove` **Valid types**: `pokemon, raid, research, wild, gym, item, lure` **Note**: 'pokemon' includes raid, research, and wild reports""" message = ctx.message channel = message.channel guild = message.guild trainer = message.author.id if content is None: return await self._guided_subscription(ctx, 'Remove') content = content.strip().lower() if content == 'shiny': sub_type, target = ['shiny', 'shiny'] else: error_message = self._get_subscription_command_error( content, self.valid_types) if error_message: response = await message.channel.send(error_message) return await utils.sleep_and_cleanup([message, response], 10) sub_type, target = content.split(' ', 1) candidate_list = [] error_list = [] not_found_list = [] remove_list = [] trainer_query = (TrainerTable.select( TrainerTable.snowflake).where((TrainerTable.snowflake == trainer) & (TrainerTable.guild == guild.id))) # check for special cases skip_parse = False if sub_type == 'all': if target == 'all': try: remove_count = SubscriptionTable.delete()\ .where((SubscriptionTable.trainer << trainer_query) & (SubscriptionTable.guild_id == ctx.guild.id)).execute() message = f'I removed your {remove_count} subscriptions!' except: message = 'I was unable to remove your subscriptions!' confirmation_msg = f'{message}' await channel.send(content=confirmation_msg) return else: target = target.split(',') if sub_type == 'pokemon': for name in target: pkmn = Pokemon.get_pokemon(self.bot, name) if pkmn: candidate_list.append( (sub_type, pkmn.name, pkmn.name)) else: error_list.append(name) if sub_type != "gym": skip_parse = True elif target == 'all': candidate_list.append((sub_type, target, target)) skip_parse = True elif target == 'shiny': candidate_list = [('shiny', 'shiny', 'shiny')] sub_type, target = ['shiny', 'shiny'] skip_parse = True if not skip_parse: candidate_list, error_list = await self._parse_subscription_content( content, 'remove', message) remove_count = 0 s_type = '' for sub in candidate_list: s_type = sub[0] s_target = sub[1] s_entry = sub[2] if len(sub) > 3: spec = sub[3] try: result, __ = SubscriptionTable.get_or_create( guild_id=ctx.guild.id, trainer=trainer, type='gym', target=s_target) current_gym_ids = result.specific split_ids = [] if current_gym_ids: current_gym_ids = current_gym_ids.strip('[]') split_id_string = current_gym_ids.split(', ') for s in split_id_string: try: split_ids.append(int(s)) except ValueError: pass for s in spec: if s in split_ids: remove_count += 1 split_ids.remove(s) result.specific = split_ids result.save() remove_list.append(s_entry) except: error_list.append(s_entry) else: try: if s_type == 'all': remove_count += SubscriptionTable.delete().where( (SubscriptionTable.trainer << trainer_query) & (SubscriptionTable.target == s_target) & (SubscriptionTable.guild_id == ctx.guild.id) ).execute() elif s_target == 'all': remove_count += SubscriptionTable.delete().where( (SubscriptionTable.trainer << trainer_query) & (SubscriptionTable.type == s_type) & (SubscriptionTable.guild_id == ctx.guild.id) ).execute() else: remove_count += SubscriptionTable.delete().where( (SubscriptionTable.trainer << trainer_query) & (SubscriptionTable.type == s_type) & (SubscriptionTable.target == s_target) & (SubscriptionTable.guild_id == ctx.guild.id) ).execute() if remove_count > 0: remove_list.append(s_entry) else: not_found_list.append(s_entry) except: error_list.append(s_entry) not_found_count = len(not_found_list) error_count = len(error_list) confirmation_msg = f'{ctx.author.mention}, successfully removed {remove_count} {s_type} subscriptions' if remove_count > 0: confirmation_msg += '\n**{remove_count} Removed:** \n\t{remove_list}'\ .format(remove_count=remove_count, remove_list=',\n\t'.join(remove_list)) if not_found_count > 0: confirmation_msg += '\n**{not_found_count} Not Found:** \n\t{not_found_list}'\ .format(not_found_count=not_found_count, not_found_list=', '.join(not_found_list)) if error_count > 0: confirmation_msg += '\n**{error_count} Errors:** \n\t{error_list}\n(Check the spelling and try again)'\ .format(error_count=error_count, error_list=', '.join(error_list)) await channel.send(content=confirmation_msg)
async def modify_report(self, ctx, payload, report_id): channel = self.bot.get_channel(ctx.channel.id) try: message = await channel.fetch_message(payload.message_id) except (discord.errors.NotFound, AttributeError): return guild = message.guild try: user = guild.get_member(payload.user_id) except AttributeError: return utils_cog = self.bot.cogs.get('Utilities') regions = utils_cog.get_channel_regions(channel, 'hideout') prompt = f'Modifying details for **Team Rocket Hideout** at ' #**{stop}**\n' \ #f'Which item would you like to modify ***{user.display_name}***?' choices_list = ['Pokestop', 'Leader', 'Lineup'] match = await utils.ask_list(self.bot, prompt, channel, choices_list, user_list=user.id) if match in choices_list: updated = False report = TrainerReportRelation.get_by_id(report_id) # Changing pokestop if match == choices_list[0]: location_matching_cog = self.bot.cogs.get('LocationMatching') utils_cog = self.bot.cogs.get('Utilities') regions = utils_cog.get_channel_regions(channel, 'hideout') stops = location_matching_cog.get_stops(guild.id, regions) query_msg = await channel.send(embed=discord.Embed( colour=discord.Colour.gold(), description="What is the correct Location?")) try: stopmsg = await self.bot.wait_for( 'message', timeout=30, check=(lambda reply: reply.author == user)) except asyncio.TimeoutError: await query_msg.delete() stopmsg = None stop = None if not stopmsg: error = "took too long to respond" elif stopmsg.clean_content.lower() == "cancel": error = "cancelled the report" await stopmsg.delete() elif stopmsg: stop = await location_matching_cog.match_prompt( channel, user.id, stopmsg.clean_content, stops) if not stop: return await channel.send(embed=discord.Embed( colour=discord.Colour.red(), description= f"No pokestop found with name '**{stopmsg.clean_content}**' " f"either. Try reporting again using the exact pokestop name!" ), delete_after=15) if await self._check_existing(stop): return await channel.send(embed=discord.Embed( colour=discord.Colour.red(), description= f"A Team Rocket Hideout has already been reported for '**{stop.name}**'!" )) if stop: updated = True report.location_id = stop.id report.save() # Changing leader elif match == choices_list[1]: query_msg = await channel.send(embed=discord.Embed( colour=discord.Colour.gold(), description="What is the correct Leader?")) try: leadmsg = await self.bot.wait_for( 'message', timeout=30, check=(lambda reply: reply.author == user)) except asyncio.TimeoutError: await query_msg.delete() leadmsg = None if not leadmsg: error = "took too long to respond" elif leadmsg.clean_content.lower() == "cancel": error = "cancelled the report" await leadmsg.delete() else: if leadmsg.clean_content.lower() in self.leader_strings: updated = True report = TrainerReportRelation.get_by_id(report_id) HideoutTable.update(rocket_leader=leadmsg.clean_content.lower())\ .where(HideoutTable.trainer_report == report.id).execute() else: return await channel.send(embed=discord.Embed( colour=discord.Colour.red(), description=f"No Team Rocket Leader found with name " f"{leadmsg.clean_content}. Please start again."), delete_after=15) # Changing lineup elif match == choices_list[2]: query_msg = await channel.send(embed=discord.Embed( colour=discord.Colour.gold(), description="What is the correct Lineup?")) try: lineupmsg = await self.bot.wait_for( 'message', timeout=30, check=(lambda reply: reply.author == user)) except asyncio.TimeoutError: await query_msg.delete() lineupmsg = None if not lineupmsg: error = "took too long to respond" elif lineupmsg.clean_content.lower() == "cancel": error = "cancelled the report" await lineupmsg.delete() else: info = re.split(r',+\s+', lineupmsg.clean_content) pokemon_ids = [None] for i in info: pkmn = Pokemon.get_pokemon(self.bot, i) if pkmn is not None: if pkmn.id not in self.leader_map.values(): pokemon_ids.append(pkmn.id) if not pokemon_ids[0]: hideout = self.get_single_hideout(report.id) if hideout.leader and hideout.leader in self.leader_map: pokemon_ids[0] = self.leader_map[hideout.leader] if len(pokemon_ids) < 3: pokemon_ids = (pokemon_ids + 3 * [None])[:3] updated = True report = TrainerReportRelation.get_by_id(report_id) HideoutTable.update(first_pokemon=pokemon_ids[0], second_pokemon=pokemon_ids[1], third_pokemon=pokemon_ids[2]) \ .where(HideoutTable.trainer_report == report.id).execute() if updated: hideout = self.get_single_hideout(report.id) message = await channel.fetch_message(hideout.message) try: await message.delete() except: pass inv_embed = await self._build_hideout_embed(ctx, hideout) invasionreportmsg = await channel.send( f'**Team Rocket Hideout** report at *{hideout.location_name}* updated!', embed=inv_embed) utilities_cog = self.bot.cogs.get('Utilities') await utilities_cog.reaction_delay(invasionreportmsg, ['\u270f', '🚫']) TrainerReportRelation.update(message=invasionreportmsg.id) \ .where(TrainerReportRelation.id == report.id).execute() listmgmt_cog = self.bot.cogs.get('ListManagement') await listmgmt_cog.update_listing_channels(guild, 'hideout', edit=True, regions=regions) try: await message.remove_reaction(payload.emoji, user) except (discord.errors.NotFound): pass
async def _counters(ctx, Kyogre, pkmn, user=None, weather=None, movesetstr="Unknown Moveset"): if isinstance(pkmn, str): pkmn = Pokemon.get_pokemon(Kyogre, pkmn) if not pkmn: return img_url = pkmn.img_url level = pkmn.raid_level if not level.isdigit(): level = "5" pokebattler_name = pkmn.species.upper() if pkmn.alolan: pokebattler_name += "_ALOLA_FORM" if pkmn.galarian: pokebattler_name += "_GALARIAN_FORM" url = "https://fight.pokebattler.com/raids/defenders/{pkmn}/levels/RAID_LEVEL_{level}/attackers/".format( pkmn=pokebattler_name, level=level) if user: url += "users/{user}/".format(user=user) userstr = "user #{user}'s".format(user=user) else: url += "levels/30/" userstr = "Level 30" weather_list = [ 'none', 'extreme', 'clear', 'sunny', 'rainy', 'partlycloudy', 'cloudy', 'windy', 'snow', 'fog' ] match_list = [ 'NO_WEATHER', 'NO_WEATHER', 'CLEAR', 'CLEAR', 'RAINY', 'PARTLY_CLOUDY', 'OVERCAST', 'WINDY', 'SNOW', 'FOG' ] if not weather: index = 0 else: index = weather_list.index(weather) weather = match_list[index] url += "strategies/CINEMATIC_ATTACK_WHEN_POSSIBLE/DEFENSE_RANDOM_MC?sort=OVERALL&" url += "weatherCondition={weather}&dodgeStrategy=DODGE_REACTION_TIME&aggregation=AVERAGE".format( weather=weather) async with ctx.typing(): async with aiohttp.ClientSession() as sess: async with sess.get(url) as resp: data = await resp.json() title_url = url.replace('https://fight', 'https://www') colour = ctx.guild.me.colour hyperlink_icon = 'https://i.imgur.com/fn9E5nb.png' pbtlr_icon = 'https://www.pokebattler.com/favicon-32x32.png' data = data['attackers'][0] raid_cp = data['cp'] atk_levels = '30' if movesetstr == "Unknown Moveset": ctrs = data['randomMove']['defenders'][-6:] est = data['randomMove']['total']['estimator'] else: for moveset in data['byMove']: move1 = moveset['move1'][:-5].lower().title().replace('_', ' ') move2 = moveset['move2'].lower().title().replace('_', ' ') moveset_str = f'{move1} | {move2}' if moveset_str == movesetstr: ctrs = moveset['defenders'][-6:] est = moveset['total']['estimator'] break else: movesetstr = "Unknown Moveset" ctrs = data['randomMove']['defenders'][-6:] est = data['randomMove']['total']['estimator'] def clean(txt): return txt.replace('_', ' ').title() title = '{pkmn} | {weather} | {movesetstr}'.format( pkmn=pkmn.name, weather=weather_list[index].title(), movesetstr=movesetstr) stats_msg = "**CP:** {raid_cp}\n".format(raid_cp=raid_cp) stats_msg += "**Weather:** {weather}\n".format(weather=clean(weather)) stats_msg += "**Attacker Level:** {atk_levels}".format( atk_levels=atk_levels) ctrs_embed = discord.Embed(colour=colour) ctrs_embed.set_author(name=title, url=title_url, icon_url=hyperlink_icon) ctrs_embed.set_thumbnail(url=img_url) ctrs_embed.set_footer(text='Results courtesy of Pokebattler', icon_url=pbtlr_icon) index = 1 for ctr in reversed(ctrs): ctr_name = clean(ctr['pokemonId']) ctr_nick = clean(ctr.get('name', '')) ctr_cp = ctr['cp'] moveset = ctr['byMove'][-1] moves = "{move1} | {move2}".format(move1=clean( moveset['move1'])[:-5], move2=clean(moveset['move2'])) name = "#{index} - {ctr_name}".format(index=index, ctr_name=(ctr_nick or ctr_name)) cpstr = "CP" ctrs_embed.add_field(name=name, value=f"{cpstr}: {ctr_cp}\n{moves}") index += 1 ctrs_embed.add_field( name="Results with {userstr} attackers".format(userstr=userstr), value= "[See your personalized results!](https://www.pokebattler.com/raids/{pkmn})" .format(pkmn=pokebattler_name)) if user: ctrs_embed.add_field( name="Pokebattler Estimator:", value="Difficulty rating: {est}".format(est=est)) await ctx.channel.send( f"Check your inbox {ctx.author.mention}, I've sent your personalized results to you directly!" ) return await ctx.author.send(embed=ctrs_embed) await ctx.channel.send(embed=ctrs_embed)
async def research(self, ctx, *, details=None): """**Usage**: `!research [pokestop name, quest]` Use just the command to start a guided session. Or provide Pokestop name and quest info to complete the report.""" message = ctx.message channel = message.channel author = message.author guild = message.guild timestamp = (message.created_at + datetime.timedelta( hours=self.bot.guild_dict[message.channel.guild.id] ['configure_dict']['settings']['offset'])) to_midnight = 24 * 60 * 60 - (timestamp - timestamp.replace( hour=0, minute=0, second=0, microsecond=0)).seconds error = False utilities_cog = self.bot.cogs.get('Utilities') loc_url = utilities_cog.create_gmaps_query("", message.channel, type="research") research_embed = discord.Embed( colour=message.guild.me.colour)\ .set_thumbnail( url='https://raw.githubusercontent.com/klords/Kyogre/master/images/misc/field-research.png?cache=0') research_embed.set_footer( text='Reported by {author} - {timestamp}'.format( author=author.display_name, timestamp=timestamp.strftime('%I:%M %p (%H:%M)')), icon_url=author.avatar_url_as(format=None, static_format='jpg', size=32)) utils_cog = self.bot.cogs.get('Utilities') regions = utils_cog.get_channel_regions(channel, 'research') location_matching_cog = self.bot.cogs.get('LocationMatching') stops = location_matching_cog.get_stops(guild.id, regions) location, quest, reward = None, None, None questrewardmanagement_cog = self.bot.cogs.get('QuestRewardManagement') if not questrewardmanagement_cog: return await channel.send(embed=discord.Embed( colour=discord.Colour.red(), description="Quest data is not loaded for this server.")) while True: if details: research_split = details.rsplit(",", 1) if len(research_split) != 2: error = "entered an incorrect amount of arguments.\n\n" \ "Usage: **!research** or **!research <pokestop>, <quest>**" break location, quest_name = research_split if stops: stop = await location_matching_cog.match_prompt( channel, author.id, location, stops) if not stop: swap_msg = await channel.send(embed=discord.Embed( colour=discord.Colour.red(), description= f"I couldn't find a pokestop named '**{location}**'. " f"Perhaps you have reversed the order of your report?\n\n" f"Looking up stop with name '**{quest_name.strip()}**'" )) quest_name, location = research_split stop = await location_matching_cog.match_prompt( channel, author.id, location.strip(), stops) if not stop: await swap_msg.delete() self.bot.help_logger.info( f"User: {ctx.author.name}, channel: {ctx.channel}, error: No Pokestop found with name: {location.strip()}." ) err_msg = await channel.send(embed=discord.Embed( colour=discord.Colour.red(), description= f"No pokestop found with name '**{location.strip()}**' " f"either. Try reporting again using the exact pokestop name!" )) return await utils.sleep_and_cleanup([err_msg], 15) await swap_msg.delete() if self.get_existing_research(guild, stop): return await channel.send(embed=discord.Embed( colour=discord.Colour.red(), description= f"A quest has already been reported for {stop.name}" )) location = stop.name loc_url = stop.maps_url regions = [stop.region] else: loc_url = utilities_cog.create_gmaps_query(location, channel, type="research") location = location.replace(loc_url, "").strip() quest = await questrewardmanagement_cog.get_quest( ctx, quest_name.strip()) if not quest: self.bot.help_logger.info( f"User: {ctx.author.name}, channel: {ctx.channel}, error: No quest found with name: {quest_name}." ) return await channel.send(embed=discord.Embed( colour=discord.Colour.red(), description= f"I couldn't find a quest named '{quest_name}'")) reward = await questrewardmanagement_cog.prompt_reward( ctx, quest) if not reward: return await channel.send(embed=discord.Embed( colour=discord.Colour.red(), description= f"I couldn't find a reward for '{quest_name}'")) research_embed.add_field(name="**Pokestop:**", value='\n'.join( textwrap.wrap(location.title(), width=30))) research_embed.add_field(name="**Quest:**", value='\n'.join( textwrap.wrap(quest.name.title(), width=30))) research_embed.add_field(name="**Reward:**", value='\n'.join( textwrap.wrap(reward.title(), width=30))) break else: research_embed.add_field( name='**New Research Report**', value="I'll help you report a research quest!\n\n" "First, I'll need to know what **pokestop** you received the quest from." " Reply with the name of the **pokestop**. " "You can reply with **cancel** to stop anytime.", inline=False) pokestopwait = await channel.send(embed=research_embed) try: pokestopmsg = await self.bot.wait_for( 'message', timeout=60, check=(lambda reply: reply.author == message.author)) except asyncio.TimeoutError: pokestopmsg = None await pokestopwait.delete() if not pokestopmsg: error = "took too long to respond" break elif pokestopmsg.clean_content.lower() == "cancel": error = "cancelled the report" await pokestopmsg.delete() break elif pokestopmsg: location = pokestopmsg.clean_content if stops: stop = await location_matching_cog.match_prompt( channel, author.id, location, stops) if not stop: self.bot.help_logger.info( f"User: {ctx.author.name}, channel: {ctx.channel}, error: No Pokestop found with name: {location.strip()}." ) return await channel\ .send(embed=discord.Embed(colour=discord.Colour.red(), description=f"I couldn't find a pokestop named '{location}'." f"Try again using the exact pokestop name!")) if self.get_existing_research(guild, stop): return await channel.send(embed=discord.Embed( colour=discord.Colour.red(), description= f"A quest has already been reported for {stop.name}" )) location = stop.name loc_url = stop.maps_url regions = [stop.region] else: loc_url = utilities_cog.create_gmaps_query( location, channel, type="research") location = location.replace(loc_url, "").strip() await pokestopmsg.delete() research_embed.add_field(name="**Pokestop:**", value='\n'.join( textwrap.wrap(location.title(), width=30))) research_embed.set_field_at( 0, name=research_embed.fields[0].name, value= "Great! Now, reply with the **quest** that you received from " "**{location}**. You can reply with **cancel** to stop anytime." "\n\nHere's what I have so far:".format(location=location), inline=False) questwait = await channel.send(embed=research_embed) try: questmsg = await self.bot.wait_for( 'message', timeout=60, check=(lambda reply: reply.author == message.author)) except asyncio.TimeoutError: questmsg = None await questwait.delete() if not questmsg: error = "took too long to respond" break elif questmsg.clean_content.lower() == "cancel": error = "cancelled the report" await questmsg.delete() break elif questmsg: quest = await questrewardmanagement_cog.get_quest( ctx, questmsg.clean_content.strip()) await questmsg.delete() if not quest: error = "didn't identify the quest" break research_embed.add_field(name="**Quest:**", value='\n'.join( textwrap.wrap(quest.name.title(), width=30))) reward = await questrewardmanagement_cog.prompt_reward( ctx, quest.name.title()) if not reward: error = "didn't identify the reward" break research_embed.add_field(name="**Reward:**", value='\n'.join( textwrap.wrap(reward.title(), width=30))) research_embed.remove_field(0) break if not error: research_msg = f'{quest.name} Field Research task, reward: {reward} reported at {location}' research_embed.title = 'Click here for my directions to the research!' research_embed.description = "Ask {author} if my directions aren't perfect!".format( author=author.name) research_embed.url = loc_url confirmation = await channel.send(research_msg, embed=research_embed) await utilities_cog.reaction_delay(confirmation, ['\u270f', '🚫']) research_dict = copy.deepcopy(self.bot.guild_dict[guild.id].get( 'questreport_dict', {})) research_dict[confirmation.id] = { 'regions': regions, 'exp': time.time() + to_midnight, 'expedit': "delete", 'reportmessage': message.id, 'reportchannel': channel.id, 'reportauthor': author.id, 'location': location, 'location_id': stop.id, 'url': loc_url, 'quest': quest.name, 'quest_id': quest.id, 'reward': reward } self.bot.guild_dict[guild.id]['questreport_dict'] = research_dict listmgmt_cog = self.bot.cogs.get('ListManagement') await listmgmt_cog.update_listing_channels(guild, 'research', edit=False, regions=regions) subscriptions_cog = self.bot.cogs.get('Subscriptions') send_channel = subscriptions_cog.get_region_list_channel( guild, regions[0], 'research') if send_channel is None: send_channel = channel points = 1 if 'encounter' in reward.lower(): pkmn = reward.rsplit(maxsplit=1)[0] research_details = { 'pokemon': [ Pokemon.get_pokemon(self.bot, p) for p in re.split(r'\s*,\s*', pkmn) ], 'location': location, 'regions': regions } points = await subscriptions_cog.send_notifications_async( 'research', research_details, send_channel, [message.author.id]) elif reward.split( ' ')[0].isdigit() and 'stardust' not in reward.lower(): item = ' '.join(reward.split(' ')[1:]) research_details = { 'item': item, 'location': location, 'regions': regions } points = await subscriptions_cog.send_notifications_async( 'item', research_details, send_channel, [author.id]) research_reports = self.bot.guild_dict[ctx.guild.id]\ .setdefault('trainers', {})\ .setdefault(regions[0], {})\ .setdefault(author.id, {})\ .setdefault('research_reports', 0) + points self.bot.guild_dict[ctx.guild.id]['trainers'][regions[0]][ author.id]['research_reports'] = research_reports await self._add_db_research_report(ctx, confirmation) else: research_embed.clear_fields() research_embed.add_field( name='**Research Report Cancelled**', value="Your report has been cancelled because you {error}! " "Retry when you're ready.".format(error=error), inline=False) confirmation = await channel.send(embed=research_embed) return await utils.sleep_and_cleanup([message, confirmation], 10)
async def _get_generic_counters(Kyogre, guild, pkmn, weather=None): if isinstance(pkmn, str): pkmn = Pokemon.get_pokemon(Kyogre, pkmn) if not pkmn: return emoji_dict = { 0: '0\u20e3', 1: '1\u20e3', 2: '2\u20e3', 3: '3\u20e3', 4: '4\u20e3', 5: '5\u20e3', 6: '6\u20e3', 7: '7\u20e3', 8: '8\u20e3', 9: '9\u20e3', 10: '10\u20e3' } ctrs_dict = {} ctrs_index = 0 ctrs_dict[ctrs_index] = {} ctrs_dict[ctrs_index]['moveset'] = "Unknown Moveset" ctrs_dict[ctrs_index]['emoji'] = '0\u20e3' img_url = pkmn.img_url level = pkmn.raid_level if not level.isdigit(): level = "5" pokebattler_name = pkmn.species.upper() if pkmn.alolan: pokebattler_name = f"{pkmn.species.upper()}_ALOLA_FORM" if pkmn.galarian: pokebattler_name = f"{pkmn.species.upper()}_GALARIAN_FORM" url = "https://fight.pokebattler.com/raids/defenders/{pkmn}/levels/RAID_LEVEL_{level}/attackers/".format( pkmn=pokebattler_name, level=level) url += "levels/30/" weather_list = [ 'none', 'extreme', 'clear', 'sunny', 'rainy', 'partlycloudy', 'cloudy', 'windy', 'snow', 'fog' ] match_list = [ 'NO_WEATHER', 'NO_WEATHER', 'CLEAR', 'CLEAR', 'RAINY', 'PARTLY_CLOUDY', 'OVERCAST', 'WINDY', 'SNOW', 'FOG' ] if not weather: index = 0 else: index = weather_list.index(weather) weather = match_list[index] url += "strategies/CINEMATIC_ATTACK_WHEN_POSSIBLE/DEFENSE_RANDOM_MC?sort=OVERALL&" url += "weatherCondition={weather}&dodgeStrategy=DODGE_REACTION_TIME&aggregation=AVERAGE".format( weather=weather) title_url = url.replace('https://fight', 'https://www') hyperlink_icon = 'https://i.imgur.com/fn9E5nb.png' pbtlr_icon = 'https://www.pokebattler.com/favicon-32x32.png' async with aiohttp.ClientSession() as sess: async with sess.get(url) as resp: data = await resp.json() data = data['attackers'][0] raid_cp = data['cp'] atk_levels = '30' ctrs = data['randomMove']['defenders'][-6:] def clean(txt): return txt.replace('_', ' ').title() title = '{pkmn} | {weather} | Unknown Moveset'.format( pkmn=pkmn.name, weather=weather_list[index].title()) stats_msg = "**CP:** {raid_cp}\n".format(raid_cp=raid_cp) stats_msg += "**Weather:** {weather}\n".format(weather=clean(weather)) stats_msg += "**Attacker Level:** {atk_levels}".format( atk_levels=atk_levels) ctrs_embed = discord.Embed(colour=guild.me.colour) ctrs_embed.set_author(name=title, url=title_url, icon_url=hyperlink_icon) ctrs_embed.set_thumbnail(url=img_url) ctrs_embed.set_footer(text='Results courtesy of Pokebattler', icon_url=pbtlr_icon) ctrindex = 1 for ctr in reversed(ctrs): ctr_name = clean(ctr['pokemonId']) moveset = ctr['byMove'][-1] moves = "{move1} | {move2}".format(move1=clean(moveset['move1'])[:-5], move2=clean(moveset['move2'])) name = "#{index} - {ctr_name}".format(index=ctrindex, ctr_name=ctr_name) ctrs_embed.add_field(name=name, value=moves) ctrindex += 1 ctrs_dict[ctrs_index]['embed'] = ctrs_embed for moveset in data['byMove']: ctrs_index += 1 move1 = moveset['move1'][:-5].lower().title().replace('_', ' ') move2 = moveset['move2'].lower().title().replace('_', ' ') movesetstr = f'{move1} | {move2}' ctrs = moveset['defenders'][-6:] title = '{pkmn} | {weather} | {movesetstr}'.format( pkmn=pkmn.name, weather=weather_list[index].title(), movesetstr=movesetstr) ctrs_embed = discord.Embed(colour=guild.me.colour) ctrs_embed.set_author(name=title, url=title_url, icon_url=hyperlink_icon) ctrs_embed.set_thumbnail(url=img_url) ctrs_embed.set_footer(text='Results courtesy of Pokebattler', icon_url=pbtlr_icon) ctrindex = 1 for ctr in reversed(ctrs): ctr_name = clean(ctr['pokemonId']) moveset = ctr['byMove'][-1] moves = "{move1} | {move2}".format(move1=clean( moveset['move1'])[:-5], move2=clean(moveset['move2'])) name = "#{index} - {ctr_name}".format(index=ctrindex, ctr_name=ctr_name) ctrs_embed.add_field(name=name, value=moves) ctrindex += 1 ctrs_dict[ctrs_index] = { 'moveset': movesetstr, 'embed': ctrs_embed, 'emoji': emoji_dict[ctrs_index] } moveset_list = [] for moveset in ctrs_dict: moveset_list.append( f"{ctrs_dict[moveset]['emoji']}: {ctrs_dict[moveset]['moveset']}\n" ) for moveset in ctrs_dict: ctrs_split = int(round(len(moveset_list) / 2 + 0.1)) ctrs_dict[moveset]['embed'].add_field( name="**Possible Movesets:**", value=f"{''.join(moveset_list[:ctrs_split])}", inline=True) ctrs_dict[moveset]['embed'].add_field( name="\u200b", value=f"{''.join(moveset_list[ctrs_split:])}", inline=True) ctrs_dict[moveset]['embed'].add_field( name="Results with Level 30 attackers", value= "[See your personalized results!](https://www.pokebattler.com/raids/{pkmn})" .format(pkmn=pokebattler_name), inline=False) return ctrs_dict
async def _process_status_command(self, ctx, teamcounts): eta = None if teamcounts is not None: if teamcounts.lower().find('eta') > -1: idx = teamcounts.lower().find('eta') eta = teamcounts[idx:] teamcounts = teamcounts[:idx] guild = ctx.guild trainer_dict = self.bot.guild_dict[guild.id]['raidchannel_dict'][ ctx.channel.id]['trainer_dict'] entered_interest = trainer_dict.get(ctx.author.id, {}).get('interest', []) egglevel = self.bot.guild_dict[guild.id]['raidchannel_dict'][ ctx.channel.id]['egglevel'] parsed_counts = await self._parse_teamcounts(ctx, teamcounts, trainer_dict, egglevel) errors = [] if not parsed_counts: raise ValueError( "I couldn't understand that format! " "Check the format against `!help interested` and try again.") totalA, totalB, groups, bosses = parsed_counts.groups() total = totalA or totalB if bosses and self.bot.guild_dict[guild.id]['raidchannel_dict'][ ctx.channel.id]['type'] == "egg": entered_interest = set(entered_interest) bosses_list = bosses.lower().split(',') if isinstance(bosses_list, str): bosses_list = [bosses.lower()] for boss in bosses_list: pkmn = Pokemon.get_pokemon(self.bot, boss) if pkmn: name = pkmn.name.lower() if name in self.bot.raid_info['raid_eggs'][egglevel][ 'pokemon']: entered_interest.add(name) else: errors.append( "{pkmn} doesn't appear in level {egglevel} raids! Please try again." .format(pkmn=pkmn.name, egglevel=egglevel)) if errors: errors.append( "Invalid Pokemon detected. Please check the pinned message " "for the list of possible bosses and try again.") raise ValueError('\n'.join(errors)) elif not bosses and self.bot.guild_dict[guild.id]['raidchannel_dict'][ ctx.channel.id]['type'] == 'egg': entered_interest = [ p for p in self.bot.raid_info['raid_eggs'][egglevel]['pokemon'] ] if total: if total[0] == 'w': total = total[1:] total = int(total) elif (ctx.author.id in trainer_dict) and (sum( trainer_dict[ctx.author.id]['status'].values()) > 0): total = trainer_dict[ctx.author.id]['count'] elif groups: total = re.sub('[^0-9 ]', ' ', groups) total = sum([int(x) for x in total.split()]) else: total = 1 if not groups: groups = '' teamcounts = f"{total} {groups}" result = await self._party_status(ctx, total, teamcounts) return (result, entered_interest, eta)
async def _parse_subscription_content(self, content, source, message=None): channel = message.channel author = message.author sub_list = [] error_list = [] raid_level_list = [str(n) for n in list(range(1, 6))] sub_type, target = content.split(' ', 1) if sub_type == 'gym': if message: channel = message.channel guild = message.guild gyms = self._get_gyms(guild.id) if gyms: gym_dict = {} for t in target.split(','): location_matching_cog = self.bot.cogs.get( 'LocationMatching') gym = await location_matching_cog.match_prompt( channel, author.id, t, gyms) if gym: if source == 'add': question_spec = 'would you like to be notified' else: question_spec = 'would you like to remove notifications' level = await utils.ask_list( self.bot, f"For {gym.name} which level raids {question_spec}?", channel, ['All'] + list(range(1, 6)), user_list=[author.id], multiple=True) if level: if 'All' in level: level = list(range(1, 6)) for l in level: gym_level_dict = gym_dict.get( l, { 'ids': [], 'names': [] }) gym_level_dict['ids'].append(gym.id) gym_level_dict['names'].append(gym.name) gym_dict[l] = gym_level_dict else: error_list.append(t) else: error_list.append(t) for l in gym_dict.keys(): entry = f"L{l} Raids at {', '.join(gym_dict[l]['names'])}" sub_list.append(('gym', l, entry, gym_dict[l]['ids'])) return sub_list, error_list if sub_type == 'item': result = RewardTable.select(RewardTable.name, RewardTable.quantity) result = result.objects(Reward) results = [o for o in result] item_names = [r.name.lower() for r in results] targets = target.split(',') for t in targets: candidates = utils.get_match(item_names, t, score_cutoff=60, isPartial=True, limit=20) name = await utils.prompt_match_result(self.bot, channel, author.id, t, candidates) if name is not None: sub_list.append((sub_type, name, name)) else: error_list.append(t) return sub_list, error_list if sub_type == 'wild': perfect_pattern = r'((100(\s*%)?|perfect)(\s*ivs?\b)?)' target, count = re.subn(perfect_pattern, '', target, flags=re.I) if count: sub_list.append((sub_type, 'perfect', 'Perfect IVs')) if sub_type == 'lure': result = LureTypeTable.select(LureTypeTable.name) result = result.objects(Lure) results = [o for o in result] lure_names = [r.name.lower() for r in results] targets = target.split(',') for t in targets: candidates = utils.get_match(lure_names, t, score_cutoff=60, isPartial=True, limit=20) name = await utils.prompt_match_result(self.bot, channel, author.id, t, candidates) if name is not None: sub_list.append((sub_type, name, name)) else: error_list.append(t) return sub_list, error_list if ',' in target: target = set([t.strip() for t in target.split(',')]) else: target = set([target]) if sub_type == 'raid': selected_levels = target.intersection(raid_level_list) for level in selected_levels: entry = f'L{level} Raids' target.remove(level) sub_list.append((sub_type, level, entry)) ex_pattern = r'^(ex([- ]*eligible)?)$' ex_r = re.compile(ex_pattern, re.I) matches = list(filter(ex_r.match, target)) if matches: entry = 'EX-Eligible Raids' for match in matches: target.remove(match) sub_list.append((sub_type, 'ex-eligible', entry)) remaining_list = [str(n) for n in list(range(6, 800))] other_numbers = target.intersection(remaining_list) for num in other_numbers: target.remove(num) error_list.append(num) for name in target: pkmn = Pokemon.get_pokemon(self.bot, name) if pkmn: sub_list.append((sub_type, pkmn.name, pkmn.name)) else: error_list.append(name) return sub_list, error_list
async def _invasion(self, ctx, *, info=None): """**Usage**: `!rocket <pokestop name> [,pokemon]` Pokemon name is optional and can be updated later.""" message = ctx.message channel = message.channel author = message.author guild = message.guild img_url = author.avatar_url_as(format=None, static_format='jpg', size=32) info = re.split(r',+\s+', info) stopname = info[0] report_time = message.created_at + datetime.timedelta( hours=self.bot.guild_dict[ guild.id]['configure_dict']['settings']['offset']) report_time_int = round(report_time.timestamp()) timestamp = report_time.strftime('%Y-%m-%d %H:%M:%S') utilities_cog = self.bot.cogs.get('Utilities') subscriptions_cog = self.bot.cogs.get('Subscriptions') location_matching_cog = self.bot.cogs.get('LocationMatching') utils_cog = self.bot.cogs.get('Utilities') regions = utils_cog.get_channel_regions(channel, 'takeover') stops = location_matching_cog.get_stops(guild.id, regions) if stops: stop = await location_matching_cog.match_prompt( channel, author.id, stopname, stops) if not stop: self.bot.help_logger.info( f"User: {ctx.author.name}, channel: {ctx.channel}, error: No Pokestop found {stopname}." ) return await channel.send(embed=discord.Embed( colour=discord.Colour.red(), description=f"No pokestop found with name '**{stopname}**' " f"either. Try reporting again using the exact pokestop name!" ), delete_after=15) if await self._check_existing(ctx, stop): return await channel.send(embed=discord.Embed( colour=discord.Colour.red(), description= f"A Team Rocket Takeover has already been reported for '**{stop.name}**'!" )) location = stop.name loc_url = stop.maps_url regions = [stop.region] pokemon_name = None pkmnid = None if len(info) > 1: pkmn = Pokemon.get_pokemon(self.bot, info[1]) if pkmn is not None: pkmnid = pkmn.id pokemon_name = pkmn.name img_url = pkmn.img_url img_url = img_url.replace('007_', '007normal_') img_url = img_url.replace('025_', '025normal_') report = TrainerReportRelation.create(created=report_time_int, trainer=author.id, location=stop.id) invasion = InvasionTable.create(trainer_report=report, pokemon_number=pkmnid) desc = f"**Pokestop**: {stop.name}" if pokemon_name is None: desc += "\n**Pokemon**: Unknown" else: desc += f"\n**Pokemon**: {pokemon_name.capitalize()}" inv_embed = discord.Embed(title=f'Click for directions!', description=desc, url=stop.maps_url, colour=discord.Colour.red()) inv_embed.set_footer(text='Reported by {author} - {timestamp}'.format( author=author.display_name, timestamp=timestamp), icon_url=img_url) if random.randint(0, 1): inv_embed.set_thumbnail( url= "https://github.com/tehstone/Kyogre/blob/master/images/misc/Team_Rocket_Grunt_F.png?raw=true" ) else: inv_embed.set_thumbnail( url= "https://github.com/tehstone/Kyogre/blob/master/images/misc/Team_Rocket_Grunt_M.png?raw=true" ) invasionreportmsg = await channel.send( f'**Team Rocket Takeover** reported at *{stop.name}*', embed=inv_embed) await utilities_cog.reaction_delay(invasionreportmsg, ['🇵', '💨']) #, '\u270f']) details = {'regions': regions, 'type': 'takeover', 'location': stop} TrainerReportRelation.update(message=invasionreportmsg.id).where( TrainerReportRelation.id == report.id).execute() send_channel = subscriptions_cog.get_region_list_channel( guild, stop.region, 'invasion') if send_channel is None: send_channel = message.channel await subscriptions_cog.send_notifications_async( 'takeover', details, send_channel, [message.author.id]) self.bot.event_loop.create_task( self.invasion_expiry_check(invasionreportmsg, report.id, author)) await asyncio.sleep( 1 ) # without this the listing update will miss the most recent report listmgmt_cog = self.bot.cogs.get('ListManagement') await listmgmt_cog.update_listing_channels(guild, 'takeover', edit=False, regions=regions)