Example #1
0
 async def list_rockets(self, channel, tz):
     report_channel = ReportChannel(self.bot, channel)
     data = await report_channel.get_all_rockets()
     if not data:
         return await channel.send("No Team GO Rocket Invasions reported!")
     wild_list = []
     for wild_id in data:
         wild = Rocket.instances.get(wild_id)
         if not wild:
             continue
         wild_list.append(await wild.summary_str(tz))
     number = len(wild_list)
     page_size = 10
     pages = ceil(number / page_size)
     ins = list(range(0, number, page_size))
     color = channel.guild.me.color
     for i in range(pages):
         if pages == 1:
             title = "Current Team GO Rocket Invasions"
         else:
             title = f"Current Team GO Rocket Invasions (Page {i+1} of {pages})"
         content = "\n\n".join(wild_list[ins[i]:ins[i] + page_size])
         embed = formatters.make_embed(title=title,
                                       content=content,
                                       msg_colour=color)
         await channel.send(embed=embed)
Example #2
0
 async def serve_map(self, request):
     channel_id = request.match_info['channel_id']
     channel = self.bot.get_channel(channel_id)
     report_channel = ReportChannel(self.bot, channel)
     rc_map = ReportChannelMap(report_channel)
     m = await rc_map.gym_map()
     return m._repr_html_()
Example #3
0
 async def list_research(self, channel):
     color = channel.guild.me.color
     report_channel = ReportChannel(self.bot, channel)
     data = await report_channel.get_all_research()
     research_list = []
     if not data:
         return await channel.send('No research reported!')
     for research_id in data:
         research = Research.instances.get(research_id)
         if not research:
             continue
         research_list.append(await research.summary_str())
     research_list_embeds = make_research_list_embeds(research_list, color)
     for embed in research_list_embeds:
         await channel.send(embed=embed)
         await asyncio.sleep(0.25)
Example #4
0
 async def showmap(self, ctx):
     report_channel = ReportChannel(self.bot, ctx.channel)
     rc_map = ReportChannelMap(report_channel)
     await ctx.send(rc_map.url)
Example #5
0
    async def rocket(self,
                     ctx,
                     rocket_type: Optional[RocketType] = RocketType.GRUNT,
                     pokemon: Greedy[Pokemon] = [],
                     *,
                     location: Pokestop):
        """Report a Team GO Rocket Pokestop invasion.

        **Arguments**
        *rocket_type (optional):* The type of Invasion. One of 'grunt', 'arlo',
        'cliff', 'sierra', or 'giovanni'. Defaults to 'grunt'.
        *pokemon (optional):* The names of the Pokemon the enemy has, in order.
        If you give more than three Pokemon, only the first three will be used.
        *location:* The location of the invasion.

        If *location* is the name of a known Pokestop,
        directions will be accurate. Otherwise Meowth just Googles
        the supplied *location* plus the name of the city.

        **Example:** `!rocket city park`"""

        mod_id = next(snowflake.create())
        name = rocket_type.name.lower()
        tz = await ctx.tz()
        new_mod = Rocket(mod_id, self.bot, ctx.guild.id, ctx.author.id,
                         location, rocket_type, tz)
        if pokemon:
            if len(pokemon) > 3:
                pokemon = pokemon[:3]
            new_mod.pokemon = [x.id for x in pokemon]
            pkmn_names = [await x.name() for x in pokemon]
            pkmn_str = f"The enemy's party: {', '.join(pkmn_names)}! "
        else:
            pkmn_str = ""
        react_list = list(new_mod.react_list.values())
        wants = await new_mod.get_wants()
        mentions = [await x.mention() for x in wants if await x.mention()]
        mention_str = "\u200b".join(mentions)
        embed = (await RocketEmbed.from_mod(new_mod)).embed
        if mentions:
            reportcontent = mention_str + " - "
        else:
            reportcontent = ""
        coming = '🚗'
        caught_id = new_mod.react_list['caught']
        caught = ctx.bot.get_emoji(caught_id)
        despawned = '💨'
        name = new_mod.name
        report_channels = []
        report_channel = ReportChannel(ctx.bot, ctx.channel)
        if isinstance(location, Pokestop):
            loc_name = await location._name()
            channel_list = await location.get_all_channels('rocket')
            report_channels.extend(channel_list)
        else:
            loc_name = location._name
        reportcontent += f'{name} reported at {loc_name}! {pkmn_str}Use {coming} if you are on the way, {str(caught)} if you catch the Shadow Pokemon, and {despawned} if it has ended.'
        if report_channel not in report_channels:
            report_channels.append(report_channel)
        for channel in report_channels:
            try:
                reportmsg = await channel.channel.send(reportcontent,
                                                       embed=embed)
                for react in react_list:
                    if isinstance(react, int):
                        react = self.bot.get_emoji(react)
                    await reportmsg.add_reaction(react)
                new_mod.message_ids.append(
                    f"{reportmsg.channel.id}/{reportmsg.id}")
            except:
                continue
        for idstring in new_mod.message_ids:
            Rocket.by_message[idstring] = new_mod
        await new_mod.upsert()
        self.bot.loop.create_task(new_mod.monitor_status())
