Exemple #1
0
class MTJikan(API):
    calls_minute = None
    calls_second = None
    last_api_call = None

    def __init__(
        self,
        selected_base: Optional[str] = None,
        session: Optional[requests.Session] = None,
    ) -> None:
        self.jikan = Jikan()

    @classmethod
    def initialize(cls):
        super().__init__(2, 30)

    def search(
        self,
        search_type: str,
        query: str,
        page: Optional[int] = None,
        parameters: Optional[Mapping[str, Optional[Union[int, str,
                                                         float]]]] = None,
    ) -> Dict[str, Any]:
        super()._check_rate_seconds()
        super()._check_rate_minutes()

        MTJikan.calls_second += 1
        MTJikan.calls_minute += 1
        MTJikan.last_api_call = datetime.now()
        search_results = self.jikan.search(search_type, query, page,
                                           parameters)
        return search_results["results"]

    def manga(self,
              id: int,
              extension: Optional[str] = None,
              page: Optional[int] = None) -> Dict[str, Any]:
        super()._check_rate_seconds()
        super()._check_rate_minutes()

        MTJikan.calls_second += 1
        MTJikan.calls_minute += 1
        MTJikan.last_api_call = datetime.now()
        search_results = self.jikan.manga(id, extension, page)
        search_results["source"] = "MAL"
        search_results["id"] = str(id)
        search_results["url"] = r"https://myanimelist.net/manga/" + str(id)
        return search_results
Exemple #2
0
from jikanpy import Jikan
from pprint import pprint

jikan = Jikan()

mushishi = jikan.anime(457)
pprint(mushishi)

fma = jikan.manga(25)
pprint(fma)

ginko = jikan.character(425)
pprint(ginko)

kana_hanazawa = jikan.person(189)
pprint(kana_hanazawa)

naruto = jikan.search(search_type='anime', query='naruto')
pprint(naruto)

winter_2018 = jikan.season(year=2018, season='winter')
pprint(winter_2018)

archive = jikan.season_archive()
pprint(archive)

later = jikan.season_later()
pprint(later)

