示例#1
0
    async def _sub_adminlist(self, ctx, *, trainer=None):
        """**Usage**: `!sub adminlist/alist <member>`
        Receive a list of all current subscriptions the provided member has"""
        message = ctx.message
        channel = message.channel
        author = message.author

        if not trainer:
            response_msg = "Please provide a trainer name or id"
            response = await channel.send(response_msg)
            return await utils.sleep_and_cleanup([message, response], 10)

        if trainer.isdigit():
            trainerid = trainer
        else:
            converter = commands.MemberConverter()
            try:
                trainer_member = await converter.convert(ctx, trainer)
                trainerid = trainer_member.id
            except:
                response_msg = f"Could not process trainer with name: {trainer}"
                await channel.send(response_msg)
                return await utils.sleep_and_cleanup([message, response_msg],
                                                     10)
        try:
            results = (SubscriptionTable.select(
                SubscriptionTable.type, SubscriptionTable.target).join(
                    TrainerTable,
                    on=(SubscriptionTable.trainer == TrainerTable.snowflake
                        )).where(SubscriptionTable.trainer == trainerid).where(
                            TrainerTable.guild == ctx.guild.id).where(
                                SubscriptionTable.guild_id == ctx.guild.id))

            results = results.execute()
            subscription_msg = ''
            types = set([s.type for s in results])
            subscriptions = {
                t: [s.target for s in results if s.type == t]
                for t in types
            }

            for sub in subscriptions:
                subscription_msg += '**{category}**:\n\t{subs}\n\n'.format(
                    category=sub.title(), subs='\n\t'.join(subscriptions[sub]))
            if len(subscription_msg) > 0:
                listmsg = "Listing subscriptions for user:  {id}\n".format(
                    id=trainer)
                listmsg += 'Current subscriptions are:\n\n{subscriptions}'.format(
                    subscriptions=subscription_msg)
                await message.add_reaction(self.success_react)
                await author.send(listmsg)
            else:
                none_msg = await channel.send(
                    f"No subscriptions found for user: {trainer}")
                await message.add_reaction(self.success_react)
                return await utils.sleep_and_cleanup([none_msg], 10)
        except:
            response_msg = f"Encountered an error while looking up subscriptions for trainer with name: {trainer}"
            await channel.send(response_msg)
            return await utils.sleep_and_cleanup([response_msg, message], 10)
示例#2
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)
示例#3
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)
示例#4
0
    def _generate_sub_list_message(ctx, types):
        message = ctx.message
        guild = message.guild
        results = (SubscriptionTable.select(
            SubscriptionTable.type, SubscriptionTable.target,
            SubscriptionTable.specific).join(
                TrainerTable,
                on=(SubscriptionTable.trainer == TrainerTable.snowflake
                    )).where(SubscriptionTable.trainer == ctx.author.id).where(
                        TrainerTable.guild == ctx.guild.id).where(
                            SubscriptionTable.guild_id == ctx.guild.id))
        if len(types) > 0:
            results = results.where(SubscriptionTable.type << types)
        results = results.execute()

        types = set([s.type for s in results])
        for r in results:
            if r.specific:
                current_gym_ids = r.specific.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

                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)))
                result = gyms.objects(Gym)
                r.specific = ",\n\t".join([o.name for o in result])
        subscriptions = {}
        for t in types:
            if t == 'gym':
                for r in results:
                    if r.type == 'gym':
                        if r.specific:
                            subscriptions[
                                f"Level {r.target} Raids at"] = r.specific
                        else:
                            msg = subscriptions.get('gym', "")
                            if len(msg) < 1:
                                msg = r.target
                            else:
                                msg += f', {r.target}'
                            subscriptions['gym'] = msg

            else:
                subscriptions[t] = [
                    s.target for s in results if s.type == t and t != 'gym'
                ]
        listmsg_list = []
        subscription_msg = ""
        sep = '\n\t'
        for sub in subscriptions.keys():
            if not isinstance(subscriptions[sub], list):
                subscriptions[sub] = [subscriptions[sub]]
            new_msg = f"**Subscription type - {sub.title()}**:\n\t{sep.join(subscriptions[sub])}\n\n"
            if len(subscription_msg) + len(
                    new_msg) < constants.MAX_MESSAGE_LENGTH:
                subscription_msg += new_msg
            else:
                listmsg_list.append(subscription_msg)
                subscription_msg = new_msg
        listmsg_list.append(subscription_msg)
        return listmsg_list
示例#5
0
    async def _sub_add(self, ctx, *, content=None):
        """Create a subscription

        **Usage**: `!sub add <type> <target>`
        Kyogre will send you a notification if an event is generated
        matching the details of your subscription.
        
        **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
        error_list = []

        if content is None:
            return await self._guided_subscription(ctx, 'Add')
        content = content.strip().lower()
        if content == 'shiny':
            candidate_list = [('shiny', '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)

            candidate_list, error_list = await self._parse_subscription_content(
                content, 'add', message)

        existing_list = []
        sub_list = []

        # don't remove. this makes sure the guild and trainer are in the db
        guild_obj, __ = GuildTable.get_or_create(snowflake=guild.id)
        trainer_obj, __ = TrainerTable.get_or_create(snowflake=trainer,
                                                     guild=guild.id)
        if guild_obj is None or trainer_obj is None:
            pass
        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=s_type,
                        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
                    spec = [int(s) for s in spec]
                    new_ids = set(split_ids + spec)
                    result.specific = list(new_ids)
                    if len(result.specific) > 0:
                        result.save()
                        sub_list.append(s_entry)
                except:
                    error_list.append(s_entry)
            else:
                try:
                    SubscriptionTable.create(guild_id=ctx.guild.id,
                                             trainer=trainer,
                                             type=s_type,
                                             target=s_target)
                    sub_list.append(s_entry)
                except IntegrityError:
                    existing_list.append(s_entry)
                except:
                    error_list.append(s_entry)

        sub_count = len(sub_list)
        existing_count = len(existing_list)
        error_count = len(error_list)

        confirmation_msg = f'{ctx.author.mention}, successfully added {sub_count} new {s_type} subscriptions'
        if sub_count > 0:
            confirmation_msg += '\n**{sub_count} Added:** \n\t{sub_list}'.format(
                sub_count=sub_count, sub_list=',\n\t'.join(sub_list))
        if existing_count > 0:
            confirmation_msg += '\n**{existing_count} Already Existing:** \n\t{existing_list}'\
                .format(existing_count=existing_count, existing_list=', '.join(existing_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)