Example #1
0
 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}")
Example #2
0
 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
Example #3
0
 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
Example #4
0
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
Example #5
0
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
Example #6
0
 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
Example #7
0
    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}")
Example #8
0
 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']
     ]
Example #9
0
 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)
Example #10
0
    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')
Example #11
0
 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")
Example #12
0
    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()
Example #13
0
 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}!')
Example #14
0
 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)
Example #15
0
 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")
Example #16
0
    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()
Example #17
0
    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)
Example #18
0
    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()
Example #19
0
 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!"
             )
Example #20
0
    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
Example #21
0
 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'])
Example #22
0
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
Example #23
0
    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)
Example #24
0
 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
Example #25
0
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)
Example #26
0
 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)
Example #27
0
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
Example #28
0
 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)
Example #29
0
    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
Example #30
0
    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)