示例#1
0
    def load(self, ctx):
        super(UtilityCommands, self).load(ctx)

        with open("league_api/data/version.json") as data_file:
            data = json.load(data_file)

        self.version = data["version"]
        self.guild_list = dict()
        self.league_helper = LeagueHelper()
示例#2
0
 def on_cm_graph(self, event, summoner_name=None, region=None):
     """Displays a graph of the summoners top 5 champions by mastery"""
     region = LeagueHelper.validate_region(region, event)
     if region:
         cm_graph = ChampionMasteryGraph(self.league_helper.watcher, region,
                                         LeagueHelper.get_champion_data())
         if summoner_name is not None:
             filepath = "cm-" + summoner_name + ".png"
         else:
             filepath = "cm-default.png"
         self._graph_renderer(event, cm_graph, summoner_name, region,
                              filepath)
示例#3
0
    def on_live_game(self, event, summoner_name=None, region=None):
        '''Displays the live game info if a summoner is in a game. Supports all game types and ranked modes'''

        # Prevent command quit on no region given if the discord user has bound a summoner to there account
        if region is None and summoner_name is None and LiveDataHelper.user_is_bound(
                LiveDataHelper.load_summoner_binds(), str(
                    event.msg.author.id)):
            region = LiveDataHelper.get_user_bound_region(
                str(event.msg.author.id))

        region = LeagueHelper.validate_region(region, event)
        if region is None:
            return

        summoner = self.league_helper.user_exists(region, summoner_name, event,
                                                  event.msg.author.id)

        if summoner:
            spectate_info = self.league_helper.user_in_game(
                region, summoner["id"])
            if spectate_info:
                game_info = GameInfo(self.league_helper)
                game_info.display_live_game(event.msg.channel, region,
                                            spectate_info)
            else:
                event.msg.reply("This summoner `" + summoner["name"] + " " +
                                region + "` is not currently in a game!")
示例#4
0
    def on_patch(self, event, version=None):
        '''Displays the latest patch notes for League of Legends'''
        s = "."
        if not version:
            version = s.join(LeagueHelper.get_champion_data()["version"].split(
                ".", 2)[:2])

        version_url = version.replace(".", "")
        patch_url = "http://na.leagueoflegends.com/en/news/game-updates/patch/patch-" + version_url + "-notes"
        version_url = "http://ddragon.leagueoflegends.com/api/versions.json"

        with urllib.request.urlopen(version_url) as url:
            raw_json = json.loads(url.read().decode())

        versionExists = False
        for patch in raw_json:
            if patch.startswith(version):
                versionExists = True

        if not versionExists:
            event.msg.reply(
                "This is not a valid patch number. Try ~patch for the most recent patch notes!"
            )
            return

        embed = CacheHelper.getZileanEmbed(
            title="League of Legends Patch Notes",
            description=version + " Patch Notes",
            footer=version + " Patch Notes")
        embed.add_field(name="Notes", value=patch_url)
        event.msg.reply(embed=embed)
示例#5
0
    def on_ability(self, event, champion_name, ability="all"):
        ''' Displays information about a specific champions ability '''
        champions = LeagueHelper.get_champion_data()
        game_info = GameInfo(self.league_helper)
        abilities = ["q", "w", "e", "r", "passive", "all"]
        champ_found = False

        if ability.lower() in ["ult", "ultimate"]:
            ability = "r"
        elif ability.lower() not in abilities:
            event.msg.reply(
                "This is not a valid ability, Try from one of these " +
                str(abilities))
            return

        for key, name in champions["keys"].items():
            if champion_name.lower() == name.lower():
                champ_found = True
                if ability == "all":
                    game_info.display_champ(event.msg.channel,
                                            champions["version"],
                                            champions["data"][name])
                else:
                    game_info.display_ability(event.msg.channel,
                                              champions["version"],
                                              champions["data"][name], ability)

        if not champ_found:
            event.msg.reply(
                "This champion does not exist! Try ~ability Akali Q as an example..."
            )
    def on_track(self, event, summoner_name=None, region=None):
        '''Adds a summoner for Zilean to track whether they are in a live game'''
        if event.msg.channel.is_dm:
            return event.msg.reply("You must use this command in a guild!")

        if region is None and summoner_name is None and LiveDataHelper.user_is_bound(
                LiveDataHelper.load_summoner_binds(), str(
                    event.msg.author.id)):
            region = LiveDataHelper.get_user_bound_region(
                str(event.msg.author.id))

        region = LeagueHelper.validate_region(region, event)
        if region is None:
            return

        summoner = self.league_helper.user_exists(
            region, summoner_name, author_id=event.msg.author.id)

        if summoner is False:
            event.msg.reply("This summoner `" + summoner_name +
                            "` does not exist on `" + region +
                            "` Maybe try another region!")
            return

        self._add_summoner(event, region, summoner)
示例#7
0
    def on_iam(self, event, summoner_name=None, region=None):
        '''Set a default summoner for yourself that all league commands will use if you leave their summoner name and region arguments blank'''
        summoner_binds = LiveDataHelper.load_summoner_binds()
        author_id = str(event.author.id)

        if summoner_name is None and region is None:
            if LiveDataHelper.user_is_bound(summoner_binds, author_id):
                summoner_tuple = summoner_binds[author_id]
                event.msg.reply("You are `" + summoner_tuple[0] + " " + summoner_tuple[1] + "` If you want to change this type ~iam [summoner_name] [region]")
            else:
                event.msg.reply("You have not bound a summoner to your discord user! To do this type `~iam [summoner_name] [region]`")
        elif (summoner_name is not None) and (region is not None):
            region = LeagueHelper.validate_region(region, event)
            if region is None:
                return

            summoner = self.league_helper.user_exists(region, summoner_name, event)
            if summoner is False:
                return

            summoner_tuple = (summoner["name"], region)
            summoner_binds[author_id] = summoner_tuple
            LiveDataHelper.save_summoner_binds(summoner_binds)
            event.msg.reply("You have updated your summoner, You are `" + summoner["name"] + " " + region + "`")
        else:
            event.msg.reply("You must enter both a summoner name and region!")
    def on_remove(self, event, summoner_name=None, region=None):
        '''Removes a summoner that is being tracked by Zilean'''
        if event.msg.channel.is_dm:
            return event.msg.reply("You must use this command in a guild!")

        if region is None and summoner_name is None and LiveDataHelper.user_is_bound(
                LiveDataHelper.load_summoner_binds(), str(
                    event.msg.author.id)):
            region = LiveDataHelper.get_user_bound_region(
                str(event.msg.author.id))
            summoner_name = LiveDataHelper.get_user_bound_name(
                str(event.msg.author.id))

        region = LeagueHelper.validate_region(region,
                                              event,
                                              send_event_msg=False)

        if not self._summoner_is_tracked(event.guild.id, summoner_name,
                                         region):
            event.msg.reply(
                "This summoner `" + summoner_name + " " + region +
                "` is not being tracked. Track them by ~tracker add <region> <summoner_name>"
            )
            return

        self._remove_summoner(event, region, summoner_name)
示例#9
0
 def on_kp_graph(self, event, summoner_name=None, region=None):
     """Displays a graph of your kill participation percentage over the last 20 games played"""
     region = LeagueHelper.validate_region(region, event)
     if region:
         kp_graph = KillParticipationGraph(self.league_helper.watcher,
                                           region,
                                           LeagueHelper.get_champion_data())
         if summoner_name is not None:
             filepath = "kp-" + summoner_name + ".png"
         else:
             filepath = "kp-default.png"
         self._graph_renderer(event,
                              kp_graph,
                              summoner_name,
                              region,
                              filepath,
                              match_validation=True)
示例#10
0
    def on_cw_graph(self, event, summoner_name=None, region=None):
        """Displays a graph of your wins per individual champion over the last 20 games played"""
        region = LeagueHelper.validate_region(region, event)

        if region:
            cw_graph = ChampionWinsGraph(self.league_helper.watcher, region,
                                         LeagueHelper.get_champion_data())
            if summoner_name is not None:
                filepath = "cw-" + summoner_name + ".png"
            else:
                filepath = "cw-default.png"
            self._graph_renderer(event,
                                 cw_graph,
                                 summoner_name,
                                 region,
                                 filepath,
                                 match_validation=True)
示例#11
0
 def on_gpm_graph(self, event, summoner_name=None, region=None):
     """Displays a graph of the league games played per month per year"""
     region = LeagueHelper.validate_region(region, event)
     if region:
         gpm_graph = GamesPerMonthGraph(self.league_helper.watcher, region)
         if summoner_name is not None:
             filepath = "gpm-" + summoner_name + ".png"
         else:
             filepath = "gpm-default.png"
         self._graph_renderer(event,
                              gpm_graph,
                              summoner_name,
                              region,
                              filepath,
                              match_validation=True)
示例#12
0
    def on_item(self, event, item_name):
        '''Searches and displays the corresponding league of legends item'''
        items = LeagueHelper.get_item_data()
        game_info = GameInfo(self.league_helper)
        item_found = False

        for key, value in items["data"].items():
            if item_name.lower() in value["name"].lower(
            ) and len(item_name) > 3:
                game_info.display_item(event.msg.channel, items["version"],
                                       items["data"][key])
                item_found = True

        if not item_found:
            event.msg.reply("This item does not exist...")
