Пример #1
0
 async def set_forty_role(self, ctx, role_id):
     role_id = utils.sanitize_name(role_id)
     try:
         role_id = int(role_id)
         role = discord.utils.get(ctx.guild.roles, id=role_id)
     except:
         role = discord.utils.get(ctx.guild.roles, name=role_id)
     if role is None:
         try:
             role = await ctx.guild.create_role(name=role_id,
                                                hoist=False,
                                                mentionable=True)
         except discord.errors.HTTPException:
             pass
         if role is None:
             await ctx.message.add_reaction(self.bot.failed_react)
             return await ctx.send(embed=discord.Embed(
                 colour=discord.Colour.red(),
                 description=
                 f"Unable to find or create role with name or id: **{role_id}**."
             ),
                                   delete_after=10)
         await ctx.send(embed=discord.Embed(
             colour=discord.Colour.from_rgb(255, 255, 0),
             description=f"Created new role: **{role.name}**"),
                        delete_after=10)
     quick_badge_dict = self.bot.guild_dict[ctx.guild.id]['configure_dict']\
         .get('quick_badge', self.quick_badge_dict_default)
     quick_badge_dict['40_role'] = role.id
     self.bot.guild_dict[
         ctx.guild.id]['configure_dict']['quick_badge'] = quick_badge_dict
     await ctx.channel.send(
         f'Level 40 auto-assign role set to **{role.name}**.',
         delete_after=10)
     return await ctx.message.add_reaction(self.bot.success_react)
Пример #2
0
async def update_raid_location(Kyogre, ctx, guild_dict, message,
                               report_channel, raid_channel, gym):
    guild = message.guild
    raid_dict = guild_dict[guild.id]['raidchannel_dict'][raid_channel.id]
    oldraidmsg = await raid_channel.fetch_message(raid_dict['raidmessage'])
    oldreportmsg = await report_channel.fetch_message(raid_dict['raidreport'])
    report_embed, raid_embed = await embed_utils.build_raid_embeds(
        Kyogre, ctx, raid_dict, True)
    regions = [gym.region]
    otw_list = []
    trainer_dict = copy.deepcopy(raid_dict['trainer_dict'])
    for trainer in trainer_dict.keys():
        if trainer_dict[trainer]['status']['coming']:
            user = guild.get_member(trainer)
            otw_list.append(user.mention)
    await raid_channel.send(
        content=f"Someone has suggested a different location for the raid! "
        f"Trainers {', '.join(otw_list)}: make sure you are headed to the right place!"
    )
    channel_name = raid_channel.name
    channel_prefix = channel_name.split("_")[0]
    new_channel_name = utils.sanitize_name(channel_prefix + "_" +
                                           gym.name)[:32]
    await raid_channel.edit(name=new_channel_name)
    try:
        message_content = get_raidtext(Kyogre, guild, raid_dict, raid_channel,
                                       False)
        await oldraidmsg.edit(new_content=message_content,
                              embed=raid_embed,
                              content=message_content)
    except:
        Kyogre.logger.info(
            f"Failed to update raid channel embed for raid at {gym.name}")
    try:
        content = build_raid_report_message(Kyogre, raid_channel, raid_dict)
        message_content = get_raidtext(Kyogre, guild, raid_dict, raid_channel,
                                       True)
        await oldreportmsg.edit(new_content=content,
                                embed=report_embed,
                                content=content)
        if raid_dict['raidcityreport'] is not None:
            report_city_channel = Kyogre.get_channel(raid_dict['reportcity'])
            report_city_msg = await report_city_channel.fetch_message(
                raid_dict['raidcityreport'])
            await report_city_msg.edit(new_content=message_content,
                                       embed=report_embed,
                                       content=message_content)
    except:
        Kyogre.logger.info(
            f"Failed to update report channel embed for raid at {gym.name}")
    raid_dict['raidmessage'] = oldraidmsg.id
    raid_dict['raidreport'] = oldreportmsg.id
    raid_dict['gym'] = gym.id
    raid_dict['address'] = gym.name
    raid_dict['regions'] = regions
    guild_dict[guild.id]['raidchannel_dict'][raid_channel.id] = raid_dict

    list_cog = Kyogre.cogs.get('ListManagement')
    await list_cog.update_listing_channels(guild, "raid", edit=True)
    return