Example #6
0
 async def channel_forecast(self, ctx):
     channel = ReportChannel(ctx.bot, ctx.channel)
     base_map, cells = await channel.get_map()
     W = base_map.width
     H = base_map.height
     padding_y = base_map.padding[1]
     font_size = ceil(padding_y * 1.2)
     font = ImageFont.truetype(
         font=os.path.join(ctx.bot.bot_dir, "fonts", "Poppins-Regular.ttf"),
         size=font_size
     )
     markers = []
     for cell in cells:
         forecast = await cell.forecast(ctx.guild.id)
         if not forecast:
             continue
         coords = cell.center_coords
         coords = (coords.lng().degrees(), coords.lat().degrees())
         for hour in forecast:
             weather = Weather(ctx.bot, forecast[hour])
             icon_path = weather.icon_path
             m = {
                 'hour': hour,
                 'icon_path': icon_path,
                 'coords': coords
             }
             markers.append(m)
     max_hour = max([x['hour'] for x in markers], default=0)
     maps = []
     for i in range(max_hour+1):
         maps.append(deepcopy(base_map))
     for m in markers:
         hour = m['hour']
         frame = maps[hour]
         coords = m['coords']
         icon_path = m['icon_path']
         marker = IconMarker(coords, icon_path, 32, 32)
         frame.add_marker(marker)
     f = io.BytesIO()
     images = [m.render() for m in maps]
     zone = await ctx.tz()
     tz = timezone(zone)
     now_dt = datetime.now(tz=tz)
     initial_hr = now_dt.replace(minute=0)
     for i in range(len(images)):
         im = images[i]
         im = im.crop((0,0,W,(H-padding_y)))
         hour = initial_hr + timedelta(hours=i)
         timestr = hour.strftime('%I:%M %p')
         d = ImageDraw.Draw(im)
         w, h = d.textsize(timestr, font=font)
         x = (W - w) / 2
         d.text((x, ceil(H*.01)), timestr, font=font, fill=(0,0,0,255))
         images[i] = im
     imageio.mimwrite(f, images, format='GIF-PIL', duration=1, subrectangles=True)
     to_send = discord.File(io.BytesIO(f.getvalue()), filename='forecast.gif')
     p = ctx.prefix
     title = 'Pokémon Go Weather Forecast: Current Region'
     desc = f'You can help Meowth determine the correct pull times by using **{p}weather** to correct the predicted weather in raid channels!'
     embed = discord.Embed(title=title, description=desc)
     embed.set_image(url='attachment://forecast.gif')
     await ctx.send(embed=embed, file=to_send)
Example #7
0
 async def convert(cls, ctx, arg):
     report_channel = ReportChannel(ctx.bot, ctx.channel)
     coords = await report_channel.center_coords()
     return await cls.from_arg(ctx.bot, ctx.command.name, ctx.channel,
                               ctx.author.id, arg, coords)