示例#13
0
    def _display_region_status(self, event, region):
        region = LeagueHelper.validate_region(region)

        if region is None:
            event.msg.reply(
                "Please enter a valid **region**: *EUW, NA, EUN, JP, LAN, LAS, OCE, TR, RU, KR* :warning:"
            )
            return

        embed = CacheHelper.getZileanEmbed(
            title="Zilean Bot",
            footer="League of Legends Server Status for " + region,
            description="Type ~status to see every regions status!")
        endpoint_status = self.league_helper.watcher.lol_status.shard_data(
            region)
        embed.add_field(name=endpoint_status["name"] + " (" +
                        endpoint_status["slug"].upper() + ")",
                        value="Server Status")

        services = endpoint_status["services"]
        for service in endpoint_status["services"]:
            embed.add_field(name=service["name"],
                            value=self._emojify_status(service["status"]),
                            inline=True)

            if len(service["incidents"]) != 0:
                embed.add_field(name="Incidents",
                                value=str(len(service["incidents"])),
                                inline=True)
                incident_msg = ""
                for incident in service["incidents"]:
                    if len(incident["updates"]) != 0:
                        recent_update = incident["updates"][0]
                        incident_msg += incident["created_at"][
                            0:10] + " " + recent_update["severity"].upper(
                            ) + ": " + recent_update["content"] + "\n"
                        embed.add_field(name="Incident Description",
                                        value=incident_msg,
                                        inline=True)
            else:
                embed.add_field(name="Incidents",
                                value="No incidents!",
                                inline=True)
                embed.add_field(name="Incident Description",
                                value="N/A",
                                inline=True)

        event.msg.reply(embed=embed)
示例#14
0
    def on_build(self, event, champion_name):
        '''Displays the highest winrate championGG build for the given champion'''
        champions = LeagueHelper.get_champion_data()
        champ_found = False

        for key, name in champions["keys"].items():
            if champion_name.lower() == name.lower():
                champion_builder = ChampionGGHelper()
                champion_builder.generate_build(event, champions["data"][name],
                                                champions["version"])
                champ_found = True

        if not champ_found:
            event.msg.reply(
                "This champion does not exist! Try ~champion Akali as an example..."
            )
示例#15
0
    def on_champion(self, event, champion_name):
        '''Searches and displays the corresponding league of legends champion'''
        champions = LeagueHelper.get_champion_data()
        game_info = GameInfo(self.league_helper)
        champ_found = False

        for key, name in champions["keys"].items():
            if champion_name.lower() == name.lower():
                game_info.display_champ(event.msg.channel,
                                        champions["version"],
                                        champions["data"][name])
                champ_found = True

        if not champ_found:
            event.msg.reply(
                "This champion does not exist! Try ~champion Akali as an example..."
            )
    def on_auto(self, event, region, summoner_name):
        '''Toggles a summoner that is being tracked to auto-display there game'''

        # Need to rework this command!
        event.msg.reply(
            "This command is currently being rehauled. For more information join the support server: https://discord.gg/ZjAyh7N"
        )
        return
        # TODO: Rework this command

        if event.msg.channel.is_dm:
            return event.msg.reply("You must use this command in a guild!")

        region = LeagueHelper.validate_region(region)

        if not self._summoner_is_tracked(event.guild.id, summoner_name,
                                         region):
            event.msg.reply(
                "This summoner is not being tracked. Track them by ~tracker add <region> <summoner_name>"
            )
            return

        tracker = self.tracker
        guild_id = str(event.guild.id)
        summoner_list = tracker[guild_id]
        auto_message = "no longer being auto-displayed :x:"

        for index, summoner_tuple in enumerate(summoner_list):
            if summoner_tuple[1] == summoner_name.lower(
            ) and region == summoner_tuple[2]:
                summoner_tuple = summoner_list[index]
                summoner_list[index] = (summoner_tuple[0], summoner_tuple[1],
                                        summoner_tuple[2],
                                        not summoner_tuple[3]
                                        )  # Invert the current bool
                if summoner_list[index][3]:
                    auto_message = "now being auto-displayed :white_check_mark:"

        tracker[guild_id] = summoner_list
        self.update_tracker(tracker)
        event.msg.reply("The summoner `" + summoner_name + "` is " +
                        auto_message)
示例#17
0
    def on_region(self, event, region=None):
        '''Sets the overall default region for League of Legends commands'''
        region_binds = LiveDataHelper.load_region_binds()
        endpoints = str(LeagueHelper.API_ENDPOINTS).replace("[","").replace("'","").replace("]", "")

        if region is None:
            if LiveDataHelper.guild_has_region(region_binds, str(event.guild.id)):
                event.msg.reply("The current default region for League of Legends commands is: `" + region_binds[str(event.guild.id)] + "`")
            else:
                event.msg.reply("This server does not currently have a default region for League of Legends commands.\nTry ~region [region] where the region is one of the following: `" + endpoints + "`")
        else:
            region = LeagueHelper.validate_region(region, event, send_event_msg=False)
            if region is None:
                event.msg.reply("You have entered an invalid region, please enter one of the following: `" + endpoints + "`")
                return

            region_binds = LiveDataHelper.load_region_binds()
            region_binds[str(event.guild.id)] = region
            LiveDataHelper.save_region_binds(region_binds)
            event.msg.reply("The default region for League of Legends commands is now `" + region + "`")