Пример #3
0
 async def _set_hatch(self, ctx, *, new_datestr):
     new_date = parse(new_datestr)
     date_key = new_date.strftime("%b_%d").lower()
     start_time = new_date.strftime("%H:%M")
     hatch, expire = self._calculate_ex_start_time(date_key, start_time,
                                                   ctx.guild.id)
     channel = ctx.channel
     ex_raid = self.bot.guild_dict[channel.guild.id]['exchannel_dict'][
         channel.category_id]['channels'][channel.id]
     ex_raid['hatch'] = hatch
     ex_raid['expire'] = expire
     embed = await self._build_ex_embed(ctx, ex_raid)
     channel_message_id = ex_raid['channel_message']
     channel_message = await ctx.channel.fetch_message(channel_message_id)
     location_matching_cog = self.bot.cogs.get('LocationMatching')
     gym_id = ex_raid['gym']
     gym = location_matching_cog.get_gym_by_id(ctx.guild.id, gym_id)
     name = utils.sanitize_name(
         f"{start_time.lower().replace(':', '')} {gym.name}")[:36]
     await ctx.channel.edit(name=name)
     await channel_message.edit(embed=embed)
     offset = self.bot.guild_dict[
         ctx.guild.id]['configure_dict']['settings']['offset']
     offset *= (60 * 60)
     hatch = datetime.datetime.fromtimestamp(hatch + offset)
     new_hatch_str = datetime.datetime.fromtimestamp(
         hatch.timestamp()).strftime('%a %b %d %I:%M %p')
     await ctx.channel.send(
         f"The start time for this EX raid has been changed to **{new_hatch_str}**!"
     )
Пример #4
0
 async def _validate_or_create_role(self,
                                    ctx,
                                    role_id,
                                    eventname='',
                                    checkin=False):
     try:
         role_id = int(role_id)
         role = discord.utils.get(ctx.guild.roles, id=role_id)
     except:
         role = discord.utils.get(ctx.guild.roles, name=role_id)
     if role is None:
         try:
             if role_id.isdigit():
                 role_id = utils.sanitize_name(eventname)
             else:
                 role_id = utils.sanitize_name(role_id)
             role = await ctx.guild.create_role(name=role_id,
                                                hoist=False,
                                                mentionable=True)
         except discord.errors.HTTPException:
             pass
         if role is None:
             await ctx.message.add_reaction(self.failed_react)
             if checkin:
                 await ctx.send(embed=discord.Embed(
                     colour=discord.Colour.red(),
                     description=
                     f"Checkin failed, no role found with name: **{role_id}** and failed to create role."
                 ),
                                delete_after=10)
             else:
                 await ctx.send(embed=discord.Embed(
                     colour=discord.Colour.red(),
                     description=
                     f"No valid role found with name or id: **{role_id}**. Failed to create role with that name."
                 ),
                                delete_after=10)
             return None
         await ctx.invoke(self.bot.get_command('event updaterole'),
                          info=f"{eventname}, {role.name}")
         await ctx.send(embed=discord.Embed(
             colour=discord.Colour.from_rgb(255, 255, 0),
             description=f"Created new role: **{role.name}**"),
                        delete_after=10)
     return role
Пример #5
0
 async def _short_output(self, ctx, *, info):
     guild = ctx.guild
     info = re.split(r',*\s+', info)
     if len(info) < 2:
         await ctx.message.add_reaction(self.bot.failed_react)
         return await ctx.send(
             "Please provide both a region name and a channel name or id.",
             delete_after=15)
     region = info[0].lower()
     channel_info = ' '.join(info[1:]).lower()
     region_names = self.bot.guild_dict[guild.id]['configure_dict'].get(
         'regions', {}).get('info', None)
     if not region_names:
         await ctx.message.add_reaction(self.bot.failed_react)
         return await ctx.send(
             "No regions have been configured for this server.",
             delete_after=15)
     if region not in region_names.keys():
         await ctx.message.add_reaction(self.bot.failed_react)
         return await ctx.send(
             f"No region with name: **{region}** found in this server's configuration.",
             delete_after=15)
     if channel_info == "none":
         self.bot.guild_dict[guild.id]['configure_dict']['raid'].setdefault(
             'short_output', {})[region] = None
         msg = f"Short output channel removed for **{region}**."
     else:
         channel = None
         name = utils.sanitize_name(channel_info)
         # If a channel mention is passed, it won't be recognized as an int but this for get will succeed
         try:
             channel = discord.utils.get(guild.text_channels, id=int(name))
         except ValueError:
             pass
         if not channel:
             channel = discord.utils.get(guild.text_channels, name=name)
         if not channel:
             await ctx.message.add_reaction(self.bot.failed_react)
             return await ctx.send(
                 f"No channel with name or id: **{channel_info}** "
                 f"found in this server's channel list.",
                 delete_after=15)
         self.bot.guild_dict[guild.id]['configure_dict']['raid'].setdefault(
             'short_output', {})[region] = channel.id
         msg = f"Short output channel for **{region}** set to **{channel.mention}**"
     await ctx.message.add_reaction(self.bot.success_react)
     return await ctx.send(msg, delete_after=15)
