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)
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")
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)
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 <رقم السورة>:<رقم الآية> <اسم تفسير اختياري>`")
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")
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")