示例#1
0
    async def unsubscribe(self, channel: int, world: str, subscription: str):
        """
        Unsubscribe a channel from hunt events
        """
        world = world.strip().lower().title()
        if world not in self.WORLDS:
            await self.bot.get_channel(channel).send(
                "No world by that name found on the Crystal DC - please check your spelling and try again"
            )
            return

        try:
            sub = getattr(self, f"""SUB_{subscription.upper()}""")
        except AttributeError:
            await self.bot.get_channel(channel).send(
                "Invalid subscription provided, valid subscriptions are: sb_a, sb_s, hw_a, hw_s, arr_a, arr_s"
            )
            return

        Subscriptions.delete().where(
                (Subscriptions.channel_id == channel)
                & (Subscriptions.world == world)
                & (Subscriptions.category == sub)
        ).execute()

        await self.bot.get_channel(channel).send(f"""Unsubscribed channel from {str(sub).replace('_', ' ').title()}-Rank hunts on {world}""")
        self._reload()
示例#2
0
 async def clear_subscriptions(self, channel: int) -> None:
     """
     Clear all subscriptions for the specified channel
     """
     Subscriptions.delete().where(
         Subscriptions.channel_id == channel).execute()
     self._reload()
示例#3
0
    async def subscribe(self,
                        channel: int,
                        world: str,
                        subscription: str,
                        conditions: typing.Optional[str] = 'all'):
        """
        Subscribe a channel to hunt events
        """
        # Validate world
        world = world.strip().lower().title()
        if world not in Worlds.get_worlds():
            await self.bot.get_channel(channel).send(
                "No world by that name found - please check your spelling and try again"
            )
            return

        # Validate subscription channel
        try:
            sub = getattr(self, f"""SUB_{subscription.upper()}""")
        except AttributeError:
            await self.bot.get_channel(channel).send(
                "Invalid subscription provided, valid subscriptions are: shb_a, shb_s, sb_a, sb_s, hw_a, hw_s, arr_a, arr_s"
            )
            return

        # Validate conditions
        if conditions == 'all':
            conditions = list(self.CONDITIONS)
        else:
            conditions = conditions.replace(' ', '').lower().split(',')
            _invalid_conditions = set(conditions) - set(self.CONDITIONS)
            if _invalid_conditions:
                await self.bot.get_channel(channel).send(
                    "Invalid conditions supplied: " + str(_invalid_conditions))
                return

        # Already subscribed?
        if Subscriptions.select().where(
            (Subscriptions.channel_id == channel)
                & (Subscriptions.world == world)
                & (Subscriptions.category == sub)).count():
            await self.bot.get_channel(channel).send(
                "This channel is already subscribed to this feed. If you want unsubscribe, use the unsub command"
            )
            return

        for condition in conditions:
            Subscriptions.insert({
                'channel_id': channel,
                'world': world,
                'category': sub,
                'event': condition
            }).execute()

        await self.bot.get_channel(channel).send(
            f"""Subscribed channel to {str(sub).replace('_', ' ').title()}-Rank hunts on {world}"""
        )
        self._reload()
示例#4
0
 async def _send_sub_message(self, message, embed: discord.Embed, sub: Subscriptions) -> typing.Optional[discord.Message]:
     """
     Attempt to send a subscription message
     """
     try:
         return await self.bot.get_channel(sub.channel_id).send(message, embed=embed)
     except AttributeError:
         self._log.warning(f"Subscription channel is no longer active; removing channel {sub.channel_id}")
         Subscriptions.delete().where(Subscriptions.channel_id == sub.channel_id).execute()
     except discord.errors.Forbidden:
         self._log.warning(f"No permission to send to channel {sub.channel_id}")
示例#5
0
    async def subscribe_all(self,
                            datacenter: str,
                            channel: int,
                            subscription: str,
                            conditions: typing.Optional[str] = 'all'):
        """
        Subscribe a channel to hunt events on all worlds
        """
        # Validate subscription channel
        try:
            sub = getattr(self, f"""SUB_{subscription.upper()}""")
        except AttributeError:
            await self.bot.get_channel(channel).send(
                "Invalid subscription provided, valid subscriptions are: sb_a, sb_s, hw_a, hw_s, arr_a, arr_s"
            )
            return

        # Validate conditions
        if conditions == 'all':
            conditions = list(self.CONDITIONS)
        else:
            conditions = conditions.replace(' ', '').lower().split(',')
            _invalid_conditions = set(conditions) - set(self.CONDITIONS)
            if _invalid_conditions:
                await self.bot.get_channel(channel).send(
                    "Invalid conditions supplied: " + str(_invalid_conditions))
                return

        # Validate datacenter
        datacenter = datacenter.strip().lower().title()
        if datacenter not in Worlds.get_datacenters():
            await self.bot.get_channel(channel).send(
                f"Invalid datacenter provided, valid datacenters are: {', '.join(Worlds.get_datacenters())}"
            )
            return

        for world in Worlds.get_datacenter_worlds(datacenter):
            # Already subscribed? Overwrite it
            Subscriptions.delete().where((Subscriptions.channel_id == channel)
                                         & (Subscriptions.world == world)
                                         & (Subscriptions.category == sub))

            for condition in conditions:
                Subscriptions.insert({
                    'channel_id': channel,
                    'world': world,
                    'category': sub,
                    'event': condition
                }).execute()

        await self.bot.get_channel(channel).send(
            f"""Subscribed channel to {str(sub).replace('_', ' ').title()}-Rank hunts on **all worlds**"""
        )
        self._reload()