Пример #6
0
 async def get_channel_by_name_or_id(ctx, name):
     channel = None
     # If a channel mention is passed, it won't be recognized as an int but this get will succeed
     name = utils.sanitize_name(name)
     try:
         channel = discord.utils.get(ctx.guild.text_channels, id=int(name))
     except ValueError:
         pass
     if not channel:
         channel = discord.utils.get(ctx.guild.text_channels, name=name)
     if channel:
         guild_channel_list = []
         for textchannel in ctx.guild.text_channels:
             guild_channel_list.append(textchannel.id)
         diff = set([channel.id]) - set(guild_channel_list)
     else:
         diff = True
     if diff:
         return None
     return channel
Пример #7
0
 async def _send_pvp_notification_async(self, ctx):
     message = ctx.message
     channel = message.channel
     guild = message.guild
     trainer = guild.get_member(message.author.id)
     trainer_info_dict = self.bot.guild_dict[
         guild.id]['trainers'].setdefault('info', {})
     friends = trainer_info_dict.setdefault(message.author.id,
                                            {}).setdefault('friends', [])
     outbound_dict = {}
     tag_msg = f'**{trainer.display_name}** wants to battle! Who will challenge them?!'
     for friend in friends:
         friend = guild.get_member(friend)
         outbound_dict[friend.id] = {
             'discord_obj': friend,
             'message': tag_msg
         }
     role_name = utils.sanitize_name(f"pvp {trainer.name}")
     subscriptions_cog = self.bot.cogs.get('Subscriptions')
     if not subscriptions_cog:
         return None
     return await subscriptions_cog.generate_role_notification_async(
         role_name, channel, outbound_dict)
Пример #8
0
 async def _create_ex_channel(self, ctx, gym, start_time, cat):
     channel_overwrite_dict = ctx.channel.overwrites
     kyogre_overwrite = {
         self.bot.user:
         discord.PermissionOverwrite(send_messages=True,
                                     read_messages=True,
                                     manage_roles=True,
                                     manage_channels=True,
                                     manage_messages=True,
                                     add_reactions=True,
                                     external_emojis=True,
                                     read_message_history=True,
                                     embed_links=True,
                                     mention_everyone=True,
                                     attach_files=True)
     }
     channel_overwrite_dict.update(kyogre_overwrite)
     name = start_time.lower().replace(':',
                                       '').replace('am',
                                                   '').replace('pm', '')
     name = utils.sanitize_name(f"{name} {gym.name}")[:36]
     return await ctx.guild.create_text_channel(
         name, overwrites=channel_overwrite_dict, category=cat)