monday = jikan.schedule(day='monday')
pprint(monday)
Exemple #3
0
class UserCog(commands.Cog):
    """
    UserCog: handles all the user-related logic.
    """

    def __init__(self, bot):
        """
        Constructor: initialize the cog.

        :param bot: The Discord bot.
        """
        self.bot = bot
        self.discordUser = None
        self.malUser = None
        self.channel = None
        self.jikan = Jikan()

    @commands.command(brief='Ping the bot')
    async def ping(self, ctx):
        """
        Ping the bot.

        :param ctx: The context.
        """
        await ctx.send(f'Pong: {round(self.bot.latency*1000)}ms')

    def start(self):
        """
        Start the UserCog:
            - retrieves the user from the database, if possible
            - start the updateMalProfileLoop
        """
        user = self.bot.get_cog('DatabaseCog').getUser()
        if user:
            try:
                self.malUser = self._getMALProfile(user['mal'])
            except jikanpy.exceptions.APIException:
                pass
            self.discordUser = self._getMember(user['discord'])
            self.channel = self._getChannel(user['channel'])
            self.bot.command_prefix = user['prefix']

        self.updateMalProfileLoop.start()

    def _getMALProfile(self, username):
        """
        Get the MyAnimeList user object, given the username.

        :param username: The username of the MAL account.
        :return: The MAL user.
        """
        return self.jikan.user(username=username)

    def _updateMALProfile(self, profile):
        """
        Update the internal MAL user, i.e. updating the watching/reading list.

        :param profile: The username of the MAL account.
        """
        try:
            newAnimeList = []
            watching = self.jikan.user(username=profile, request='animelist', argument='watching')['anime']
            ptw = self.jikan.user(username=profile, request='animelist', argument='ptw')['anime']
            for anime in watching + ptw:
                anime['title_english'] = self.jikan.anime(anime['mal_id'])['title_english']
                newAnimeList.append(anime)

            newMangaList = []
            reading = self.jikan.user(username=profile, request='mangalist', argument='reading')['manga']
            ptr = self.jikan.user(username=profile, request='mangalist', argument='ptr')['manga']
            for manga in reading + ptr:
                manga['title_english'] = self.jikan.manga(manga['mal_id'])['title_english']
                newMangaList.append(manga)

            # If for some reason, we cannot retrieve the new lists (e.g. API error), keep the old ones
            if newAnimeList:
                self.bot.get_cog('AnimeCog').list = newAnimeList
            if newMangaList:
                self.bot.get_cog('MangaCog').list = newMangaList

        except Exception as e:
            # There's nothing we can do :'(
            print(str(e))

    def _getMember(self, user):
        """
        Get the Discord member object, give its name and tag.

        :param user: The user (name + tag).
        :return: The member object, if none can be found, return None.
        """
        for member in self.bot.get_all_members():
            if str(member) == user:
                return member
        return None

    def _getChannel(self, channelName):
        """
        Get the Discord channel object, give the name of the channel.

        :param channelName: The name of the channel.
        :return: The channel object, if none can be found, return None.
        """
        for channel in self.bot.get_all_channels():
            if str(channel) == channelName:
                return channel
        return None

    @commands.command(brief='Set your MAL profile')
    async def setProfile(self, ctx, profile: str):
        """
        Set the internal MAL account, as well as the discord account and bot channel.

        :param ctx: The context.
        :param profile: Name of the MAL account.
        """
        try:
            self.malUser = self._getMALProfile(profile)
        except jikanpy.exceptions.APIException:
            await ctx.send(f'Unable to find user {profile}, make sure the profile is public.')
            return
        
        await ctx.send(
            'Successfully set profile, you\'ll now receive notifications for new anime episodes and manga chapters!')

        self.discordUser = ctx.author
        if self.channel is None:
            self.channel = ctx.channel

        # Store data in database
        self.bot.get_cog('DatabaseCog').addUser(profile, str(self.discordUser), str(self.channel))

        self._updateMALProfile(profile)

    @commands.command(brief='Remove your MAL profile from the bot')
    async def removeProfile(self, ctx):
        self.bot.get_cog('DatabaseCog').truncateUsers()
        self.discordUser = None
        self.malUser = None
        self.channel = None
        self.bot.get_cog('AnimeCog').list = []
        self.bot.get_cog('MangaCog').list = []
        await ctx.send('Successfully removed you from the bot!')

    @commands.command(brief='Get a brief overview of your MAL profile')
    async def getProfile(self, ctx):
        """
        Get the MAL profile in form of an embed

        :param ctx: The context.
        """
        if self.malUser:
            embed = discord.Embed(title=self.malUser['username'], color=discord.Color.green())
            embed.add_field(name="Watching/Plan-to-Watch", value=str(len(self.bot.get_cog('AnimeCog').list)))
            embed.add_field(name="Reading/Plan-to-Read", value=str(len(self.bot.get_cog('MangaCog').list)))
            embed.add_field(name="Link", value=self.malUser['url'])
            embed.set_thumbnail(url=self.malUser['image_url'])
            await ctx.send(embed=embed)
        else:
            await ctx.send("Profile is not set, please use `!setProfile <USERNAME>` first.")

    @commands.command(brief='Set the bot channel (where it will ping you)')
    async def setChannel(self, ctx, channel: discord.TextChannel):
        """
        Set the bot channel.

        :param ctx: The context.
        :param channel: Name of the bot channel.
        """
        self.channel = channel
        self.bot.get_cog('DatabaseCog').addUser(self.malUser['username'], str(self.discordUser), str(channel))
        await ctx.send(f'Successfully set bot channel to {channel.mention}.')

    @commands.command(brief='Set the prefix of the bot')
    async def setPrefix(self, ctx, prefix: str):
        """
        Set the prefix of the bot

        :param ctx: The context.
        :param prefix: The new prefix for the bot.
        """
        self.bot.command_prefix = prefix
        self.bot.get_cog('DatabaseCog').addUser(self.malUser['username'], str(self.discordUser), str(self.channel), prefix)
        await ctx.send(f'Successfully set the prefix to `{prefix}`.')

    @setChannel.error
    async def setChannelError(self, ctx, error):
        """
        Error Handler for setChannel.

        :param ctx: The context.
        :param error: The error raised.
        """
        await ctx.send(error.args[0])

    @tasks.loop(hours=1)
    async def updateMalProfileLoop(self):
        """
        Loop that periodically updates the MAL account, i.e. update watching/reading list.
        """
        if self.malUser:
            await self._updateMALProfile(self.malUser['username'])