Example #8
0
    async def lure(self, ctx, kind, *, location: Pokestop):
        """Report a lured Pokestop.

        **Arguments**
        *kind:* Glacial, Mossy or Magnetic
        *location:* The location of the lure.

        If *location* is the name of a known Pokestop,
        directions will be accurate. Otherwise Meowth just Googles
        the supplied *location* plus the name of the city.

        **Example:** `!lure glacial city park`"""

        word_list = ["glacial", "mossy", "magnetic"]
        result = fuzzymatch.get_match(word_list, kind)
        kind = result[0]
        if not kind:
            raise commands.BadArgument()
        mod_id = next(snowflake.create())
        new_mod = Modifier(mod_id, self.bot, ctx.guild.id, ctx.author.id,
                           location, kind)
        name = new_mod.name
        react_list = list(new_mod.react_list.values())
        embed = (await ModEmbed.from_mod(new_mod)).embed
        want = Want(ctx.bot, kind, ctx.guild.id)
        mention = await want.mention()
        if mention:
            reportcontent = mention + " - "
        else:
            reportcontent = ""
        coming = '🚗'
        despawned = '💨'
        report_channels = []
        report_channel = ReportChannel(ctx.bot, ctx.channel)
        if isinstance(location, Pokestop):
            loc_name = await location._name()
            loc_id = 'pokestop/' + str(location.id)
            channel_list = await location.get_all_channels('wild')
            report_channels.extend(channel_list)
        else:
            loc_name = location._name
            loc_id = f'{location.city}/{location.arg}'
        reportcontent += f'{name} reported at {loc_name}! Use {coming} if you are on the way and {despawned} if it has ended.'
        if report_channel not in report_channels:
            report_channels.append(report_channel)
        for channel in report_channels:
            try:
                reportmsg = await channel.channel.send(reportcontent,
                                                       embed=embed)
                for react in react_list:
                    if isinstance(react, int):
                        react = self.bot.get_emoji(react)
                    await reportmsg.add_reaction(react)
                new_mod.message_ids.append(
                    f"{reportmsg.channel.id}/{reportmsg.id}")
            except:
                continue
        for idstring in new_mod.message_ids:
            Modifier.by_message[idstring] = new_mod
        await new_mod.upsert()
        self.bot.loop.create_task(new_mod.monitor_status())
Example #9
0
    async def wild(self, ctx, pokemon: Pokemon, *, location: POI):
        """Report a wild Pokemon.

        **Arguments**
        *pokemon:* The name of the wild Pokemon plus additional
        information.
        *location:* The location of the wild spawn.

        If the *pokemon* argument is multiple words, wrap it in quotes.
        You may optionally supply additional information.
        If *location* is the name of a known Gym or Pokestop,
        directions will be accurate. Otherwise Meowth just Googles
        the supplied *location* plus the name of the city.
        
        **Example:** `!wild "female combee" city park`"""
        if not await pokemon._wild_available():
            raise
        weather = await location.weather()
        if weather == 'NO_WEATHER':
            weather = None
        pkmn = await pokemon.validate('wild', weather=weather)
        if pkmn.id == 'DITTO':
            disask = await ctx.send(
                'What Pokemon is this Ditto disguised as? Type your response below.'
            )

            def check(m):
                return m.channel == ctx.channel and m.author == ctx.author

            try:
                reply = await ctx.bot.wait_for('message', check=check)
                disguised = await Pokemon.convert(ctx, reply.content)
                await disask.delete()
                try:
                    await reply.delete()
                except:
                    pass
            except:
                disguised = None
        else:
            disguised = None
        wild_table = self.bot.dbi.table('wilds')
        wild_id = next(snowflake.create())
        new_wild = Wild(wild_id, self.bot, ctx.guild.id, ctx.author.id,
                        location, pkmn)
        react_list = list(new_wild.react_list.values())
        name = await pkmn.name()
        family = await pkmn._familyId()
        want = Want(ctx.bot, family, ctx.guild.id)
        mention = await want.mention()
        embed = (await WildEmbed.from_wild(new_wild)).embed
        if mention:
            reportcontent = mention + " - "
        else:
            reportcontent = ""
        coming = '🚗'
        caught_id = new_wild.react_list['caught']
        caught = ctx.bot.get_emoji(caught_id)
        despawned = '💨'
        report_channels = []
        report_channel = ReportChannel(ctx.bot, ctx.channel)
        if isinstance(location, POI):
            loc_name = await location._name()
            if isinstance(location, Gym):
                loc_id = 'gym/' + str(location.id)
            elif isinstance(location, Pokestop):
                loc_id = 'pokestop/' + str(location.id)
            channel_list = await location.get_all_channels('wild')
            report_channels.extend(channel_list)
        else:
            loc_name = location._name
            loc_id = f'{location.city}/{location.arg}'
        reportcontent += f'Wild {name} reported at {loc_name}! Use {coming} if you are on the way, {str(caught)} if you catch the Pokemon, and {despawned} if the Pokemon despawns.'
        if disguised:
            dis_name = await disguised.name()
            reportcontent += f'\nThis Ditto is disguised as a {dis_name}!'
        if report_channel not in report_channels:
            report_channels.append(report_channel)
        for channel in report_channels:
            try:
                reportmsg = await channel.channel.send(reportcontent,
                                                       embed=embed)
                for react in react_list:
                    if isinstance(react, int):
                        react = self.bot.get_emoji(react)
                    await reportmsg.add_reaction(react)
                new_wild.message_ids.append(
                    f"{reportmsg.channel.id}/{reportmsg.id}")
            except:
                continue
        d = {
            'id': wild_id,
            'guild': ctx.guild.id,
            'location': loc_id,
            'reporter_id': ctx.author.id,
            'pkmn': pkmn.id,
            'created': new_wild.created,
            'messages': new_wild.message_ids,
            'caught_by': []
        }
        for idstring in new_wild.message_ids:
            Wild.by_message[idstring] = new_wild
        insert = wild_table.insert()
        insert.row(**d)
        self.bot.loop.create_task(new_wild.monitor_status())
        await insert.commit()