Пример #9
0
async def update_raid_location(Kyogre, guild_dict, message, report_channel,
                               raid_channel, gym):
    guild = message.guild
    raid_dict = guild_dict[guild.id]['raidchannel_dict'][raid_channel.id]
    oldraidmsg = await raid_channel.fetch_message(raid_dict['raidmessage'])
    oldreportmsg = await report_channel.fetch_message(raid_dict['raidreport'])
    oldembed = oldraidmsg.embeds[0]
    newloc = gym.maps_url
    regions = [gym.region]
    new_embed = discord.Embed(title=oldembed.title,
                              url=newloc,
                              colour=guild.me.colour)
    for field in oldembed.fields:
        t = 'team'
        s = 'status'
        if (t not in field.name.lower()) and (s not in field.name.lower()):
            new_embed.add_field(name=field.name,
                                value=field.value,
                                inline=field.inline)
    weather = raid_dict.get('weather', None)
    utils_cog = Kyogre.cogs.get('Utilities')
    enabled = utils_cog.raid_channels_enabled(guild, raid_channel)
    if enabled:
        embed_indices = await embed_utils.get_embed_field_indices(new_embed)
        gym_embed = new_embed.fields[embed_indices['gym']]
        gym_info = "**Name:** {0}\n**Notes:** {1}".format(
            gym.name, "_EX Eligible Gym_" if gym.ex_eligible else "N/A")
        if weather is not None:
            gym_info += "\n**Weather**: " + weather
        new_embed.set_field_at(embed_indices['gym'],
                               name=gym_embed.name,
                               value=gym_info,
                               inline=True)
        new_embed.set_footer(text=oldembed.footer.text,
                             icon_url=oldembed.footer.icon_url)
        new_embed.set_thumbnail(url=oldembed.thumbnail.url)
    otw_list = []
    trainer_dict = copy.deepcopy(raid_dict['trainer_dict'])
    for trainer in trainer_dict.keys():
        if trainer_dict[trainer]['status']['coming']:
            user = guild.get_member(trainer)
            otw_list.append(user.mention)
    await raid_channel.send(
        content=
        'Someone has suggested a different location for the raid! Trainers {trainer_list}: make sure you are headed to the right place!'
        .format(trainer_list=', '.join(otw_list)))
    channel_name = raid_channel.name
    channel_prefix = channel_name.split("_")[0]
    new_channel_name = utils.sanitize_name(channel_prefix + "_" +
                                           gym.name)[:32]
    await raid_channel.edit(name=new_channel_name)
    try:
        message_content = get_raidtext(Kyogre, guild, guild_dict, raid_dict,
                                       gym, report_channel, raid_channel,
                                       False)
        await oldraidmsg.edit(new_content=message_content,
                              embed=new_embed,
                              content=message_content)
    except:
        pass
    try:
        if enabled:
            embed_indices = await embed_utils.get_embed_field_indices(new_embed
                                                                      )
            new_embed = await embed_utils.filter_fields_for_report_embed(
                new_embed, embed_indices, enabled)
            message_content = get_raidtext(Kyogre, guild, guild_dict,
                                           raid_dict, gym, report_channel,
                                           raid_channel, True)
            await oldreportmsg.edit(new_content=message_content,
                                    embed=new_embed,
                                    content=message_content)
            if raid_dict['raidcityreport'] is not None:
                report_city_channel = Kyogre.get_channel(
                    raid_dict['reportcity'])
                report_city_msg = await report_city_channel.fetch_message(
                    raid_dict['raidcityreport'])
                await report_city_msg.edit(new_content=message_content,
                                           embed=new_embed,
                                           content=message_content)
    except:
        pass
    raid_dict['raidmessage'] = oldraidmsg.id
    raid_dict['raidreport'] = oldreportmsg.id
    raid_dict['gym'] = gym.id
    raid_dict['address'] = gym.name
    raid_dict['regions'] = regions
    guild_dict[guild.id]['raidchannel_dict'][raid_channel.id] = raid_dict

    list_cog = Kyogre.cogs.get('ListManagement')
    await list_cog.update_listing_channels(guild, "raid", edit=True)
    return
