Esempio n. 1
0
class TafsirEnglish(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    async def send_embed(self, ctx, spec):
        if spec.num_pages == 1:
            return await ctx.send(embed=spec.embed)

        # If there are multiple pages, construct buttons for their navigation.
        buttons = [
            manage_components.create_button(style=ButtonStyle.grey,
                                            label="Previous Page",
                                            emoji="⬅",
                                            custom_id="tafsir_previous_page"),
            manage_components.create_button(style=ButtonStyle.green,
                                            label="Next Page",
                                            emoji="➡",
                                            custom_id="tafsir_next_page")
        ]
        action_row = manage_components.create_actionrow(*buttons)
        await ctx.send(embed=spec.embed, components=[action_row])

        while True:
            try:
                button_ctx = await manage_components.wait_for_component(
                    self.bot, components=action_row, timeout=600)
                if button_ctx.custom_id == 'tafsir_previous_page':
                    if spec.page > 1:
                        spec.page -= 1
                    else:
                        spec.page = spec.num_pages
                    await spec.make_embed()
                    await button_ctx.edit_origin(embed=spec.embed)
                elif button_ctx.custom_id == 'tafsir_next_page':
                    if spec.page < spec.num_pages:
                        spec.page += 1
                    else:
                        spec.page = 1
                    await spec.make_embed()
                    await button_ctx.edit_origin(embed=spec.embed)

            except asyncio.TimeoutError:
                break

    async def process_request(self, ref: str, tafsir: str, page: int):
        spec = TafsirSpecifics(tafsir, ref, page)
        try:
            await spec.get_text()
        except IndexError:
            # If no entry was found in the default tafsir (Maarif-ul-Quran), fall back to Tafsir al-Jalalayn.
            if tafsir == 'maarifulquran':
                return await self.process_request(ref, 'jalalayn', page)
            else:
                raise NoText

        if len(spec.text) == 0:
            raise NoText

        await spec.make_embed()
        return spec

    @commands.command(name='tafsir')
    async def tafsir(self,
                     ctx,
                     ref: str,
                     tafsir: str = "maarifulquran",
                     page: int = 1):
        spec = await self.process_request(ref, tafsir, page)
        await self.send_embed(ctx, spec)

    @cog_ext.cog_slash(
        name="tafsir",
        description="Get the tafsir of a verse.",
        options=[
            create_option(name="reference",
                          description=
                          "The verse to get the tafsir of, e.g. 1:4 or 2:255.",
                          option_type=3,
                          required=True),
            create_option(name="tafsir",
                          description="The name of the tafsir.",
                          option_type=3,
                          required=False,
                          choices=generate_choices_from_dict(name_mappings))
        ])
    async def slash_tafsir(self,
                           ctx: SlashContext,
                           ref: str,
                           tafsir: str = "maarifulquran"):
        spec = await self.process_request(ref, tafsir, 1)
        await self.send_embed(ctx, spec)

    @tafsir.error
    async def on_tafsir_error(self, ctx, error):
        if isinstance(error, MissingRequiredArgument):
            await ctx.send(INVALID_ARGUMENTS.format(ctx.prefix))
        elif isinstance(error, InvalidReference):
            await ctx.send(INVALID_ARGUMENTS.format(ctx.prefix))
        elif isinstance(error, InvalidAyah):
            await ctx.send(INVALID_AYAH.format(error.num_verses))
        elif isinstance(error, InvalidSurah):
            await ctx.send(INVALID_SURAH)
        elif isinstance(error, InvalidTafsir):
            await ctx.send(INVALID_TAFSIR)
        elif isinstance(error, NoText):
            await ctx.send(NO_TEXT)
        elif isinstance(error, BadAlias):
            await ctx.send(BAD_ALIAS)
Esempio n. 2
0
class HadithCommands(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    async def abstract_hadith(self, channel, collection_name, ref, lang):

        if collection_name not in HADITH_COLLECTION_LIST:
            raise InvalidCollection

        if collection_name in hadith_collection_aliases:
            collection_name = hadith_collection_aliases[collection_name]

        hadith = HadithSpecifics(collection_name, ref, lang)
        try:
            embed = await hadith.fetch_hadith()
        except InvalidHadith:
            return await channel.send(
                "Sorry, no hadith with this number could be found.")

        if hadith.num_pages == 1:
            return await channel.send(embed=embed)

        # If there are multiple pages, construct buttons for their navigation.
        buttons = [
            manage_components.create_button(style=ButtonStyle.grey,
                                            label="Previous Page",
                                            emoji="⬅",
                                            custom_id="hadith_previous_page"),
            manage_components.create_button(style=ButtonStyle.green,
                                            label="Next Page",
                                            emoji="➡",
                                            custom_id="hadith_next_page")
        ]
        action_row = manage_components.create_actionrow(*buttons)
        await channel.send(embed=embed, components=[action_row])

        while True:
            try:
                button_ctx = await manage_components.wait_for_component(
                    self.bot, components=action_row, timeout=600)
                if button_ctx.custom_id == 'hadith_previous_page':
                    if hadith.page > 1:
                        hadith.page -= 1
                    else:
                        hadith.page = hadith.num_pages
                    em = hadith.make_embed()
                    await button_ctx.edit_origin(embed=em)
                elif button_ctx.custom_id == 'hadith_next_page':
                    if hadith.page < hadith.num_pages:
                        hadith.page += 1
                    else:
                        hadith.page = 1
                    em = hadith.make_embed()
                    await button_ctx.edit_origin(embed=em)

            except asyncio.TimeoutError:
                break

    async def _rhadith(self, ctx):
        await self.abstract_hadith(ctx, 'riyadussalihin',
                                   Reference(str(random.randint(1, 1896))),
                                   'en')

    async def _rahadith(self, ctx):
        await self.abstract_hadith(ctx, 'riyadussalihin',
                                   Reference(str(random.randint(1, 1896))),
                                   'ar')

    @commands.command(name='hadith')
    async def hadith(self, ctx, collection_name: str, ref: Reference):
        await ctx.channel.trigger_typing()
        await self.abstract_hadith(ctx, collection_name.lower(), ref, 'en')

    @commands.command(name='ahadith')
    async def ahadith(self, ctx, collection_name: str, ref: Reference):
        await ctx.channel.trigger_typing()
        await self.abstract_hadith(ctx, collection_name.lower(), ref, 'ar')

    @commands.command(name="rhadith")
    async def rhadith(self, ctx):
        await ctx.channel.trigger_typing()
        await self._rhadith(ctx)

    @commands.command(name="rahadith")
    async def rahadith(self, ctx):
        await ctx.channel.trigger_typing()
        await self._rahadith(ctx)

    @hadith.error
    async def hadith_error(self, ctx, error):
        if isinstance(error, commands.MissingRequiredArgument):
            await ctx.send(INVALID_INPUT.format(ctx.prefix))
        elif isinstance(error, InvalidCollection):
            await ctx.send(INVALID_COLLECTION)

    @ahadith.error
    async def ahadith_error(self, ctx, error):
        if isinstance(error, commands.MissingRequiredArgument):
            await ctx.send(INVALID_INPUT.format(f'{ctx.prefix}a'))
        elif isinstance(error, InvalidCollection):
            await ctx.send(INVALID_COLLECTION)

    @cog_ext.cog_slash(
        name="hadith",
        description="Send hadith in English from sunnah.com.",
        options=[
            create_option(name="hadith_collection",
                          description="The name of the hadith collection.",
                          option_type=3,
                          required=True,
                          choices=generate_choices_from_dict(
                              english_hadith_collections)),
            create_option(name="hadith_number",
                          description="The number of the hadith.",
                          option_type=3,
                          required=True)
        ])
    async def slash_hadith(self, ctx: SlashContext, hadith_collection: str,
                           hadith_number: str):
        await ctx.defer()
        await self.abstract_hadith(ctx, hadith_collection,
                                   Reference(hadith_number), 'en')

    @cog_ext.cog_slash(
        name="ahadith",
        description="Send hadith in Arabic from sunnah.com.",
        options=[
            create_option(
                name="hadith_collection",
                description="The name of the hadith collection.",
                option_type=3,
                required=True,
                choices=generate_choices_from_dict(arabic_hadith_collections)),
            create_option(name="hadith_number",
                          description="The number of the hadith.",
                          option_type=3,
                          required=True)
        ])
    async def slash_ahadith(self, ctx: SlashContext, hadith_collection: str,
                            hadith_number: str):
        await ctx.defer()
        await self.abstract_hadith(ctx, hadith_collection,
                                   Reference(hadith_number), 'ar')

    @cog_ext.cog_slash(
        name="rhadith",
        description="Send a random hadith in English from sunnah.com.")
    async def slash_rhadith(self, ctx: SlashContext):
        await ctx.defer()
        await self._rhadith(ctx)

    @cog_ext.cog_slash(
        name="rahadith",
        description="Send a random hadith in Arabic from sunnah.com.")
    async def slash_rahadith(self, ctx: SlashContext):
        await ctx.defer()
        await self._rahadith(ctx)

    def findURL(self, message):
        urls = re.findall(r'(https?://\S+)', message)
        for link in urls:
            if "sunnah.com/" in link:
                return link

    @cog_ext.cog_context_menu(target=ContextMenuType.MESSAGE,
                              name="Get Hadith Text")
    async def get_hadith_text(self, ctx: MenuContext):
        content = ctx.target_message.content
        url = self.findURL(content)
        if url:
            try:
                meta = url.split("/")
                collection = meta[3]
                if collection in hadith_collection_aliases:
                    collection = hadith_collection_aliases[collection]
                if ":" in collection:  # For urls like http://sunnah.com/bukhari:1
                    if collection[-1] == "/":  # if url ended with /
                        collection = collection[:-1]
                    ref = collection.split(":")[1]  # getting hadith number
                    ref = Reference(ref)
                    collection = collection.split(":")[0]  # getting book name
                else:
                    book = meta[4]
                    try:
                        hadith = meta[5]
                        ref = f"{book}:{hadith}"
                        ref = Reference(ref)
                    except:
                        ref = Reference(
                            book
                        )  # For hadith collections which are a single 'book' long (e.g. 40 Hadith Nawawi)
                await self.abstract_hadith(ctx, collection, ref, "en")
            except InvalidHadith:
                await ctx.send("**There is no valid sunnah.com link here**")
        else:
            await ctx.send("**There is no valid sunnah.com link here**")

    @commands.Cog.listener()
    async def on_message(self, message):
        content = message.content
        url = self.findURL(content)
        if url:
            meta = url.split("/")
            collection = meta[3]
            if collection in hadith_collection_aliases:
                collection = hadith_collection_aliases[collection]
            if ":" in collection:  # For urls like http://sunnah.com/bukhari:1
                if collection[-1] == "/":  # if url ended with /
                    collection = collection[:-1]
                ref = collection.split(":")[1]  # getting hadith number
                ref = Reference(ref)
                collection = collection.split(":")[0]  # getting book name
            else:
                book = meta[4]
                try:
                    hadith = meta[5]
                    ref = f"{book}:{hadith}"
                    ref = Reference(ref)
                except:
                    ref = Reference(
                        book
                    )  # For hadith collections which are a single 'book' long (e.g. 40 Hadith Nawawi)
            await self.abstract_hadith(message.channel, collection, ref, "en")
Esempio n. 3
0
class TafsirEnglish(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    async def send_embed(self, ctx, spec):
        msg = await ctx.send(embed=spec.embed)
        if spec.num_pages > 1:
            await msg.add_reaction(emoji='⬅')
            await msg.add_reaction(emoji='➡')

        while True:
            try:
                reaction, user = await self.bot.wait_for(
                    "reaction_add",
                    timeout=300,
                    check=lambda reaction, user:
                    (reaction.emoji == '➡' or reaction.emoji == '⬅') and user
                    != self.bot.user and reaction.message.id == msg.id)

            except asyncio.TimeoutError:
                await msg.remove_reaction(emoji='➡', member=self.bot.user)
                await msg.remove_reaction(emoji='⬅', member=self.bot.user)
                break

            if reaction.emoji == '➡' and spec.page:
                spec.page += 1
                if spec.page > spec.num_pages:
                    spec.page = 1

            if reaction.emoji == '⬅':
                spec.page -= 1
                if spec.page < 1:
                    spec.page = spec.num_pages

            await spec.make_embed()
            await msg.edit(embed=spec.embed)
            try:
                await msg.remove_reaction(reaction.emoji, user)
            # The above fails if the bot doesn't have the "Manage Messages" permission, but it can be safely ignored
            # as it is not essential functionality.
            except discord.ext.commands.errors.CommandInvokeError:
                pass

    async def process_request(self, ref: str, tafsir: str, page: int):
        spec = TafsirSpecifics(tafsir, ref, page)
        try:
            await spec.get_text()
        except IndexError:
            # If no entry was found in the default tafsir (Maarif-ul-Quran), fall back to Tafsir al-Jalalayn.
            if tafsir == 'maarifulquran':
                return await self.process_request(ref, 'jalalayn', page)
            else:
                raise NoText

        if len(spec.text) == 0:
            raise NoText

        await spec.make_embed()
        return spec

    @commands.command(name='tafsir')
    async def tafsir(self,
                     ctx,
                     ref: str,
                     tafsir: str = "maarifulquran",
                     page: int = 1):
        spec = await self.process_request(ref, tafsir, page)
        print("lol")
        await self.send_embed(ctx, spec)

    @cog_ext.cog_slash(
        name="tafsir",
        description="Get the tafsir of a verse.",
        options=[
            create_option(name="reference",
                          description=
                          "The verse to get the tafsir of, e.g. 1:4 or 2:255.",
                          option_type=3,
                          required=True),
            create_option(name="tafsir",
                          description="The name of the tafsir.",
                          option_type=3,
                          required=False,
                          choices=generate_choices_from_dict(name_mappings))
        ])
    async def slash_tafsir(self,
                           ctx: SlashContext,
                           ref: str,
                           tafsir: str = "maarifulquran"):
        await ctx.defer()
        spec = await self.process_request(ref, tafsir, 1)
        await self.send_embed(ctx, spec)

    @tafsir.error
    async def on_tafsir_error(self, ctx, error):
        if isinstance(error, MissingRequiredArgument):
            await ctx.send(INVALID_ARGUMENTS.format(ctx.prefix))
        elif isinstance(error, InvalidReference):
            await ctx.send(INVALID_ARGUMENTS.format(ctx.prefix))
        elif isinstance(error, InvalidAyah):
            await ctx.send(INVALID_AYAH.format(error.num_verses))
        elif isinstance(error, InvalidSurah):
            await ctx.send(INVALID_SURAH)
        elif isinstance(error, InvalidTafsir):
            await ctx.send(INVALID_TAFSIR)
        elif isinstance(error, NoText):
            await ctx.send(NO_TEXT)
Esempio n. 4
0
class Tafsir(commands.Cog):

    def __init__(self, bot):
        self.bot = bot
        self.url = 'https://tafsir.app/{}/{}/{}'

    def make_url(self, tafsir_id, surah, ayah):
        url = self.url.format(tafsir_id, surah, ayah)
        return url

    '''
    Gets the tafir ID (for use in the URL) and Arabic name
    '''
    @staticmethod
    def get_tafsir_id(tafsir):
        tafsir_name = dictName[tafsir.lower()]
        tafsir_id = dictID[tafsir.lower()]
        return tafsir_name, tafsir_id

    '''
    Get the surah and ayah from the ref. 
    '''
    @staticmethod
    def process_ref(ref: str):
        surah, ayah = ref.split(':')
        return surah, ayah

    '''
    Gets, formats and paginates the tafsir text.
    '''
    @staticmethod
    def process_text(content, page):

        # Parse the website's source and find the tafsir text.
        soup = BeautifulSoup(content, 'html.parser')
        tag = soup.find('div', attrs={'id': 'preloaded'})
        text = tag.get_text().strip()
        text = text.replace('*', '')\
            .replace('⁕', '') \
            .replace('}', ' ﴾') \
            .replace('{', ' ﴿') \
            .replace('﴾', '﴾"')\
            .replace('﴿', '"﴿') \
            .replace('«', '"«') \
            .replace('»', '»"') \
            .replace('"ayah":', '') \
            .replace(']]', ']') \
            .replace('[[', '[')

        cleanb = re.compile('\([^)]*\)')
        text = re.sub(cleanb, '', text)

        # Paginate the text, set the embed text to the current page and calculate how many pages were made:
        try:
            pages = textwrap.wrap(text, 2034, break_long_words=False)
            text = pages[page - 1]
            num_pages = len(pages)
        except IndexError:
            return

        # Now we process the footnotes for the current page.
        # Firstly, we find all the footnotes in the text and add them to the footer text.
        footnotes = re.findall("\[(.*?)\]", text)
        footer = []
        footnote_number = 1
        for footnote in footnotes:
            text = text.replace(footnote, '')
            footnote_number_arabic = convert_to_arabic_number(str(footnote_number))
            footer.append(f'\n({footnote_number_arabic}) {footnote}')
            footnote_number = footnote_number + 1
        footer = ''.join(footer)

        # Now we replace the footnotes in the text with a reference:
        total_footnotes = len(footnotes)
        footnote_number = 1
        for x in range(total_footnotes):
            footnote_number_arabic = convert_to_arabic_number(str(footnote_number))
            text = text.replace('[]', f'({footnote_number_arabic})', 1)
            footnote_number = footnote_number + 1

        return text, num_pages, footer

    @staticmethod
    def make_embed(text, page, tafsir_name, surah, ayah, footer, formatted_url, num_pages):

        ref = convert_to_arabic_number(f'{surah}:{ayah}')
        text = text.replace('#', '\n')
        text = f'```py\n{text}\n```'
        em = discord.Embed(title=ref, colour=0x467f05, description=text)
        if footer != '':
            em.set_footer(text=f'Page {page}/{num_pages} \n____________________________________\n{footer}')
        else:
            em.set_footer(text=f'Page {page}/{num_pages}')
        em.set_author(name=f'{tafsir_name}', url=formatted_url, icon_url=icon)

        return em

    async def _atafsir(self, ctx, ref: str, tafsir: str, page: int):
        surah, ayah = self.process_ref(ref)
        tafsir_name, tafsir_id = self.get_tafsir_id(tafsir)
        formatted_url = self.make_url(tafsir_id, surah, ayah)
        content = str(await get_site_source(formatted_url))

        try:
            text, num_pages, footer = self.process_text(content, page)
        except AttributeError:
            return await ctx.send('***عفوا، لا مواد لهذه الآية في هذا الكتاب***')

        em = self.make_embed(text, page, tafsir_name, surah, ayah, footer, formatted_url, num_pages)

        msg = await ctx.send(embed=em)
        if num_pages > 1:
            await msg.add_reaction(emoji='⬅')
            await msg.add_reaction(emoji='➡')

    @commands.command(name="atafsir")
    async def atafsir(self, ctx, ref: str, tafsir: str = "tabari", page: int = 1):
        await self._atafsir(ctx, ref, tafsir, page)

    @cog_ext.cog_slash(name="atafsir", description="تبعث تفسير أي آية, يوجد 56 تفسير متاح بالعربية",
                       options=[
                           create_option(
                               name="تفسير",
                               description="اسم التفسير.",
                               option_type=3,
                               required=True,
                               choices=generate_choices_from_dict(dictName)),
                           create_option(
                               name= "السورة_و_الآية",
                               description = "رقم السورة:رقم الآية - على سبيل المثال: 2:255",
                               option_type=3,
                               required=True)])
    async def slash_atafsir(self, ctx: SlashContext, tafsir: str, ref: str):
        await ctx.defer()
        await self._atafsir(ctx, ref, tafsir, 1)

    @commands.Cog.listener()
    async def on_reaction_add(self, reaction, user):
        if reaction.message.author == self.bot.user and user != self.bot.user:
            msg = reaction.message
            embed = msg.embeds[0]

            # Get the tafsir ID to use in the URL from its Arabic name in the embed's author:
            arabic_name = embed.author.name
            try:
                tafsir_name = dictNameReverse[arabic_name]
            except KeyError:
                return

            tafsir_id = dictID[tafsir_name]

            # Get the surah and ayah from the embed's title:
            ref = convert_from_arabic_number(embed.title)
            surah, ayah = self.process_ref(ref)

            # Get the page number from the embed footer. First we split to get the word, then again to get the current
            # page.
            page = int(embed.footer.text.split(' ')[1].split('/')[0])
            num_pages = int(embed.footer.text.split(' ')[1].split('/')[1])

            # If the reaction is the forward arrow, attempt to get the last page:
            if reaction.emoji == '➡':
                await msg.remove_reaction(emoji="➡", member=user)

                new_page = page - 1
                if new_page < 1:
                    new_page = num_pages

                formatted_url = self.make_url(tafsir_id, surah, ayah)
                content = str(await get_site_source(formatted_url))
                text, _, footer = self.process_text(content, new_page)

                em = self.make_embed(text, new_page, arabic_name, surah, ayah, footer, formatted_url, num_pages)
                await msg.edit(embed=em)
                await msg.add_reaction(emoji='⬅')

            # If the reaction is the backwards arrow, attempt to get the next page.
            elif reaction.emoji == '⬅':
                await reaction.message.remove_reaction(emoji="⬅", member=user)

                new_page = page + 1
                if new_page > num_pages:
                    new_page = 1

                formatted_url = self.make_url(tafsir_id, surah, ayah)
                content = str(await get_site_source(formatted_url))
                text, _, footer = self.process_text(content, new_page)

                em = self.make_embed(text, new_page, arabic_name, surah, ayah, footer, formatted_url, num_pages)
                await msg.edit(embed=em)
                await msg.add_reaction(emoji='➡')

    @atafsir.error
    async def on_atafsir_error(self, ctx, error):
        if isinstance(error, MissingRequiredArgument):
            await ctx.send(f"**لقد أدخلت الأمر خطأ**. اكتب `{ctx.prefix}atafsir <رقم السورة>:<رقم الآية> <اسم تفسير اختياري>`")
Esempio n. 5
0
class HadithCommands(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    FORTY_HADITH_COLLECTIONS = {'qudsi40', 'nawawi40'}

    async def abstract_hadith(self, channel, collection_name, ref, lang):

        if collection_name not in HADITH_COLLECTION_LIST:
            raise InvalidCollection

        if f'{collection_name}40' in self.FORTY_HADITH_COLLECTIONS:
            collection_name = collection_name + '40'

        hadith = HadithSpecifics(collection_name, ref, lang)
        embed = await hadith.fetch_hadith()
        msg = await channel.send(embed=embed)

        if hadith.num_pages > 1:
            await msg.add_reaction(emoji='⬅')
            await msg.add_reaction(emoji='➡')

        await msg.add_reaction(emoji='❎')

        while True:
            try:
                reaction, user = await self.bot.wait_for(
                    "reaction_add",
                    timeout=180,
                    check=lambda reaction, user:
                    (reaction.emoji == '➡' or reaction.emoji == '⬅' or reaction
                     .emoji == '❎') and user != self.bot.user and reaction.
                    message.id == msg.id)

            except asyncio.TimeoutError:
                await msg.remove_reaction(emoji='➡', member=self.bot.user)
                await msg.remove_reaction(emoji='⬅', member=self.bot.user)
                await msg.remove_reaction(emoji='❎', member=self.bot.user)
                break

            if reaction.emoji == '➡':
                if hadith.page < hadith.num_pages:
                    hadith.page += 1
                else:
                    hadith.page = 1

            if reaction.emoji == '⬅':
                if hadith.page > 1:
                    hadith.page -= 1
                else:
                    hadith.page = hadith.num_pages

            if reaction.emoji == '❎':
                return await msg.delete()

            em = hadith.make_embed()
            await msg.edit(embed=em)

            try:
                await msg.remove_reaction(reaction.emoji, user)

            # The above fails if the bot doesn't have the "Manage Messages" permission, but it can be safely ignored
            # as it is not essential functionality.
            except discord.ext.commands.errors.CommandInvokeError:
                pass

    @commands.command(name='hadith')
    async def hadith(self, ctx, collection_name: str, ref: Reference):
        await self.abstract_hadith(ctx.channel, collection_name, ref, 'en')

    @commands.command(name='ahadith')
    async def ahadith(self, ctx, collection_name: str, ref: Reference):
        await self.abstract_hadith(ctx.channel, collection_name, ref, 'ar')

    @hadith.error
    async def hadith_error(self, ctx, error):
        if isinstance(error, commands.MissingRequiredArgument):
            await ctx.send(INVALID_INPUT.format(ctx.prefix))
        elif isinstance(error, InvalidCollection):
            await ctx.send(INVALID_COLLECTION)
        else:
            await ctx.send("Hadith could not be found.")

    @ahadith.error
    async def ahadith_error(self, ctx, error):
        if isinstance(error, commands.MissingRequiredArgument):
            await ctx.send(INVALID_INPUT.format(f'{ctx.prefix}a'))
        elif isinstance(error, InvalidCollection):
            await ctx.send(INVALID_COLLECTION)
        else:
            await ctx.send("Hadith could not be found.")

    @cog_ext.cog_slash(
        name="hadith",
        description="Send hadith in English from sunnah.com.",
        options=[
            create_option(name="hadith_collection",
                          description="The name of the hadith collection.",
                          option_type=3,
                          required=True,
                          choices=generate_choices_from_dict(
                              english_hadith_collections)),
            create_option(name="hadith_number",
                          description="The number of the hadith.",
                          option_type=3,
                          required=True)
        ])
    async def slash_hadith(self, ctx: SlashContext, hadith_collection: str,
                           hadith_number: str):
        await ctx.respond()
        await self.abstract_hadith(ctx.channel, hadith_collection,
                                   Reference(hadith_number), 'en')

    @cog_ext.cog_slash(
        name="ahadith",
        description="Send hadith in Arabic from sunnah.com.",
        options=[
            create_option(
                name="hadith_collection",
                description="The name of the hadith collection.",
                option_type=3,
                required=True,
                choices=generate_choices_from_dict(arabic_hadith_collections)),
            create_option(name="hadith_number",
                          description="The number of the hadith.",
                          option_type=3,
                          required=True)
        ])
    async def slash_ahadith(self, ctx: SlashContext, hadith_collection: str,
                            hadith_number: str):
        await ctx.respond()
        await self.abstract_hadith(ctx.channel, hadith_collection,
                                   Reference(hadith_number), 'ar')

    def findURL(self, message):
        urls = re.findall(r'(https?://\S+)', message)
        for link in urls:
            if "sunnah.com/" in link:
                return link

    @commands.Cog.listener()
    async def on_message(self, message):
        content = message.content
        url = self.findURL(content)
        if url:
            meta = url.split("/")
            collection = meta[3]
            if collection in self.FORTY_HADITH_COLLECTIONS:
                collection = collection[:-2]
            if ":" in collection:  # For urls like http://sunnah.com/bukhari:1
                if collection[-1] == "/":  # if url ended with /
                    collection = collection[:-1]
                ref = collection.split(":")[1]  # getting hadith number
                ref = Reference(ref)
                collection = collection.split(":")[0]  # getting book name
            else:
                book = meta[4]
                try:
                    hadith = meta[5]
                    ref = f"{book}:{hadith}"
                    ref = Reference(ref)
                except:
                    ref = Reference(
                        book
                    )  # For hadith collections which are a single 'book' long (e.g. 40 Hadith Nawawi)
            await self.abstract_hadith(message.channel, collection, ref, "en")
Esempio n. 6
0
class HadithCommands(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    FORTY_HADITH_COLLECTIONS = {'qudsi40', 'nawawi40'}

    async def abstract_hadith(self, channel, collection_name, ref, lang):

        if collection_name not in HADITH_COLLECTION_LIST:
            raise InvalidCollection

        if f'{collection_name}40' in self.FORTY_HADITH_COLLECTIONS:
            collection_name = collection_name + '40'

        hadith = HadithSpecifics(collection_name, ref, lang)
        embed = await hadith.fetch_hadith()

        if hadith.num_pages == 1:
            return await channel.send(embed=embed)

        # If there are multiple pages, construct buttons for their navigation.
        buttons = [
            manage_components.create_button(style=ButtonStyle.grey, label="Previous Page", emoji="⬅",
                                            custom_id="hadith_previous_page"),
            manage_components.create_button(style=ButtonStyle.green, label="Next Page", emoji="➡",
                                            custom_id="hadith_next_page")
        ]
        action_row = manage_components.create_actionrow(*buttons)
        await channel.send(embed=embed, components=[action_row])

        while True:
            try:
                button_ctx = await manage_components.wait_for_component(self.bot, components=action_row, timeout=600)
                if button_ctx.custom_id == 'hadith_previous_page':
                    if hadith.page > 1:
                        hadith.page -= 1
                    else:
                        hadith.page = hadith.num_pages
                    em = hadith.make_embed()
                    await button_ctx.edit_origin(embed=em)
                elif button_ctx.custom_id == 'hadith_next_page':
                    if hadith.page < hadith.num_pages:
                        hadith.page += 1
                    else:
                        hadith.page = 1
                    em = hadith.make_embed()
                    await button_ctx.edit_origin(embed=em)

            except asyncio.TimeoutError:
                break

    @commands.command(name='hadith')
    async def hadith(self, ctx, collection_name: str, ref: Reference):
        await self.abstract_hadith(ctx, collection_name.lower(), ref, 'en')

    @commands.command(name='ahadith')
    async def ahadith(self, ctx, collection_name: str, ref: Reference):
        await self.abstract_hadith(ctx, collection_name.lower(), ref, 'ar')

    @hadith.error
    async def hadith_error(self, ctx, error):
        if isinstance(error, commands.MissingRequiredArgument):
            await ctx.send(INVALID_INPUT.format(ctx.prefix))
        elif isinstance(error, InvalidCollection):
            await ctx.send(INVALID_COLLECTION)


    @ahadith.error
    async def ahadith_error(self, ctx, error):
        if isinstance(error, commands.MissingRequiredArgument):
            await ctx.send(INVALID_INPUT.format(f'{ctx.prefix}a'))
        elif isinstance(error, InvalidCollection):
            await ctx.send(INVALID_COLLECTION)

    @cog_ext.cog_slash(name="hadith", description="Send hadith in English from sunnah.com.",
                       options=[
                           create_option(
                               name="hadith_collection",
                               description="The name of the hadith collection.",
                               option_type=3,
                               required=True,
                               choices=generate_choices_from_dict(english_hadith_collections)),
                           create_option(
                               name = "hadith_number",
                               description = "The number of the hadith.",
                               option_type=3,
                               required=True)])
    async def slash_hadith(self, ctx: SlashContext, hadith_collection: str, hadith_number: str):
        await ctx.defer()
        await self.abstract_hadith(ctx, hadith_collection, Reference(hadith_number), 'en')

    @cog_ext.cog_slash(name="ahadith", description="Send hadith in Arabic from sunnah.com.",
                       options=[
                           create_option(
                               name="hadith_collection",
                               description="The name of the hadith collection.",
                               option_type=3,
                               required=True,
                               choices=generate_choices_from_dict(arabic_hadith_collections)),
                           create_option(
                               name = "hadith_number",
                               description = "The number of the hadith.",
                               option_type=3,
                               required=True)])
    async def slash_ahadith(self, ctx: SlashContext, hadith_collection: str, hadith_number: str):
        await ctx.defer()
        await self.abstract_hadith(ctx, hadith_collection, Reference(hadith_number), 'ar')

    def findURL(self, message):
        urls = re.findall(r'(https?://\S+)', message)
        for link in urls:
            if "sunnah.com/" in link:
                return link

    @staticmethod
    def make_buttons(hadith: HadithSpecifics):
        original_link_button = manage_components.create_button(style=ButtonStyle.URL,
                                                               label="View on sunnah.com",
                                                               emoji=emojis["MOUSE"],
                                                               url=hadith.url)

        return manage_components.create_actionrow(*original_link_button)

    @commands.Cog.listener()
    async def on_message(self, message):
        content = message.content
        url = self.findURL(content)
        if url:
            meta = url.split("/")
            collection = meta[3]
            if collection in self.FORTY_HADITH_COLLECTIONS:
                collection = collection[:-2]
            if ":" in collection:  # For urls like http://sunnah.com/bukhari:1
                if collection[-1] == "/":  # if url ended with /
                    collection = collection[:-1]
                ref = collection.split(":")[1]  # getting hadith number
                ref = Reference(ref)
                collection = collection.split(":")[0]  # getting book name
            else:
                book = meta[4]
                try:
                    hadith = meta[5]
                    ref = f"{book}:{hadith}"
                    ref = Reference(ref)
                except:
                    ref = Reference(book)  # For hadith collections which are a single 'book' long (e.g. 40 Hadith Nawawi)
            await self.abstract_hadith(message.channel, collection, ref, "en")