Example #10
0
 async def research(self, ctx, reward: Optional[Union[Pokemon, ItemReward]], task: Optional[Task], *, location: Pokestop):
     """Report a Field Research task.
     
     **Arguments**
     *reward (optional):* Description of the reward for the research. Either
         a Pokemon or an item.
     *task (optional):* Either the text of the research task itself or
         the research category (e.g. `raid`). If a conversion to a Task cannot
         be made, Meowth asks you to select a category, then to select the
         specific task.
     *location:* Name of the Pokestop where the Field Research can be found.
     
     Meowth will automatically expire the research at midnight local time.
     The reporter will be awarded points for the number of users that obtain
     the task."""
     tz = await ctx.tz()
     if reward and not task:
         task_matches = await self.possible_tasks(reward.id)
         if len(task_matches) == 1:
             task = Task(ctx.bot, task_matches[0])
         elif len(task_matches) > 1:
             react_list = formatters.mc_emoji(len(task_matches))
             display_dict = dict(zip(react_list, task_matches))
             display_dict["\u2754"] = "Other"
             react_list.append("\u2754")
             embed = formatters.mc_embed(display_dict)
             multi = await ctx.send('Multiple possible Tasks found! Please select from the following list.',
                 embed=embed)
             payload = await formatters.ask(ctx.bot, [multi], user_list=[ctx.author.id],
                 react_list=react_list)
             if not payload:
                 try:
                     return await multi.delete()
                 except:
                     return
             task = display_dict[str(payload.emoji)]
             if task == 'Other':
                 otherask = await ctx.send('What is the Task for this Research? Please type your answer below.')
                 def check(m):
                     return m.author == ctx.author and m.channel == ctx.channel
                 reply = await ctx.bot.wait_for('message', check=check)
                 arg = reply.content
                 try:
                     await reply.delete()
                     await otherask.delete()
                 except:
                     pass
                 task = PartialTask(ctx.bot, arg)
             else:
                 task = Task(ctx.bot, task)
             try:
                 await multi.delete()
             except:
                 pass
     if not task:
         cats = await self.task_categories()
         content = "What category of Research Task is this? Select from the options below."
         react_list = formatters.mc_emoji(len(cats))
         cat_dict = dict(zip(react_list, cats))
         embed = formatters.mc_embed(cat_dict)
         multi = await ctx.send(content, embed=embed)
         payload = await formatters.ask(ctx.bot, [multi], user_list=[ctx.author.id], react_list=react_list)
         if not payload:
             try:
                 return await multi.delete()
             except:
                 return
         cat = cat_dict[str(payload.emoji)]
         try:
             await multi.delete()
         except:
             pass
         task = await Task.convert(ctx, cat, require_task=True)
     if isinstance(task, Task) and not reward:
         possible_rewards = await task.possible_rewards()
         if len(possible_rewards) == 1:
             reward = possible_rewards[0]
         else:
             react_list = formatters.mc_emoji(len(possible_rewards))
             item_dict = {}
             pkmn_dict = {}
             for reward in possible_rewards:
                 if '/' in reward:
                     obj = ItemReward(ctx.bot, reward)
                     desc = await obj.description()
                     item_dict[desc] = reward
                 else:
                     pkmn = Pokemon(ctx.bot, reward)
                     name = await pkmn.name()
                     pkmn_dict[name] = reward
             reward_dict = dict(pkmn_dict, **item_dict)
             if len(pkmn_dict) > 1:
                 react_list = formatters.mc_emoji(len(possible_rewards)+1)
                 reward_dict['Unknown Encounter'] = 'unknown_encounter'
             choice_dict = dict(zip(react_list, reward_dict.values()))
             display_dict = dict(zip(react_list, reward_dict.keys()))
             embed = formatters.mc_embed(display_dict)
             embed.fields[0].value = embed.fields[0].value + "\n<:silph:548259248442703895>Research tasks and rewards provided by [The Silph Road](https://thesilphroad.com/research-tasks)"
             multi = await ctx.send('What is the reward for this task? Please select from the options below.',
                 embed=embed)
             payload = await formatters.ask(ctx.bot, [multi], user_list=[ctx.author.id],
                 react_list=react_list)
             if not payload:
                 try:
                     return await multi.delete()
                 except:
                     return
             reward = choice_dict[str(payload.emoji)]
             try:
                 await multi.delete()
             except:
                 pass
     elif not reward:
         msg = await ctx.send('What is the reward for this Research? Please type your response below.')
         def check(m):
             return m.author == ctx.author and m.channel == ctx.channel
         reply = await ctx.bot.wait_for('message', check=check)
         try:
             reward = await Pokemon.convert(ctx, reply.content)
         except:
             reward = None
         if not reward:
             try:
                 reward = await ItemReward.convert(ctx, reply.content)
             except:
                 reward = ItemReward(ctx.bot, f'partial/{reply.content}/1')
         try:
             await reply.delete()
             await msg.delete()
         except:
             pass
     if not isinstance(reward, str):
         reward = reward.id
     research_id = next(snowflake.create())
     research = Research(research_id, ctx.bot, ctx.guild.id, ctx.author.id, task, location, reward, tz, time.time())
     embed = await ResearchEmbed.from_research(research)
     embed = embed.embed
     wants = await research.get_wants()
     mentions = [wants.get(x) for x in wants if wants.get(x)]
     mention_str = "\u200b".join(mentions)
     if mention_str:
         reportcontent = mention_str + " - "
     else:
         reportcontent = ""
     stamp = ctx.bot.get_emoji(583375171847585823)
     map_icon = ctx.bot.get_emoji(597185467217346602)
     reportcontent += f"Field Research reported! Use {str(stamp)} to indicate that you picked up this task!"
     report_channels = []
     report_channel = ReportChannel(ctx.bot, ctx.channel)
     msgs = []
     if isinstance(location, Pokestop):
         research_table = ctx.bot.dbi.table('research')
         query = research_table.query()
         query.where(location=str(location.id), guild_id=ctx.guild.id)
         old_research = await query.get()
         if old_research:
             return await ctx.send("There is already a research task reported at this pokéstop!", delete_after=20)
         channel_list = await location.get_all_channels('research')
         report_channels.extend(channel_list)
     if report_channel not in report_channels:
         report_channels.append(report_channel)
     stamp = ctx.bot.get_emoji(583375171847585823)
     for channel in report_channels:
         try:
             msg = await channel.channel.send(reportcontent, embed=embed)
             await msg.add_reaction("\U0001F4DD")  # Task emoji
             await msg.add_reaction(map_icon)
             await msg.add_reaction(stamp)
         except:
             continue
         idstring = f'{msg.channel.id}/{msg.id}'
         msgs.append(idstring)
         Research.by_message[idstring] = research
     research.message_ids = msgs
     await research.upsert()
     ctx.bot.loop.create_task(research.monitor_status())