Пример #10
0
 async def send_notifications_async(self,
                                    notification_type,
                                    details,
                                    new_channel,
                                    exclusions=[]):
     valid_types = [
         'raid', 'research', 'wild', 'nest', 'gym', 'shiny', 'item', 'lure',
         'hideout'
     ]
     if notification_type not in valid_types:
         return
     guild = new_channel.guild
     # get trainers
     try:
         results = (SubscriptionTable.select(
             SubscriptionTable.trainer, SubscriptionTable.target,
             SubscriptionTable.specific).join(
                 TrainerTable,
                 on=(SubscriptionTable.trainer == TrainerTable.snowflake
                     )).where((SubscriptionTable.type == notification_type)
                              | (SubscriptionTable.type == 'pokemon')
                              | (SubscriptionTable.type == 'gym')).
                    where(TrainerTable.guild == guild.id).where(
                        SubscriptionTable.guild_id == guild.id)).execute()
     except:
         return
     # group targets by trainer
     trainers = set([s.trainer for s in results])
     target_dict = {
         t: {s.target: s.specific
             for s in results if s.trainer == t}
         for t in trainers
     }
     regions = set(details.get('regions', []))
     ex_eligible = details.get('ex-eligible', None)
     tier = details.get('tier', None)
     perfect = details.get('perfect', None)
     pokemon_list = details.get('pokemon', [])
     gym = details.get('location', None)
     item = details.get('item', None)
     lure_type = details.get('lure_type', None)
     if not isinstance(pokemon_list, list):
         pokemon_list = [pokemon_list]
     location = details.get('location', None)
     multi = details.get('multi', False)
     region_dict = self.bot.guild_dict[guild.id]['configure_dict'].get(
         'regions', None)
     outbound_dict = {}
     # build final dict
     for trainer in target_dict:
         user = guild.get_member(trainer)
         if trainer in exclusions or not user:
             continue
         if region_dict and region_dict.get('enabled', False):
             matched_regions = [
                 n for n, o in region_dict.get('info', {}).items()
                 if o['role'] in [r.name for r in user.roles]
             ]
             if regions and regions.isdisjoint(matched_regions):
                 continue
         targets = target_dict[trainer]
         descriptors = []
         target_matched = False
         if 'ex-eligible' in targets and ex_eligible:
             target_matched = True
             descriptors.append('ex-eligible')
         if tier and str(tier) in targets:
             tier = str(tier)
             if targets[tier]:
                 try:
                     current_gym_ids = targets[tier].strip('[').strip(']')
                     split_id_string = current_gym_ids.split(', ')
                     split_ids = []
                     for s in split_id_string:
                         try:
                             split_ids.append(int(s))
                         except ValueError:
                             pass
                     target_gyms = (GymTable.select(
                         LocationTable.id, LocationTable.name,
                         LocationTable.latitude, LocationTable.longitude,
                         RegionTable.name.alias('region'),
                         GymTable.ex_eligible,
                         LocationNoteTable.note).join(LocationTable).join(
                             LocationRegionRelation).join(RegionTable).join(
                                 LocationNoteTable,
                                 JOIN.LEFT_OUTER,
                                 on=(LocationNoteTable.location_id ==
                                     LocationTable.id)
                             ).where((LocationTable.guild == guild.id) & (
                                 LocationTable.guild == RegionTable.guild)
                                     & (LocationTable.id << split_ids)))
                     target_gyms = target_gyms.objects(Gym)
                     found_gym_names = [r.name for r in target_gyms]
                     if gym in found_gym_names:
                         target_matched = True
                 except:
                     pass
             else:
                 target_matched = True
             descriptors.append(
                 'level {level}'.format(level=details['tier']))
         pkmn_adj = ''
         if perfect and 'perfect' in targets:
             target_matched = True
             pkmn_adj = 'perfect '
         for pokemon in pokemon_list:
             if pokemon.name in targets:
                 target_matched = True
             full_name = pkmn_adj + pokemon.name
             descriptors.append(full_name)
         if gym in targets:
             target_matched = True
         if item and item.lower() in targets:
             target_matched = True
         if 'shiny' in targets:
             target_matched = True
         if 'takeover' in targets or (lure_type and lure_type in targets):
             trainer_info = self.bot.guild_dict[
                 guild.id]['trainers'].setdefault('info', {}).setdefault(
                     trainer, {})
             t_location = trainer_info.setdefault('location', None)
             distance = trainer_info.setdefault('distance', None)
             stop = details['location']
             if t_location is not None and distance is not None:
                 if self.close_enough(
                     (float(stop.latitude), float(stop.longitude)),
                     (t_location[0], t_location[1]), distance):
                     target_matched = True
                 else:
                     target_matched = False
             else:
                 target_matched = True
         if not target_matched:
             continue
         description = ', '.join(descriptors)
         start = 'An' if re.match(r'^[aeiou]', description, re.I) else 'A'
         if notification_type == 'item':
             start = 'An' if re.match(r'^[aeiou]', item, re.I) else 'A'
             if multi:
                 location = 'multiple locations'
             message = f'{start} **{item} research task** has been reported at **{location}**!'
         elif notification_type == 'lure':
             message = f'A **{lure_type.capitalize()}** lure has been dropped at {location.name}!'
         elif notification_type == 'hideout':
             message = f'A **Team Rocket Hideout** has been spotted at {location.name}!'
         elif notification_type == 'wild':
             message = f'A **wild {description} spawn** has been reported at **{location}**!'
         elif notification_type == 'research':
             if multi:
                 location = 'multiple locations'
             message = f'{start} **{description} research task** has been reported at **{location}**!'
         elif 'hatching' in details and details['hatching']:
             message = f"The egg at **{location}** has hatched into {start.lower()} **{description}** raid!"
         else:
             message = f'{start} {description} {notification_type} at {location} has been reported!'
         outbound_dict[trainer] = {'discord_obj': user, 'message': message}
     pokemon_names = ' '.join([p.name for p in pokemon_list])
     if notification_type == 'item':
         role_name = utils.sanitize_name(f"{item} {location}".title())
     elif notification_type == 'lure':
         role_name = utils.sanitize_name(
             f'{lure_type} {location.name}'.title())
     elif notification_type == 'hideout':
         role_name = utils.sanitize_name(
             f'Rocket Hideout {location.name}'.title())
     else:
         role_name = utils.sanitize_name(
             f"{notification_type} {pokemon_names} {location}".title())
     # starting to hit rate limit for role creation so explicitly mentioning all trainers in the meantime
     await self.notify_all_async(new_channel, outbound_dict)
     faves_cog = self.bot.cogs.get('Faves')
     return faves_cog.get_report_points(guild.id, pokemon_list,
                                        notification_type)