示例#18
0
class UtilityCommands(Plugin):
    def load(self, ctx):
        super(UtilityCommands, self).load(ctx)

        with open("league_api/data/version.json") as data_file:
            data = json.load(data_file)

        self.version = data["version"]
        self.guild_list = dict()
        self.league_helper = LeagueHelper()

    @Plugin.command("info")
    def on_info(self, event):
        """Displays information about the bot"""
        guild_list = self.client.state.guilds
        user_list = self.client.state.users
        channel_list = self.client.state.channels

        embed = CacheHelper.getZileanEmbed(title="Zilean Bot Info", footer="Bot Information", description="A discord bot that tracks time spent playing league and other statistics :hourglass_flowing_sand: https://samuel-maddock.github.io/Zilean/")
        embed.add_field(name="Version:", value=self.version)
        embed.add_field(name="Developed using:", value="https://github.com/pseudonym117/Riot-Watcher https://github.com/b1naryth1ef/disco")
        embed.add_field(name="Guilds Connected: ", value=len(guild_list), inline=True)
        embed.add_field(name="Users Connected: ", value=len(user_list), inline=True)
        embed.add_field(name="Channels Connected: ", value=len(channel_list), inline=True)
        embed.add_field(name="If you enjoy the bot please upvote it below:heart_exclamation:", value="https://discordbots.org/bot/459139146544578571")
        embed.add_field(name="If you have feature suggestions/spotted some bugs", value="Join the support server: https://discord.gg/ZjAyh7N")
        embed.add_field(name="Use ~help for a list of commands!", value=":wave:")
        event.msg.reply(embed=embed)

    @Plugin.command("help")
    def on_help(self, event):
        """Displays help and command information about Zilean"""
        embed = CacheHelper.getZileanEmbed(title="Zilean Command List", footer="Zilean Commands", description="Note that [arg] is a required argument and (arg) is an optional argument")
        embed.add_field(name="Zilean Commands", value="You can view the commands by following the link below" + "\nhttps://samuel-maddock.github.io/Zilean/#command-section")
        embed.add_field(name="If you enjoy the bot please upvote it below:heart_exclamation:", value="https://discordbots.org/bot/459139146544578571")
        embed.add_field(name="If you have feature suggestions/spotted some bugs", value="Join the support server: https://discord.gg/ZjAyh7N")
        event.msg.author.open_dm().send_message(embed=embed)
        event.msg.author.open_dm().send_message(embed=self.get_notification())
        event.msg.reply("Check your DMs for more information... :cyclone:")

    @Plugin.command("changelog")
    def on_changelog(self, event):
        '''Displays a list of recent changes to Zilean'''
        embed = self.get_notification()
        event.msg.reply(embed=embed)

    @Plugin.command("uptime")
    def on_uptime(self, event):
        '''Displays how long Zilean has been online for'''
        uptime = datetime.now() - self.start_time
        hours = str(uptime.seconds//3600)
        minutes = str((uptime.seconds//60)%60)
        seconds = str(uptime.seconds%60)

        if (hours == "0"):
            hours = "00"

        if (minutes=="0"):
            minutes = "00"

        uptime_string = str(uptime.days) + " Days, " + hours + ":" + minutes + ":" + seconds + " (Hrs/Min/Sec)"
        embed = CacheHelper.getZileanEmbed(title="Zilean Uptime", footer="Zilean Bot", description="Zilean has been online for: " + uptime_string)
        event.msg.reply(embed=embed)

    @Plugin.command("commands", aliases=["cmd", "cmds", "command"])
    def on_commands(self, event):
        """Displays the link to the commands"""
        event.msg.reply("Zilean Commands: https://samuel-maddock.github.io/Zilean/#command-section :hourglass_flowing_sand:")

    @Plugin.command("ping")
    def on_ping(self, event):
        """A basic ping command, returns the latency in milliseconds"""
        delta = datetime.now() - event.msg.timestamp
        delta_tuple = math.modf(delta.total_seconds())
        ms = round(delta_tuple[0] * 1000)
        event.msg.reply("Pong! " + str(ms) + "ms")

    @Plugin.command("bind")
    def on_bind(self, event):
        '''Binds Zilean to the current text channel to be used during live game alerts'''

        if event.msg.channel.is_dm:
            return event.msg.reply("You must use this command in a guild!")

        guild = event.guild
        channel = event.channel
        channel_binds = LiveDataHelper.load_guild_binds()

        if LiveDataHelper.guild_is_binded(channel_binds, str(guild.id)):
            if channel_binds[str(guild.id)] == channel.id:
                event.msg.reply("Zilean is already bound to this channel: `#" + channel.name + "`")
                return

        channel_binds[str(guild.id)] = channel.id
        LiveDataHelper.save_guild_binds(channel_binds)
        event.msg.reply("The tracker messages are now bound to the following text channel: `#" + channel.name + "`")

    @Plugin.command("region", "[region:str]")
    def on_region(self, event, region=None):
        '''Sets the overall default region for League of Legends commands'''
        region_binds = LiveDataHelper.load_region_binds()
        endpoints = str(LeagueHelper.API_ENDPOINTS).replace("[","").replace("'","").replace("]", "")

        if region is None:
            if LiveDataHelper.guild_has_region(region_binds, str(event.guild.id)):
                event.msg.reply("The current default region for League of Legends commands is: `" + region_binds[str(event.guild.id)] + "`")
            else:
                event.msg.reply("This server does not currently have a default region for League of Legends commands.\nTry ~region [region] where the region is one of the following: `" + endpoints + "`")
        else:
            region = LeagueHelper.validate_region(region, event, send_event_msg=False)
            if region is None:
                event.msg.reply("You have entered an invalid region, please enter one of the following: `" + endpoints + "`")
                return

            region_binds = LiveDataHelper.load_region_binds()
            region_binds[str(event.guild.id)] = region
            LiveDataHelper.save_region_binds(region_binds)
            event.msg.reply("The default region for League of Legends commands is now `" + region + "`")

    @Plugin.command("iam", "[summoner_name:str] [region:str]")
    def on_iam(self, event, summoner_name=None, region=None):
        '''Set a default summoner for yourself that all league commands will use if you leave their summoner name and region arguments blank'''
        summoner_binds = LiveDataHelper.load_summoner_binds()
        author_id = str(event.author.id)

        if summoner_name is None and region is None:
            if LiveDataHelper.user_is_bound(summoner_binds, author_id):
                summoner_tuple = summoner_binds[author_id]
                event.msg.reply("You are `" + summoner_tuple[0] + " " + summoner_tuple[1] + "` If you want to change this type ~iam [summoner_name] [region]")
            else:
                event.msg.reply("You have not bound a summoner to your discord user! To do this type `~iam [summoner_name] [region]`")
        elif (summoner_name is not None) and (region is not None):
            region = LeagueHelper.validate_region(region, event)
            if region is None:
                return

            summoner = self.league_helper.user_exists(region, summoner_name, event)
            if summoner is False:
                return

            summoner_tuple = (summoner["name"], region)
            summoner_binds[author_id] = summoner_tuple
            LiveDataHelper.save_summoner_binds(summoner_binds)
            event.msg.reply("You have updated your summoner, You are `" + summoner["name"] + " " + region + "`")
        else:
            event.msg.reply("You must enter both a summoner name and region!")

    @Plugin.listen("Ready")
    def on_ready(self, event):
        self.start_time = datetime.now()
        self.client.update_presence(Status.ONLINE, Game(type=GameType.watching, name="you play League of Legends"))
        command_list = self.generate_command_list()
        self.update_command_list(command_list)
        atexit.register(self.on_bot_shutdown)  # Register bot shutdown hook

    @Plugin.schedule(CACHE_SCHEDULE)
    def on_cache_update(self):
        CacheHelper.update_static_data()

    @Plugin.listen("GuildCreate")
    def on_guild_create(self, event):
        self.guild_list[str(event.guild.id)] = (event.guild.name, event.guild.id)
        logger = CacheHelper.get_logger("GuildCreate")
        logger.zilean("New Guild Created: " + event.guild.name + " " + str(event.guild.id))

    @Plugin.listen("GuildDelete")
    def on_guild_remove(self, event):
        guild_list = self.guild_list
        guild = guild_list[str(event.id)]
        guild_list.pop(str(event.id))

        logger = CacheHelper.get_logger("GuildRemove")
        logger.zilean("Guild Removed: " + guild[0] + " " + str(guild[1]))

        channel_binds = LiveDataHelper.load_guild_binds()
        channel_bind = channel_binds.pop(str(event.id), None)

        if channel_bind:
            logger.zilean("Guild-Channel bind has been removed for " + guild[0] + " " + str(guild[1]))

        LiveDataHelper.save_guild_binds(channel_binds)

    @Plugin.listen("MessageCreate")
    def on_message_create(self, event):
        content = event.message.content
        if content == "<@459139146544578571>":
            event.message.reply("Type ~help and ~info to get started!")

    @Plugin.pre_command()
    def on_command_event(self, command, event, args, kwargs):
        CacheHelper.log_command(command, event)
        return event

    def on_bot_shutdown(self):
        CacheHelper.save_guilds(self.guild_list)
        logger = CacheHelper.get_logger("ShutdownHook")
        logger.zilean("Bot Shutdown - Guild List saved successfully")

        # Send restart messages to those who have bound the bot to a channel
        ''' channel_binds = LiveDataHelper.load_guild_binds()
        for guild_id in channel_binds.keys():
            try:
                channel = self.bot.client.state.channels[channel_binds[guild_id]]
                channel.send_message("Zilean is restarting - The bot is updating, please be patient... :recycle:")
            except KeyError as err:
                logger = CacheHelper.get_logger("GuildBindError")
                logger.zilean("Guild ID failed to be removed when the bot was offline: " + str(guild_id)) '''

    def generate_command_list(self):
        command_list = dict()
        for name, plugin in self.bot.plugins.items():
            command_list[name] = list()
            for command in plugin.commands:
                prefix = self.bot.config.commands_prefix
                cmd_description = command.get_docstring()
                cmd_usage = list()
                args = ""

                if command.group:
                    prefix += command.group + " "

                if command.args:
                    for arg in command.args.args:
                        if arg.required:
                            args += "[" + arg.name + "] "
                        else:
                            args += "(" + arg.name + ") "

                if len(command.triggers) > 1:
                    for trigger in command.triggers:
                        cmd_usage.append(prefix + trigger + " " + args)
                else:
                    cmd_usage.append(prefix + command.name + " " + args)

                cmd_name = prefix + command.name

                command_list.setdefault(name, []).append((cmd_name, cmd_usage, cmd_description))

        return command_list

    def update_command_list(self, command_list):
        with open("docs/commandList.json", "w") as data_file:
            json.dump(command_list, data_file)
        logger = CacheHelper.get_logger("CommandList")
        logger.zilean("Command List Generated")

    def get_notification(self):
        embed = CacheHelper.getZileanEmbed(title="Recent Zilean Changes (" + self.version + ")", footer="Zilean Update", description=
            "For previous updates and changes go to the changelog here:\nhttps://samuel-maddock.github.io/Zilean/changelog.html\n\n" +
            "You can now bind a League of Legends summoner to your discord user by using the ~iam command. Try **~iam [summoner_name] [region]** to get started!\n\n" +
            "If you do this any command that requires a summoner name and region will work without writing those arguments eg ~match_history will display your own match history.\n\n" +
            "In order to support adding a default LoL region, the command structure for some commands have changed!"
            "\n\n"
            "For many LoL commands you used to state **[region] [summoner_name]** but now the order is **[summoner_name] (region)**."
            "\n\n"
            "The region is only optional if you set a default region for your server using **~region [league region]**"
            "\n\n**Note that you need to remove any spaces from a summoner name for the commands to work!**")
        embed.color = 0xFF3B73
        return embed
 def load(self, ctx):
     super(GameTrackerCommands, self).load(ctx)
     self.league_helper = LeagueHelper()
     self.tracker = self.load_tracker()
class GameTrackerCommands(Plugin):
    def load(self, ctx):
        super(GameTrackerCommands, self).load(ctx)
        self.league_helper = LeagueHelper()
        self.tracker = self.load_tracker()

    @Plugin.pre_command()
    def on_command_event(self, command, event, args, kwargs):
        CacheHelper.log_command(command, event)
        return event

    def load_tracker(self):
        with open("league_api/data/live/tracker.json") as tracker_file:
            return json.load(tracker_file)

    def update_tracker(self, tracker):
        with open("league_api/data/live/tracker.json", "w") as tracker_file:
            json.dump(tracker, tracker_file)

        self.tracker = tracker

    @Plugin.command("tracker")
    def on_tracker(self, event):
        '''Displays the list of tracked summoners and whether they are in game'''

        if len(event.args) >= 1:
            return

        if event.msg.channel.is_dm:
            return event.msg.reply("You must use this command in a guild!")

        tracker = self.tracker

        if not self._guild_is_tracked(str(event.msg.guild.id)):
            event.msg.reply(
                "You are currently not tracking any players! Try ~tracker add [summoner_name] [region] to begin..."
            )
            return

        self._display_track(tracker[str(event.msg.guild.id)],
                            event.msg.channel)

    @Plugin.command("add", '[summoner_name:str] [region:str]', group="tracker")
    def on_track(self, event, summoner_name=None, region=None):
        '''Adds a summoner for Zilean to track whether they are in a live game'''
        if event.msg.channel.is_dm:
            return event.msg.reply("You must use this command in a guild!")

        if region is None and summoner_name is None and LiveDataHelper.user_is_bound(
                LiveDataHelper.load_summoner_binds(), str(
                    event.msg.author.id)):
            region = LiveDataHelper.get_user_bound_region(
                str(event.msg.author.id))

        region = LeagueHelper.validate_region(region, event)
        if region is None:
            return

        summoner = self.league_helper.user_exists(
            region, summoner_name, author_id=event.msg.author.id)

        if summoner is False:
            event.msg.reply("This summoner `" + summoner_name +
                            "` does not exist on `" + region +
                            "` Maybe try another region!")
            return

        self._add_summoner(event, region, summoner)

    @Plugin.command("remove",
                    '[summoner_name:str] [region:str]',
                    group="tracker")
    def on_remove(self, event, summoner_name=None, region=None):
        '''Removes a summoner that is being tracked by Zilean'''
        if event.msg.channel.is_dm:
            return event.msg.reply("You must use this command in a guild!")

        if region is None and summoner_name is None and LiveDataHelper.user_is_bound(
                LiveDataHelper.load_summoner_binds(), str(
                    event.msg.author.id)):
            region = LiveDataHelper.get_user_bound_region(
                str(event.msg.author.id))
            summoner_name = LiveDataHelper.get_user_bound_name(
                str(event.msg.author.id))

        region = LeagueHelper.validate_region(region,
                                              event,
                                              send_event_msg=False)

        if not self._summoner_is_tracked(event.guild.id, summoner_name,
                                         region):
            event.msg.reply(
                "This summoner `" + summoner_name + " " + region +
                "` is not being tracked. Track them by ~tracker add <region> <summoner_name>"
            )
            return

        self._remove_summoner(event, region, summoner_name)

    @Plugin.command("reset", group="tracker")
    def on_reset(self, event):
        '''Removes all of the summoners that are being tracked by Zilean'''
        if event.msg.channel.is_dm:
            return event.msg.reply("You must use this command in a guild!")

        if self._guild_is_tracked(event.msg.guild.id):
            event.msg.reply(
                "The tracker list for this guild has been reset :sparkles:")
            self.tracker[str(event.msg.guild.id)] = list()
            self.update_tracker(self.tracker)
        else:
            event.msg.reply(
                "The tracker list for this guild is empty! Use ~tracker add <region> <summoner_name> to get started..."
            )

    @Plugin.command("auto",
                    "<region:str> <summoner_name:str...>",
                    group="tracker")
    def on_auto(self, event, region, summoner_name):
        '''Toggles a summoner that is being tracked to auto-display there game'''

        # Need to rework this command!
        event.msg.reply(
            "This command is currently being rehauled. For more information join the support server: https://discord.gg/ZjAyh7N"
        )
        return
        # TODO: Rework this command

        if event.msg.channel.is_dm:
            return event.msg.reply("You must use this command in a guild!")

        region = LeagueHelper.validate_region(region)

        if not self._summoner_is_tracked(event.guild.id, summoner_name,
                                         region):
            event.msg.reply(
                "This summoner is not being tracked. Track them by ~tracker add <region> <summoner_name>"
            )
            return

        tracker = self.tracker
        guild_id = str(event.guild.id)
        summoner_list = tracker[guild_id]
        auto_message = "no longer being auto-displayed :x:"

        for index, summoner_tuple in enumerate(summoner_list):
            if summoner_tuple[1] == summoner_name.lower(
            ) and region == summoner_tuple[2]:
                summoner_tuple = summoner_list[index]
                summoner_list[index] = (summoner_tuple[0], summoner_tuple[1],
                                        summoner_tuple[2],
                                        not summoner_tuple[3]
                                        )  # Invert the current bool
                if summoner_list[index][3]:
                    auto_message = "now being auto-displayed :white_check_mark:"

        tracker[guild_id] = summoner_list
        self.update_tracker(tracker)
        event.msg.reply("The summoner `" + summoner_name + "` is " +
                        auto_message)

    @Plugin.schedule(TRACKER_SCHEDULE, init=False)
    def on_schedule_track(self):
        tracker = self.tracker
        channel_binds = LiveDataHelper.load_guild_binds()
        game_info = GameInfo(self.league_helper)

        if len(tracker) == 0:
            return

        for guild_id in channel_binds.keys():
            guild_id = str(guild_id)
            if self._guild_is_tracked(guild_id):
                channel = self.bot.client.state.channels.get(
                    channel_binds[guild_id])
                if channel is not None:  # Prevents errors if the bot has left a guild, but the guild id still persits in the binds
                    summoner_list = tracker[guild_id]
                    logger = CacheHelper.get_logger("TrackerMessage")
                    self._display_track(tracker[guild_id], channel)
                    logger.zilean(
                        "Tracker: " + guild_id + " " +
                        self.bot.client.state.guilds.get(int(guild_id)).name)

    def _display_track(self, summoner_list, channel):
        game_found = False
        has_live_games = False
        summoner_names = ""
        regions = ""
        in_game = ""
        footer = ""

        connection_failure = False
        for summoner in summoner_list:
            summoner_failed = False
            auto_display = summoner[3]
            summoner_names += summoner[1] + "\n"
            regions += summoner[2] + "\n"

            try:
                spectate_info = self.league_helper.user_in_game(
                    summoner[2], summoner[0])
            except ConnectionError as e:
                logger = CacheHelper.get_logger("TrackerError")
                logger.zilean("Could not connect to the Riot API. Summoner: " +
                              summoner[1] + "Channel: " + channel.name)
                summoner_failed = True
                connection_failure = True

            if spectate_info and not summoner_failed:
                in_game += "**Yes** | " + self.boolMsg(auto_display) + "\n"
                if auto_display:
                    game_info = GameInfo(self.league_helper)
                    game_info.display_live_game(channel, summoner[2],
                                                spectate_info)
                has_live_games = True
            elif not summoner_failed:
                in_game += "No | " + self.boolMsg(auto_display) + "\n"
            else:
                in_game += "Summoner info cannot be retrieved at this time\n"

        if connection_failure:
            footer = "Error retrieving one or more summoners info"
        if not has_live_games:
            footer = "No one is currently in a live game :("
        else:
            footer = "To view a summoner in game use ~game_info <region> <summoner_name>"

        description = "This message is automatically displayed every " + str(int(TRACKER_SCHEDULE/60)) + " minutes!" + \
                            "\n If auto-display is turned on for a summoner their game is automatically displayed"

        embed = CacheHelper.getZileanEmbed(
            title=":eye: Tracking Live Games... :eye:",
            description=description,
            footer=footer)
        embed.add_field(name="Summoner Name",
                        value=summoner_names,
                        inline=True)
        embed.add_field(name="Region", value=regions, inline=True)
        embed.add_field(name="In Game | Auto-Display",
                        value=in_game,
                        inline=True)

        if connection_failure:
            embed.add_field(
                name="Connection Issue",
                value=
                "One or more summoners info could not be retrieved. Please try again in a few minutes."
            )

        try:
            channel.send_message(embed=embed)
        except ConnectionError as e:
            logger = CacheHelper.get_logger("TrackerError")
            logger.zilean(
                "Tracker message failed to send. Could not connect to the Discord API"
            )
        except APIException as e:
            logger = CacheHelper.get_logger("TrackerError")
            logger.zilean("APIException - " + str(e.status_code))

    def boolMsg(self, bool):
        if bool:
            return "**Yes**"
        else:
            return "No"

    def _guild_is_tracked(self, guild_id):
        tracker = self.tracker
        try:
            a = tracker[str(guild_id)]
            if len(a) == 0:
                return False
            else:
                return True
        except KeyError as err:
            return False

    def _summoner_is_tracked(self, guild_id, summoner_name, region):
        if not self._guild_is_tracked(guild_id):
            return False

        tracker = self.tracker
        summoner_info_list = tracker[str(guild_id)]
        for summoner_tuple in summoner_info_list:
            if summoner_name.lower() == summoner_tuple[1].replace(
                    " ", "").lower() and region == summoner_tuple[2]:
                return True
        return False

    def _add_summoner(self, event, region, summoner, is_auto=False):
        guild_id = str(event.guild.id)
        data = (summoner["id"], summoner["name"].lower(), region, is_auto)
        tracker = self.tracker
        summoner_list = list()

        if self._guild_is_tracked(guild_id):
            if self._summoner_is_tracked(guild_id, summoner["name"], region):
                event.msg.reply("This summoner is already being tracked: `" +
                                summoner["name"] + "`")
                return
            else:
                summoner_list = tracker[guild_id]

        if len(summoner_list) >= 10:
            event.msg.reply(
                "You are already tracking the maximum number (10) of summoners! Use ~tracker remove [region] [summoner_name] to remove a summoner"
            )
            return

        summoner_list.append(data)
        tracker[guild_id] = summoner_list
        self.update_tracker(tracker)

        event.msg.reply(
            "The summoner `" + summoner["name"] + " " + region +
            "` is now being tracked, tracking messages will be displayed every "
            + str(int(TRACKER_SCHEDULE / 60)) + " minutes :eye:")
        channel_binds = LiveDataHelper.load_guild_binds()

        if LiveDataHelper.guild_is_binded(channel_binds, guild_id):
            channel = self.bot.client.state.channels.get(
                channel_binds[guild_id])
            event.msg.reply(
                "You will receive track alerts on the current bound text channel: `#"
                + channel.name + "`")
        else:
            channel = event.msg.channel
            channel_binds[str(guild_id)] = channel.id
            LiveDataHelper.save_guild_binds(channel_binds)
            event.msg.reply(
                "The tracker messages are now bound to the following text channel: `#"
                + channel.name + "`" + "\n" +
                "Use ~bind to change the bound text channel")

    def _remove_summoner(self, event, region, summoner_name):
        tracker = self.tracker
        guild_id = str(event.guild.id)
        summoner_list = tracker[guild_id]

        for index, summoner_tuple in enumerate(summoner_list):
            if summoner_tuple[1] == summoner_name.lower(
            ) and summoner_tuple[2] == region:
                summoner_name = summoner_tuple[1]
                del summoner_list[index]

        tracker[guild_id] = summoner_list
        self.update_tracker(tracker)
        event.msg.reply("The summoner `" + summoner_name + " " + region +
                        "` is no longer being tracked.")
示例#21
0
    def display_past_game(self, channel, region, match, summoner_id):

        # Find the current game mode that is being played using a CDragon json
        match["gameQueueConfigId"] = match["queueId"]
        description, queue_name, pick_type, is_ranked = self._get_queue_info(
            region, match)

        game_epoch = match["gameCreation"]
        game_duration = datetime.timedelta(seconds=match["gameDuration"])
        game_date = datetime.datetime.fromtimestamp(game_epoch /
                                                    1000).strftime('%d-%m-%Y')

        champion_data = LeagueHelper.get_champion_data()
        image_url = "http://ddragon.leagueoflegends.com/cdn/" + champion_data[
            "version"] + "/img/champion/"

        for participant in match["participantIdentities"]:
            if participant["player"]["currentAccountId"] == summoner_id:
                target_player = participant

        for participant in match["participants"]:
            if participant["participantId"] == target_player["participantId"]:
                target_champion_id = participant["championId"]
                target_stats = str(participant["stats"]["kills"]) + "/" + str(
                    participant["stats"]["deaths"]) + "/" + str(
                        participant["stats"]["assists"])
                target_team = participant["teamId"]

        for team in match["teams"]:
            if team["teamId"] == target_team:
                match_outcome = team["win"]

        if match_outcome == "Fail":
            match_outcome = "Defeat"
            embed_color = 16711686
        else:
            match_outcome = "Victory"
            embed_color = 65286

        target_champion = champion_data["keys"][str(target_champion_id)]

        embed = CacheHelper.getZileanEmbed(title="Match History Game Info",
                                           description=queue_name)
        embed.set_thumbnail(url=image_url + target_champion + ".png")
        embed.color = embed_color
        embed.add_field(name="Summoner Name",
                        value=target_player["player"]["summonerName"],
                        inline=True)
        embed.add_field(name="Champion", value=target_champion, inline=True)
        embed.add_field(name="k/d/a", value=target_stats, inline=True)
        embed.add_field(name="Match Outcome", value=match_outcome, inline=True)
        embed.add_field(name="Game Duration:",
                        value=str(game_duration),
                        inline=True)
        embed.add_field(name="Game Date:", value=game_date, inline=True)
        embed.add_field(
            name="More Info",
            value=
            "http://matchhistory.euw.leagueoflegends.com/en/#match-details/" +
            region + "/" + str(match["gameId"]) + "/" + str(summoner_id) +
            "?tab=overview")
        channel.send_message(embed=embed)
示例#22
0
    def display_live_game(self, channel, region, spectate_info):
        channel.send_message("Game found generating live info...")

        if spectate_info["gameType"] == "CUSTOM_GAME":
            channel.send_message(
                "Custom game spectating is not supported SOONtm")
            return

        champion_data = LeagueHelper.get_champion_data()

        team_info = list()
        for participant in spectate_info["participants"]:
            champ_info = (participant["teamId"], participant["summonerName"],
                          champion_data["keys"][str(
                              participant["championId"])],
                          participant["summonerId"])
            team_info.append(champ_info)

        blue_names = ""
        blue_champs = ""
        red_names = ""
        red_champs = ""
        blue_rank = ""
        red_rank = ""

        # Find the current game mode that is being played using a CDragon json
        # Currently the CDragon json needs to be updated manually -> TODO
        description, queue_name, pick_type, is_ranked = self._get_queue_info(
            region, spectate_info)

        # Find the summoners names, champions and ranks on each team
        for participant in team_info:
            ranked_positions = self.league_helper.watcher.league.positions_by_summoner(
                region, participant[3])
            rank, rank_type = self._get_rank_by_queue(queue_name, is_ranked,
                                                      ranked_positions)

            if participant[0] == 100:
                blue_names += participant[1] + "\n"
                blue_champs += participant[2] + "\n"
                blue_rank += rank + "\n"
            else:
                red_names += participant[1] + "\n"
                red_champs += participant[2] + "\n"
                red_rank += rank + "\n"

        # Find the list of banned champions for both teams
        blue_ban, red_ban = self._get_banned_champions(
            spectate_info["bannedChampions"], champion_data)

        if description == "":
            description = "Playing an unknown gamemode/map -> Please update queue.json "

        # Format all of the live game info using a discord embed message
        embed = CacheHelper.getZileanEmbed(title="Live Game Info",
                                           description=description,
                                           footer="Live Game Info")

        embed.add_field(name=":large_blue_circle: Blue Team",
                        value=blue_names,
                        inline=True)
        embed.add_field(name="Rank", value=blue_rank, inline=True)
        embed.add_field(name="Champions:", value=blue_champs, inline=True)
        embed.add_field(name=":red_circle: Red Team",
                        value=red_names,
                        inline=True)
        embed.add_field(name="Rank", value=red_rank, inline=True)
        embed.add_field(name="Champions:", value=red_champs, inline=True)

        if "DRAFT" in pick_type:
            embed.add_field(
                name=":no_entry_sign: Red Team Bans :no_entry_sign:",
                value=red_ban,
                inline=True)
            embed.add_field(
                name=":no_entry_sign: Blue Team Bans :no_entry_sign:",
                value=blue_ban,
                inline=True)

        channel.send_message(embed=embed)
示例#23
0
    def on_summoner(self, event, summoner_name=None, region=None):
        '''Displays information about a League of Legends summoner'''
        # TODO: Tidy this up...

        # Prevent command quit on no region given if the discord user has bound a summoner to there account
        if region is None and summoner_name is None and LiveDataHelper.user_is_bound(
                LiveDataHelper.load_summoner_binds(), str(
                    event.msg.author.id)):
            region = LiveDataHelper.get_user_bound_region(
                str(event.msg.author.id))

        region = LeagueHelper.validate_region(region, event)
        if region is None:
            return

        summoner = self.league_helper.user_exists(region, summoner_name, event,
                                                  event.msg.author.id)
        if not summoner:
            return

        version = LeagueHelper.get_champion_data()["version"]
        embed = CacheHelper.getZileanEmbed(
            title="Summoner Profile: ",
            footer="Displaying summoner info for " + summoner["name"],
            description=summoner["name"] + " " + region)
        embed.set_thumbnail(url="http://ddragon.leagueoflegends.com/cdn/" +
                            version + "/img/profileicon/" +
                            str(summoner["profileIconId"]) + ".png")
        embed.add_field(name="Summoner Level",
                        value=str(summoner["summonerLevel"]))
        ranked_positions = self.league_helper.watcher.league.positions_by_summoner(
            region, summoner["id"])

        ranks_array = ["RANKED SOLO 5x5", "RANKED FLEX TT", "RANKED FLEX SR"]
        for rank in ranked_positions:
            rank_name = rank["queueType"].replace("_", " ")
            embed.add_field(name="Queue Type", value=rank_name, inline=True)
            ranks_array.remove(rank_name)

            winrate = round(
                (rank["wins"] / (rank["wins"] + rank["losses"])) * 100)
            rank_msg = rank["tier"] + " " + rank["rank"] + " (" + str(
                rank["leaguePoints"]) + "lp)"
            winrate_msg = " | " + str(winrate) + "%"
            winloss_msg = " | W:" + str(rank["wins"]) + " L:" + str(
                rank["losses"])

            embed.add_field(name="Rank | Wins/Losses | Winrate",
                            value=rank_msg + winloss_msg + winrate_msg,
                            inline=True)

        for rank in ranks_array:
            embed.add_field(name="Queue Type", value=rank, inline=True)
            embed.add_field(name="Rank | Wins/Losses | Winrate",
                            value="UNRANKED",
                            inline=True)

        try:
            matchlist = self.league_helper.watcher.match.matchlist_by_account(
                region, summoner["accountId"])
            match = self.league_helper.watcher.match.by_id(
                region, matchlist["matches"][0]["gameId"])

            for participant in match["participantIdentities"]:
                if participant["player"]["currentAccountId"] == summoner[
                        "accountId"]:
                    target_player = participant

            for participant in match["participants"]:
                if participant["participantId"] == target_player[
                        "participantId"]:
                    target_champion_id = participant["championId"]
                    target_stats = str(
                        participant["stats"]["kills"]) + "/" + str(
                            participant["stats"]["deaths"]) + "/" + str(
                                participant["stats"]["assists"])
                    target_team = participant["teamId"]

            for team in match["teams"]:
                if team["teamId"] == target_team:
                    match_outcome = team["win"]

            if match_outcome == "Fail":
                match_outcome = "Defeat :x:"
            else:
                match_outcome = "Victory :white_check_mark:"

            target_champion = LeagueHelper.get_champion_data()["keys"][str(
                target_champion_id)]
            embed.add_field(
                name="Last Game Played:",
                value="**" + match_outcome + "**\n" + target_champion + " " +
                target_stats +
                " http://matchhistory.euw.leagueoflegends.com/en/#match-details/"
                + region + "/" + str(match["gameId"]) + "/" +
                str(summoner["accountId"]) + "?tab=overview")

        except HTTPError as err:
            if err.response.status_code == 404:
                embed.add_field(
                    name="Last Game Played",
                    value="This summoner has not recently played a game.")

        if not self.league_helper.user_in_game(region, summoner["id"]):
            embed.add_field(
                name="Live Game",
                value="This summoner is not currently in a live game.")
        else:
            embed.add_field(
                name="Live Game",
                value="This summoner is in a live game, type ~live_game " +
                region + " " + summoner_name + " for more info.")

        event.msg.reply(embed=embed)
示例#24
0
    def generate_build(self, event, champion, version):
        # For ChampionGG API Documentation: http://api.champion.gg/docs/#api-Champions-GetChampion
        # This sends a GET request to the championGG API and retrieves the champions highest winrate build

        champion_id = champion["key"]
        embed = CacheHelper.getZileanEmbed(title="Champion Build",
                                           description=champion["name"] + " " +
                                           champion["title"])
        api_url = "http://api.champion.gg/v2/champions/" + champion_id + "?champData=hashes&api_key=" + self.key
        response = urllib.request.urlopen(api_url)
        build_info = json.loads(response.read().decode("utf-8"))[
            0]  # Decode the byte response to json object
        # The above also stores the json dict and not the array of the dict

        # Retrieve hashes for the highest winrate build
        hashes = build_info["hashes"]
        skill_order = hashes["skillorderhash"]["highestWinrate"]["hash"].strip(
            "skill-")
        start_items = hashes["firstitemshash"]["highestWinrate"]["hash"].strip(
            "first-")
        final_items = hashes["finalitemshashfixed"]["highestWinrate"][
            "hash"].strip("items-")
        rune_hash = hashes["runehash"]["highestWinrate"]["hash"]

        # Convert hashes into viewable strings
        items = LeagueHelper.get_item_data()
        runes = LeagueHelper.get_rune_data()

        start_items, start_build_urls = self.parse_item_hash(
            start_items, items, True)
        final_items, final_build_urls = self.parse_item_hash(
            final_items, items, True)
        rune_message_1, rune_message_2, rune_path_urls = self.parse_rune_hash(
            rune_hash, runes)
        skill_order = skill_order.replace("-", ">")

        # Generate the final build image
        self.generate_build_image(final_build_urls, "finalbuild.png")
        self.generate_build_image(start_build_urls, "startbuild.png")
        self.generate_build_image(rune_path_urls[0:5], "runepath1.png")
        self.generate_build_image(rune_path_urls[5:8], "runepath2.png")

        # Append and send message embed and images
        image_url = "http://ddragon.leagueoflegends.com/cdn/" + version + "/img/champion/"
        embed.set_thumbnail(url=image_url + champion["image"]["full"])
        embed.add_field(name="ProBuilds: " + champion["name"],
                        value="https://www.probuilds.net/champions/details/" +
                        champion["name"])
        embed.add_field(name="In-Depth Builds:",
                        value="https://www.mobafire.com/league-of-legends/" +
                        champion["name"] +
                        "-guide?sort=patch&order=ascending&author=all&page=1")
        embed.add_field(name="Skill Order", value=skill_order)
        event.msg.reply(embed=embed)
        event.msg.reply("**Recommended Starting Items:**\n" + start_items,
                        attachments=[("startbuild.png",
                                      open("startbuild.png", "rb"))])
        event.msg.reply("**Recommended Final Build:**\n" + final_items,
                        attachments=[("finalbuild.png",
                                      open("finalbuild.png", "rb"))])
        event.msg.reply("**Recommended Runes:**\n" + rune_message_1,
                        attachments=[("runepath1.png",
                                      open("runepath1.png", "rb"))])
        event.msg.reply(rune_message_2,
                        attachments=[("runepath2.png",
                                      open("runepath2.png", "rb"))])
示例#25
0
class GraphCommands(Plugin):
    def load(self, ctx):
        super(GraphCommands, self).load(ctx)
        self.league_helper = LeagueHelper()

    @Plugin.pre_command()
    def on_command_event(self, command, event, args, kwargs):
        CacheHelper.log_command(command, event)
        return event

    @Plugin.command('games_per_month',
                    "[summoner_name:str] [region:str]",
                    group="graph",
                    aliases=["gpm"])
    def on_gpm_graph(self, event, summoner_name=None, region=None):
        """Displays a graph of the league games played per month per year"""
        region = LeagueHelper.validate_region(region, event)
        if region:
            gpm_graph = GamesPerMonthGraph(self.league_helper.watcher, region)
            if summoner_name is not None:
                filepath = "gpm-" + summoner_name + ".png"
            else:
                filepath = "gpm-default.png"
            self._graph_renderer(event,
                                 gpm_graph,
                                 summoner_name,
                                 region,
                                 filepath,
                                 match_validation=True)

    @Plugin.command("champion_mastery",
                    "[summoner_name:str] [region:str]",
                    group="graph",
                    aliases=["cm"])
    def on_cm_graph(self, event, summoner_name=None, region=None):
        """Displays a graph of the summoners top 5 champions by mastery"""
        region = LeagueHelper.validate_region(region, event)
        if region:
            cm_graph = ChampionMasteryGraph(self.league_helper.watcher, region,
                                            LeagueHelper.get_champion_data())
            if summoner_name is not None:
                filepath = "cm-" + summoner_name + ".png"
            else:
                filepath = "cm-default.png"
            self._graph_renderer(event, cm_graph, summoner_name, region,
                                 filepath)

    @Plugin.command("champion_wins",
                    "[summoner_name:str] [region:str]",
                    group="graph",
                    aliases=["cw"])
    def on_cw_graph(self, event, summoner_name=None, region=None):
        """Displays a graph of your wins per individual champion over the last 20 games played"""
        region = LeagueHelper.validate_region(region, event)

        if region:
            cw_graph = ChampionWinsGraph(self.league_helper.watcher, region,
                                         LeagueHelper.get_champion_data())
            if summoner_name is not None:
                filepath = "cw-" + summoner_name + ".png"
            else:
                filepath = "cw-default.png"
            self._graph_renderer(event,
                                 cw_graph,
                                 summoner_name,
                                 region,
                                 filepath,
                                 match_validation=True)

    @Plugin.command("kill_participation",
                    "[summoner_name:str] [region:str]",
                    group="graph",
                    aliases=["kp"])
    def on_kp_graph(self, event, summoner_name=None, region=None):
        """Displays a graph of your kill participation percentage over the last 20 games played"""
        region = LeagueHelper.validate_region(region, event)
        if region:
            kp_graph = KillParticipationGraph(self.league_helper.watcher,
                                              region,
                                              LeagueHelper.get_champion_data())
            if summoner_name is not None:
                filepath = "kp-" + summoner_name + ".png"
            else:
                filepath = "kp-default.png"
            self._graph_renderer(event,
                                 kp_graph,
                                 summoner_name,
                                 region,
                                 filepath,
                                 match_validation=True)

    '''
    @Plugin.command("living_time_vs_gold", "<region:str> <summoner_name:str...>", group="graph", aliases=["ltg"])
    def on_ltg_graph(self, event, region, summoner_name):
        """Displays a scatter graph of your longest living time against your total gold earned for 100 recent games"""
        region = LeagueHelper.validate_region(region)
        if self._validate_region(event, region):
            ltg_graph = LivingTimeGold(self.league_helper.watcher, region, LeagueHelper.get_champion_data())
            filepath = "ltg-" + summoner_name + ".png"
            self._graph_renderer(event, ltg_graph, summoner_name, region, filepath, match_validation=True) 
    '''

    def _graph_renderer(self,
                        event,
                        graph,
                        summoner_name,
                        region,
                        filepath,
                        match_validation=False):

        if summoner_name is None and LiveDataHelper.user_is_bound(
                LiveDataHelper.load_summoner_binds(), str(
                    event.msg.author.id)):
            summoner_tuple = LiveDataHelper.load_summoner_binds()[str(
                event.msg.author.id)]
            summoner_name = summoner_tuple[0]
            region = summoner_tuple[1]
            graph.set_region(region)

        if not self.league_helper.has_match_history(
                region, summoner_name) and match_validation:
            event.msg.reply(
                "The summoner `" + summoner_name +
                "` does not exist on the region `" + region +
                "` or does not have enough games in their match history. Try again with a different summoner!"
            )
            return
        elif self.league_helper.user_exists(region, summoner_name, event):
            event.msg.reply("Loading " + summoner_name +
                            "'s data... :hourglass_flowing_sand:")
            result = graph.render(summoner_name, filepath)
            event.msg.reply(attachments=[(filepath, open(filepath, "rb"))])

            if result is not None:
                event.msg.reply(result)

            os.remove(filepath)
示例#26
0
class GameInfoCommands(Plugin):
    def load(self, ctx):
        super(GameInfoCommands, self).load(ctx)
        self.league_helper = LeagueHelper()

    @Plugin.pre_command()
    def on_command_event(self, command, event, args, kwargs):
        CacheHelper.log_command(command, event)
        return event

    @Plugin.command("patch", "[version:str]")
    def on_patch(self, event, version=None):
        '''Displays the latest patch notes for League of Legends'''
        s = "."
        if not version:
            version = s.join(LeagueHelper.get_champion_data()["version"].split(
                ".", 2)[:2])

        version_url = version.replace(".", "")
        patch_url = "http://na.leagueoflegends.com/en/news/game-updates/patch/patch-" + version_url + "-notes"
        version_url = "http://ddragon.leagueoflegends.com/api/versions.json"

        with urllib.request.urlopen(version_url) as url:
            raw_json = json.loads(url.read().decode())

        versionExists = False
        for patch in raw_json:
            if patch.startswith(version):
                versionExists = True

        if not versionExists:
            event.msg.reply(
                "This is not a valid patch number. Try ~patch for the most recent patch notes!"
            )
            return

        embed = CacheHelper.getZileanEmbed(
            title="League of Legends Patch Notes",
            description=version + " Patch Notes",
            footer=version + " Patch Notes")
        embed.add_field(name="Notes", value=patch_url)
        event.msg.reply(embed=embed)

    @Plugin.command("status", "[region:str]")
    def on_status(self, event, region=None):
        '''Displays the status of the league of legends servers. Use ~status (region) for a more detailed breakdown'''

        if region:
            self._display_region_status(event, region)
            return

        embed = CacheHelper.getZileanEmbed(
            title="League of Legends Server Status",
            description=
            "Use ~status [region] for a more detailed breakdown of server status! Displayed below is the game status",
            footer="League of Legends Server Status")
        for endpoint in LeagueHelper.API_ENDPOINTS:
            endpoint_status = self.league_helper.watcher.lol_status.shard_data(
                endpoint)
            embed.add_field(name=endpoint_status["name"] + " (" +
                            endpoint_status["slug"].upper() + ")",
                            value=self._emojify_status(
                                endpoint_status["services"][0]["status"]),
                            inline=True)

        event.msg.reply(embed=embed)

    def _emojify_status(self, status):
        if status == "online":
            return ":white_check_mark:"
        else:
            return ":no_entry_sign:"

    def _display_region_status(self, event, region):
        region = LeagueHelper.validate_region(region)

        if region is None:
            event.msg.reply(
                "Please enter a valid **region**: *EUW, NA, EUN, JP, LAN, LAS, OCE, TR, RU, KR* :warning:"
            )
            return

        embed = CacheHelper.getZileanEmbed(
            title="Zilean Bot",
            footer="League of Legends Server Status for " + region,
            description="Type ~status to see every regions status!")
        endpoint_status = self.league_helper.watcher.lol_status.shard_data(
            region)
        embed.add_field(name=endpoint_status["name"] + " (" +
                        endpoint_status["slug"].upper() + ")",
                        value="Server Status")

        services = endpoint_status["services"]
        for service in endpoint_status["services"]:
            embed.add_field(name=service["name"],
                            value=self._emojify_status(service["status"]),
                            inline=True)

            if len(service["incidents"]) != 0:
                embed.add_field(name="Incidents",
                                value=str(len(service["incidents"])),
                                inline=True)
                incident_msg = ""
                for incident in service["incidents"]:
                    if len(incident["updates"]) != 0:
                        recent_update = incident["updates"][0]
                        incident_msg += incident["created_at"][
                            0:10] + " " + recent_update["severity"].upper(
                            ) + ": " + recent_update["content"] + "\n"
                        embed.add_field(name="Incident Description",
                                        value=incident_msg,
                                        inline=True)
            else:
                embed.add_field(name="Incidents",
                                value="No incidents!",
                                inline=True)
                embed.add_field(name="Incident Description",
                                value="N/A",
                                inline=True)

        event.msg.reply(embed=embed)

    @Plugin.command('live_game', '"[summoner_name:str] [region:str]"')
    def on_live_game(self, event, summoner_name=None, region=None):
        '''Displays the live game info if a summoner is in a game. Supports all game types and ranked modes'''

        # Prevent command quit on no region given if the discord user has bound a summoner to there account
        if region is None and summoner_name is None and LiveDataHelper.user_is_bound(
                LiveDataHelper.load_summoner_binds(), str(
                    event.msg.author.id)):
            region = LiveDataHelper.get_user_bound_region(
                str(event.msg.author.id))

        region = LeagueHelper.validate_region(region, event)
        if region is None:
            return

        summoner = self.league_helper.user_exists(region, summoner_name, event,
                                                  event.msg.author.id)

        if summoner:
            spectate_info = self.league_helper.user_in_game(
                region, summoner["id"])
            if spectate_info:
                game_info = GameInfo(self.league_helper)
                game_info.display_live_game(event.msg.channel, region,
                                            spectate_info)
            else:
                event.msg.reply("This summoner `" + summoner["name"] + " " +
                                region + "` is not currently in a game!")

    @Plugin.command("match_history",
                    "[summoner_name:str] [region:str] [game_number:int]")
    def on_recent_game(self,
                       event,
                       summoner_name=None,
                       region=None,
                       game_number=0):
        '''Displays a match in the summoners match history, by default displays the most recent game'''

        game_number = game_number - 1

        if game_number < 0:
            game_number = 0

        # If we want users to have a summoner bound to them we have to deal with the game number being passed as the summoner_name...
        if region is None and LiveDataHelper.user_is_bound(
                LiveDataHelper.load_summoner_binds(), str(
                    event.msg.author.id)):
            region = LiveDataHelper.get_user_bound_region(
                str(event.msg.author.id))
            try:
                game_number = int(summoner_name)
                game_number = game_number - 1
                if game_number < 0:
                    game_number = 0
                summoner_name = None
            except ValueError as err:
                pass
            except TypeError as err:
                pass

        # If we want users to choose a match history game and use the default region for the server
        # Then the game number is actually passed to the region variable
        # So we swap them or just leave it if the game number they has passed is not an int
        if LiveDataHelper.guild_has_region(
                LiveDataHelper.load_region_binds(), str(
                    event.guild.id)) and region is not None:
            try:
                game_number = int(region)
                game_number = game_number - 1
                if game_number < 0:
                    game_number = 0
                region = None
            except ValueError as err:
                pass
            except TypeError as err:
                pass

        region = LeagueHelper.validate_region(region, event)
        if region is None:
            return

        summoner = self.league_helper.user_exists(region, summoner_name, event,
                                                  event.msg.author.id)
        if not summoner:
            return

        # TODO: has_match_history returns false if history < 20, need to change this...
        if not self.league_helper.has_match_history(region, summoner["name"]):
            event.msg.reply(
                "This summoner has no valid match history at this time `" +
                region + "`")
            return

        matchlist = self.league_helper.watcher.match.matchlist_by_account(
            region, summoner["accountId"])

        if game_number > len(matchlist["matches"]):
            event.msg.reply(
                "The game number entered has exceeded the number of games available `Max Games: "
                + str(len(matchlist["matches"])) + "`")
            return
        else:
            game_info = GameInfo(self.league_helper)
            match = self.league_helper.watcher.match.by_id(
                region, matchlist["matches"][game_number]["gameId"])
            game_info.display_past_game(event.msg.channel, region, match,
                                        summoner["accountId"])

    @Plugin.command("item", "<item_name:str...>")
    def on_item(self, event, item_name):
        '''Searches and displays the corresponding league of legends item'''
        items = LeagueHelper.get_item_data()
        game_info = GameInfo(self.league_helper)
        item_found = False

        for key, value in items["data"].items():
            if item_name.lower() in value["name"].lower(
            ) and len(item_name) > 3:
                game_info.display_item(event.msg.channel, items["version"],
                                       items["data"][key])
                item_found = True

        if not item_found:
            event.msg.reply("This item does not exist...")

    @Plugin.command("champion", "<champion_name:str...>")
    def on_champion(self, event, champion_name):
        '''Searches and displays the corresponding league of legends champion'''
        champions = LeagueHelper.get_champion_data()
        game_info = GameInfo(self.league_helper)
        champ_found = False

        for key, name in champions["keys"].items():
            if champion_name.lower() == name.lower():
                game_info.display_champ(event.msg.channel,
                                        champions["version"],
                                        champions["data"][name])
                champ_found = True

        if not champ_found:
            event.msg.reply(
                "This champion does not exist! Try ~champion Akali as an example..."
            )

    @Plugin.command("ability", "<champion_name:str>, [ability:str]")
    def on_ability(self, event, champion_name, ability="all"):
        ''' Displays information about a specific champions ability '''
        champions = LeagueHelper.get_champion_data()
        game_info = GameInfo(self.league_helper)
        abilities = ["q", "w", "e", "r", "passive", "all"]
        champ_found = False

        if ability.lower() in ["ult", "ultimate"]:
            ability = "r"
        elif ability.lower() not in abilities:
            event.msg.reply(
                "This is not a valid ability, Try from one of these " +
                str(abilities))
            return

        for key, name in champions["keys"].items():
            if champion_name.lower() == name.lower():
                champ_found = True
                if ability == "all":
                    game_info.display_champ(event.msg.channel,
                                            champions["version"],
                                            champions["data"][name])
                else:
                    game_info.display_ability(event.msg.channel,
                                              champions["version"],
                                              champions["data"][name], ability)

        if not champ_found:
            event.msg.reply(
                "This champion does not exist! Try ~ability Akali Q as an example..."
            )

    @Plugin.command("summoner", "[summoner_name:str] [region:str]")
    def on_summoner(self, event, summoner_name=None, region=None):
        '''Displays information about a League of Legends summoner'''
        # TODO: Tidy this up...

        # Prevent command quit on no region given if the discord user has bound a summoner to there account
        if region is None and summoner_name is None and LiveDataHelper.user_is_bound(
                LiveDataHelper.load_summoner_binds(), str(
                    event.msg.author.id)):
            region = LiveDataHelper.get_user_bound_region(
                str(event.msg.author.id))

        region = LeagueHelper.validate_region(region, event)
        if region is None:
            return

        summoner = self.league_helper.user_exists(region, summoner_name, event,
                                                  event.msg.author.id)
        if not summoner:
            return

        version = LeagueHelper.get_champion_data()["version"]
        embed = CacheHelper.getZileanEmbed(
            title="Summoner Profile: ",
            footer="Displaying summoner info for " + summoner["name"],
            description=summoner["name"] + " " + region)
        embed.set_thumbnail(url="http://ddragon.leagueoflegends.com/cdn/" +
                            version + "/img/profileicon/" +
                            str(summoner["profileIconId"]) + ".png")
        embed.add_field(name="Summoner Level",
                        value=str(summoner["summonerLevel"]))
        ranked_positions = self.league_helper.watcher.league.positions_by_summoner(
            region, summoner["id"])

        ranks_array = ["RANKED SOLO 5x5", "RANKED FLEX TT", "RANKED FLEX SR"]
        for rank in ranked_positions:
            rank_name = rank["queueType"].replace("_", " ")
            embed.add_field(name="Queue Type", value=rank_name, inline=True)
            ranks_array.remove(rank_name)

            winrate = round(
                (rank["wins"] / (rank["wins"] + rank["losses"])) * 100)
            rank_msg = rank["tier"] + " " + rank["rank"] + " (" + str(
                rank["leaguePoints"]) + "lp)"
            winrate_msg = " | " + str(winrate) + "%"
            winloss_msg = " | W:" + str(rank["wins"]) + " L:" + str(
                rank["losses"])

            embed.add_field(name="Rank | Wins/Losses | Winrate",
                            value=rank_msg + winloss_msg + winrate_msg,
                            inline=True)

        for rank in ranks_array:
            embed.add_field(name="Queue Type", value=rank, inline=True)
            embed.add_field(name="Rank | Wins/Losses | Winrate",
                            value="UNRANKED",
                            inline=True)

        try:
            matchlist = self.league_helper.watcher.match.matchlist_by_account(
                region, summoner["accountId"])
            match = self.league_helper.watcher.match.by_id(
                region, matchlist["matches"][0]["gameId"])

            for participant in match["participantIdentities"]:
                if participant["player"]["currentAccountId"] == summoner[
                        "accountId"]:
                    target_player = participant

            for participant in match["participants"]:
                if participant["participantId"] == target_player[
                        "participantId"]:
                    target_champion_id = participant["championId"]
                    target_stats = str(
                        participant["stats"]["kills"]) + "/" + str(
                            participant["stats"]["deaths"]) + "/" + str(
                                participant["stats"]["assists"])
                    target_team = participant["teamId"]

            for team in match["teams"]:
                if team["teamId"] == target_team:
                    match_outcome = team["win"]

            if match_outcome == "Fail":
                match_outcome = "Defeat :x:"
            else:
                match_outcome = "Victory :white_check_mark:"

            target_champion = LeagueHelper.get_champion_data()["keys"][str(
                target_champion_id)]
            embed.add_field(
                name="Last Game Played:",
                value="**" + match_outcome + "**\n" + target_champion + " " +
                target_stats +
                " http://matchhistory.euw.leagueoflegends.com/en/#match-details/"
                + region + "/" + str(match["gameId"]) + "/" +
                str(summoner["accountId"]) + "?tab=overview")

        except HTTPError as err:
            if err.response.status_code == 404:
                embed.add_field(
                    name="Last Game Played",
                    value="This summoner has not recently played a game.")

        if not self.league_helper.user_in_game(region, summoner["id"]):
            embed.add_field(
                name="Live Game",
                value="This summoner is not currently in a live game.")
        else:
            embed.add_field(
                name="Live Game",
                value="This summoner is in a live game, type ~live_game " +
                region + " " + summoner_name + " for more info.")

        event.msg.reply(embed=embed)

    @Plugin.command("build", "<champion_name:str>")
    def on_build(self, event, champion_name):
        '''Displays the highest winrate championGG build for the given champion'''
        champions = LeagueHelper.get_champion_data()
        champ_found = False

        for key, name in champions["keys"].items():
            if champion_name.lower() == name.lower():
                champion_builder = ChampionGGHelper()
                champion_builder.generate_build(event, champions["data"][name],
                                                champions["version"])
                champ_found = True

        if not champ_found:
            event.msg.reply(
                "This champion does not exist! Try ~champion Akali as an example..."
            )
示例#27
0
    def on_recent_game(self,
                       event,
                       summoner_name=None,
                       region=None,
                       game_number=0):
        '''Displays a match in the summoners match history, by default displays the most recent game'''

        game_number = game_number - 1

        if game_number < 0:
            game_number = 0

        # If we want users to have a summoner bound to them we have to deal with the game number being passed as the summoner_name...
        if region is None and LiveDataHelper.user_is_bound(
                LiveDataHelper.load_summoner_binds(), str(
                    event.msg.author.id)):
            region = LiveDataHelper.get_user_bound_region(
                str(event.msg.author.id))
            try:
                game_number = int(summoner_name)
                game_number = game_number - 1
                if game_number < 0:
                    game_number = 0
                summoner_name = None
            except ValueError as err:
                pass
            except TypeError as err:
                pass

        # If we want users to choose a match history game and use the default region for the server
        # Then the game number is actually passed to the region variable
        # So we swap them or just leave it if the game number they has passed is not an int
        if LiveDataHelper.guild_has_region(
                LiveDataHelper.load_region_binds(), str(
                    event.guild.id)) and region is not None:
            try:
                game_number = int(region)
                game_number = game_number - 1
                if game_number < 0:
                    game_number = 0
                region = None
            except ValueError as err:
                pass
            except TypeError as err:
                pass

        region = LeagueHelper.validate_region(region, event)
        if region is None:
            return

        summoner = self.league_helper.user_exists(region, summoner_name, event,
                                                  event.msg.author.id)
        if not summoner:
            return

        # TODO: has_match_history returns false if history < 20, need to change this...
        if not self.league_helper.has_match_history(region, summoner["name"]):
            event.msg.reply(
                "This summoner has no valid match history at this time `" +
                region + "`")
            return

        matchlist = self.league_helper.watcher.match.matchlist_by_account(
            region, summoner["accountId"])

        if game_number > len(matchlist["matches"]):
            event.msg.reply(
                "The game number entered has exceeded the number of games available `Max Games: "
                + str(len(matchlist["matches"])) + "`")
            return
        else:
            game_info = GameInfo(self.league_helper)
            match = self.league_helper.watcher.match.by_id(
                region, matchlist["matches"][game_number]["gameId"])
            game_info.display_past_game(event.msg.channel, region, match,
                                        summoner["accountId"])
示例#28
0
 def load(self, ctx):
     super(GameInfoCommands, self).load(ctx)
     self.league_helper = LeagueHelper()