示例#6
0
    async def on_find(self, world: str, name: str, xivhunt: dict, instance=1):
        """
        Hunt found event handler
        """
        if world not in self._hunts:
            self._hunts[world] = {'horus': {}, 'xivhunt': []}

        _key = f"{name.strip().lower()}_{instance}"
        if _key in self._hunts[world]['xivhunt']:
            self._log.debug(f"Hunt {name} on instance {instance} already logged")
            return

        hunt = self._marks_info[name.lower()]
        if hunt['Rank'] not in ('A', 'S'):
            self._log.debug(f"""Ignoring notifications for {hunt['Rank']} rank hunts""")
            return

        print(f"A hunt has been found on world {world} (Instance {instance}) :: {name}, Rank {xivhunt['rank']}")

        subs = Subscriptions.select().where(
                (Subscriptions.world == world)
                & (Subscriptions.category == hunt['Channel'])
        )
        embed = hunt_embed(name, xivhunt=xivhunt)

        for sub in subs:  # type: Subscriptions
            if self.COND_FIND != sub.event:
                continue

            _meta = SubscriptionsMeta.select().where(SubscriptionsMeta.channel_id == sub.channel_id)
            meta  = {m.name : m.value for m in _meta}
            role_mention = meta['notifier'] if 'notifier' in meta else None

            content = f"""A hunt has been found on **{world}** (**Instance {instance}**)!"""
            if role_mention:
                content = f"""{role_mention} {content}"""

            message = await self._send_sub_message(content, embed, sub)
            if not message:
                continue

            await self.log_notification(message, sub.channel_id, world, name, instance)

            # Relay counter
            _counter_key = f"""{hunt['Rank'].lower()}_count"""
            if _counter_key not in meta:
                SubscriptionsMeta.insert({
                    'channel_id'    : sub.channel_id,
                    'name'          : _counter_key,
                    'value'         : 1
                }).execute()
            else:
                SubscriptionsMeta.update({
                    'value'         : int(meta[_counter_key]) + 1
                }).where(
                    (SubscriptionsMeta.channel_id == sub.channel_id)
                    & (SubscriptionsMeta.name == _counter_key)
                ).execute()

        self._hunts[world]['xivhunt'].append(_key)
示例#7
0
 async def get_subscriptions(self,
                             channel: int) -> typing.List[Subscriptions]:
     """
     Get all subscriptions for the specified channel
     """
     return list(
         Subscriptions.select().where(Subscriptions.channel_id == channel))
示例#8
0
    async def on_change(self, world: str, old: HorusHunt, new: HorusHunt):
        """
        Hunt status change event handler
        """
        hunt = self._marks_info[old.name.lower()]
        subs = Subscriptions.select().where(
                (Subscriptions.world == world)
                & (Subscriptions.category == hunt['Channel'])
        )
        embed = hunt_embed(new.name, new)

        for sub in subs:  # type: Subscriptions
            if new.status == new.STATUS_OPENED and self.COND_OPEN == sub.event:
                await self._send_sub_message(f"A hunt has opened on **{world}** (**Instance {new.instance}**)!", embed, sub)
                break

            if new.status == new.STATUS_MAXED and self.COND_OPEN == sub.event:
                await self._send_sub_message(f"A hunts maximum spawn window has been reached on **{world}** (**Instance {new.instance}**)!", embed, sub)
                break

            if new.status == new.STATUS_DIED and self.COND_DEAD == sub.event:
                # If we previously sent a notification that the hunt was found, edit that message instead of
                # sending a new one
                notification = await self.get_notification(sub.channel_id, world, new.name, new.instance)
                if notification:
                    notification, log = notification
                    found   = int(notification.created_at.timestamp())
                    killed  = arrow.get(int(new.last_mark / 1000)).timestamp
                    seconds = killed - log.found

                    kill_time = []
                    if seconds > 120:
                        kill_time.append(f"""{int(seconds / 60)} minutes""")
                        seconds -= int(seconds / 60) * 60
                    elif seconds > 60:
                        kill_time.append(f"""1 minute""")
                        seconds -= 60
                    kill_time.append(f"""{int(seconds)} seconds""")

                    log.killed = killed
                    log.kill_time = seconds
                    log.save()

                    try:
                        await notification.edit(content=f"""A scouted hunt has died on **{world}** (**Instance {new.instance}**) after **{', '.join(kill_time)}**!""", embed=embed)
                        continue
                    except discord.NotFound:
                        self._log.warning(f"Notification message for hunt {new.name} on world {world} has been deleted")

                await self._send_sub_message(f"A hunt has died on **{world}** (**Instance {new.instance}**)!", embed, sub)

            _key = f"{new.name.strip().lower()}_{new.instance}"
            if _key in self._hunts[world]['xivhunt']:
                self._hunts[world]['xivhunt'].remove(_key)
示例#9
0
    def __init__(self, bot: Bot):
        self._log = logging.getLogger(__name__)
        self.bot = bot

        self.xivhunt = XivHunt(bot)
        self.horus = Horus(bot)

        self._subscriptions = list(Subscriptions.select())
        self._subscriptions_meta = list(SubscriptionsMeta.select())

        self._marks_info = {}
        self._load_marks()

        self._hunts = {}
        self._changed = {}
        self._found = {}

        # Callbacks
        self._recheck_cbs = []

        # Logged notifications for editing later
        self._notifications = {}
示例#10
0
 def _reload(self):
     """
     Save configuration changes
     """
     self._subscriptions = list(Subscriptions.select())
     self._subscriptions_meta = list(SubscriptionsMeta.select())