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)
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_()
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)
async def showmap(self, ctx): report_channel = ReportChannel(self.bot, ctx.channel) rc_map = ReportChannelMap(report_channel) await ctx.send(rc_map.url)
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())
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)
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)
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())
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()
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())