Spaces:
Sleeping
Sleeping
| import discord | |
| from discord.ext import commands, tasks | |
| from discord import app_commands | |
| from discord.ui import Button, View, Select | |
| import asyncio | |
| import random | |
| import os | |
| from datetime import datetime | |
| # ======================================================= | |
| # ุงูุฅุนุฏุงุฏุงุช ุงูุฃุณุงุณูุฉ (ุงูุซูุงุจุช) | |
| # ======================================================= | |
| TARGET_GUILD_ID = 1463693244897693779 # ุฃูุฏู ุงูุณูุฑูุฑ ุงูู ุณู ูุญ | |
| OWNER_ROLE_ID = 1492516779598155877 # ุฃูุฏู ุฑุชุจุฉ ุงูู ุงูู ููุชุญูู | |
| # ======================================================= | |
| # ุงูุฃุฐูุงุฑ ูุงูุชุฐููุฑุงุช (ุงููุงุฆู ุฉ ุงููุงู ูุฉ) | |
| # ======================================================= | |
| REMINDERS = [ | |
| "๐ธ ุณุจุญุงู ุงููู ูุจุญู ุฏูุ ุณุจุญุงู ุงููู ุงูุนุธูู ", | |
| "โจ ุงูููู ุตู ูุณูู ุนูู ูุจููุง ู ุญู ุฏ", | |
| "๐ฟ ุฃุณุชุบูุฑ ุงููู ุงูุนุธูู ูุฃุชูุจ ุฅููู", | |
| "๐๏ธ ูุง ุญูู ููุง ููุฉ ุฅูุง ุจุงููู", | |
| "๐ฟ ุณุจุญุงู ุงูููุ ูุงูุญู ุฏ ูููุ ููุง ุฅูู ุฅูุง ุงูููุ ูุงููู ุฃูุจุฑ", | |
| "๐ธ ุณุจุญุงู ุงููู", "โจ ุงูุญู ุฏ ููู", "๐ฟ ุงููู ุฃูุจุฑ", "๐๏ธ ูุง ุฅูู ุฅูุง ุงููู", | |
| "๐ฟ ุงูููู ุงุบูุฑ ูู", "๐ธ ุงูููู ุงุฑุญู ูู", "โจ ุงูููู ุชุจ ุนูู", "๐ฟ ุงูููู ุงุฑุฒููู", | |
| "๐๏ธ ุญุณุจู ุงููู ููุนู ุงููููู", "๐ฟ ุชูููุช ุนูู ุงููู", "๐ธ ุฑุจ ุงุบูุฑ ูู ูููุงูุฏู", | |
| "โจ ุงูููู ุงุฌุนููู ู ู ุงูุตุงูุญูู", "๐ฟ ุงูููู ุงูุฏูู", "๐๏ธ ุงูููู ุซุจุชูู", | |
| "๐ฟ ุงูููู ุงุฑุฒููู ุงูุฌูุฉ", "๐ธ ุงูููู ุฃุฌุฑูู ู ู ุงููุงุฑ", "โจ ูุง ุฑุจ", "๐ฟ ูุง ุงููู", | |
| "๐๏ธ ูุง ุญู ูุง ูููู ุจุฑุญู ุชู ุฃุณุชุบูุซ", "๐ฟ ุงูููู ุฅูู ุฃุณุฃูู ุงูุนุงููุฉ", | |
| "๐ธ ุงูููู ุฅูู ุฃุณุฃูู ุงููุฏู ูุงูุชูู", "โจ ุงูููู ุฅูู ุฃุนูุฐ ุจู ู ู ุงููู ูุงูุญุฒู", | |
| "๐ฟ ุงูููู ุฅูู ุฃุนูุฐ ุจู ู ู ุงูุนุฌุฒ ูุงููุณู", "๐๏ธ ุงูููู ุฅูู ุฃุนูุฐ ุจู ู ู ุงูุฌุจู ูุงูุจุฎู", | |
| "๐ฟ ุงูููู ุฅูู ุฃุนูุฐ ุจู ู ู ุบูุจุฉ ุงูุฏูู ูููุฑ ุงูุฑุฌุงู", "๐ธ ุงูููู ุงุฌุนู ุงููุฑุขู ุฑุจูุน ููุจู", | |
| "โจ ุงูููู ููุฑ ููุจู", "๐ฟ ุงูููู ุทูุฑ ููุจู", "๐๏ธ ุงูููู ุฃุตูุญ ุญุงูู", | |
| "๐ฟ ุงูููู ุงุฌุนููู ู ู ุงูุฐุงูุฑูู", "๐ธ ุงูููู ุงุฌุนููู ู ู ุงูุดุงูุฑูู", | |
| "โจ ุงูููู ุงุฌุนููู ู ู ุงูุตุงุจุฑูู", "๐ฟ ุงูููู ุงุฌุนููู ู ู ุงูุชูุงุจูู", | |
| "๐๏ธ ุงูููู ุงุฌุนููู ู ู ุงูู ุชููู", "๐ฟ ุงูููู ุงุฌุนููู ู ู ุงูู ุญุณููู", | |
| "๐ธ ุงูููู ุงุฑุฒููู ุงูุฅุฎูุงุต", "โจ ุงูููู ุงุฑุฒููู ุงูุตุฏู", "๐ฟ ุงูููู ุงุฑุฒููู ุญุณู ุงูุฎุงุชู ุฉ", | |
| "๐๏ธ ุงูููู ุงุฌุนู ูุจุฑู ุฑูุถุฉ ู ู ุฑูุงุถ ุงูุฌูุฉ", "๐ฟ ุงูููู ุงุฌุนููู ู ู ุฃูู ุงูุฌูุฉ", | |
| "๐ธ ุงูููู ุงุฑุฒููู ุงููุฑุฏูุณ ุงูุฃุนูู", "โจ ุงูููู ูุง ุชุญุฑู ูู ู ู ุฑุญู ุชู", | |
| "๐ฟ ุงูููู ูุง ุชูููู ุฅูู ููุณู", "๐๏ธ ุงูููู ุงุฑุญู ู ูุชุงูุง", "๐ฟ ุงูููู ุงุดู ู ุฑุถุงูุง", | |
| "๐ธ ุงูููู ูุฑุฌ ูู ูู ูุง", "โจ ุงูููู ุงูุถ ุฏููููุง", "๐ฟ ุงูููู ูุณุน ุฑุฒููุง", | |
| "๐๏ธ ุงูููู ุจุงุฑู ููุง", "๐ฟ ุงูููู ุงุญูุธูุง", "๐ธ ุงูููู ุงูุตุฑูุง", | |
| "โจ ุงูููู ุงุฌุนููุง ู ู ุนุจุงุฏู ุงูุตุงูุญูู", "๐ฟ ุงูููู ุงุฑุฒููุง ุฑุถุงู", | |
| "๐๏ธ ุงูููู ุงุฌุนููุง ู ู ุฃูู ุงูุฐูุฑ", "๐ฟ ุงูููู ุงุฑุฒููุง ุญุจู", "๐ธ ุงูููู ุงุฑุฒููุง ุญุจ ูุจูู", | |
| "โจ ุงูููู ุงุฌุนููุง ู ู ุงูู ุชููููู", "๐ฟ ุงูููู ุงุฑุฒููุง ุงูุตุจุฑ", "๐๏ธ ุงูููู ุงุฑุฒููุง ุงููููู", | |
| "๐ฟ ุงูููู ุงุฌุนููุง ู ู ุงูุฐุงูุฑูู ุงููู ูุซูุฑุง", "๐ธ ุงูููู ุงุฌุนููุง ู ู ุงููุงูุชูู", | |
| "โจ ุงูููู ุงุฑุฒููุง ุญุณู ุงูุธู ุจู", "๐ฟ ุงูููู ุงุฌุนููุง ู ู ุงูู ูุจูููู", | |
| "๐๏ธ ุงูููู ุงุฑุฒููุง ูุฐุฉ ุงููุธุฑ ุฅูู ูุฌูู", "๐ฟ ุงูููู ุงุฌุนููุง ู ู ุงููุงุฆุฒูู", | |
| "๐ธ ุงูููู ุงุฌุนููุง ู ู ุฃูู ุงููุฑุฏูุณ", "โจ ุงูููู ุงุฌุนููุง ู ู ุนุชูุงุฆู ู ู ุงููุงุฑ", | |
| "๐ฟ ุงูููู ุงุฌุนููุง ู ู ุงูู ุณุชุบูุฑูู", "๐๏ธ ุงูููู ุงุฌุนููุง ู ู ุงูุฑุงุฌุนูู ุฅููู", | |
| "๐ฟ ุงูููู ุงุฌุนููุง ู ู ุงูู ููุจูู", "๐ธ ุงูููู ุงุฑุฒููุง ุงูุชูุจุฉ ุงููุตูุญ", | |
| "โจ ุงูููู ุชูุจู ู ูุง", "๐ฟ ุงูููู ุงุบูุฑ ููุง", "๐๏ธ ุงูููู ุงุฑุญู ูุง", "๐ฟ ุงูููู ุชุจ ุนูููุง", | |
| "๐ธ ุงูููู ุงูุฏูุง", "โจ ุงูููู ุงุญูุธูุง ู ู ูู ุณูุก", "๐ฟ ุงูููู ุงุฌุนููุง ู ู ุงูุตุงูุญูู", | |
| "๐๏ธ ุงูููู ุงุฑุฒููุง ุงูุฌูุฉ ุจุบูุฑ ุญุณุงุจ", "๐ฟ ุงูููู ุงุฌุนููุง ู ู ุฃูู ุงููุฑุขู", | |
| "๐ธ ุงูููู ุงุฌุนู ุงููุฑุขู ุดููุนุงู ููุง", "โจ ุงูููู ุงุฌุนู ุงููุฑุขู ุญุฌุฉ ููุง", | |
| "๐ฟ ุงูููู ุงุฌุนููุง ู ู ุงูุฐูู ูุณุชู ุนูู ุงูููู ููุชุจุนูู ุฃุญุณูู", | |
| "๐๏ธ ุงูููู ุงุฌุนููุง ู ู ุฃููู ุงูุฃูุจุงุจ", "๐ฟ ุงูููู ุงุฑุฒููุง ุงูุนูู ุงููุงูุน", | |
| "๐ธ ุงูููู ุงุฑุฒููุง ุงูุนู ู ุงูุตุงูุญ", "โจ ุงูููู ุงุฑุฒููุง ุงูุฅูู ุงู ุงููุงู ู", | |
| "๐ฟ ุงูููู ุงุฌุนููุง ู ู ุฃูู ุงูุชููู", "๐๏ธ ุงูููู ุงุฌุนููุง ู ู ุงูุตุงุฏููู", | |
| "๐ฟ ุงูููู ุงุฌุนููุง ู ู ุงูู ุฎูุตูู", "๐ธ ุงูููู ุงุฌุนููุง ู ู ุนุจุงุฏู ุงูู ูุฑุจูู", | |
| "โจ ุงูููู ุงุฌุนููุง ู ู ุงูุฐุงูุฑูู ุงูุดุงูุฑูู", "๐ฟ ุงูููู ุงุฌุนููุง ู ู ุงูุตุงุจุฑูู ุงูู ุญุชุณุจูู" | |
| ] | |
| # ======================================================= | |
| # ูุงุฆู ุฉ 30 ูุงุฑุฆ (ุจุฏูู ุงุฎุชุตุงุฑ) | |
| # ======================================================= | |
| RECITERS = [ | |
| {"name": "ุฅุฐุงุนุฉ ุชูุงูุงุช ู ููุนุฉ", "desc": "ุจุซ ู ุจุงุดุฑ ูุชูุงูุงุช ู ุฎุชุงุฑุฉ", "url": "https://qurango.net/radio/tarateel"}, | |
| {"name": "ุนุจุฏุงูุจุงุณุท ุนุจุฏุงูุตู ุฏ", "desc": "ุชูุงูุฉ ู ุฌูุฏุฉ ุจุตูุช ุฎุงุดุน", "url": "https://qurango.net/radio/abdulbasit_abdulsamad_mjawwad"}, | |
| {"name": "ู ุดุงุฑู ุงูุนูุงุณู", "desc": "ุชูุงูุฉ ูุงุฏุฆุฉ ูู ุฑูุญุฉ", "url": "https://qurango.net/radio/mishary_alafasi"}, | |
| {"name": "ูุงุณุฑ ุงูุฏูุณุฑู", "desc": "ุชูุงูุงุช ู ู ูุฒุฉ ู ู ุงูุญุฑู ", "url": "https://qurango.net/radio/yasser_aldosari"}, | |
| {"name": "ู ุงูุฑ ุงูู ุนูููู", "desc": "ุชูุงูุฉ ุนุฐุจุฉ ูุดููุฑุฉ", "url": "https://qurango.net/radio/maher_al_muaiqly"}, | |
| {"name": "ุฃุญู ุฏ ุจู ุนูู ุงูุนุฌู ู", "desc": "ุชูุงูุฉ ุฎุงุดุนุฉ", "url": "https://qurango.net/radio/ahmad_alajmy"}, | |
| {"name": "ุณุนุฏ ุงูุบุงู ุฏู", "desc": "ุชูุงูุฉ ู ุฑูุญุฉ ููููุจ", "url": "https://qurango.net/radio/saad_alghamidi"}, | |
| {"name": "ุณุนูุฏ ุงูุดุฑูู ", "desc": "ู ู ุชูุงูุงุช ุงูุญุฑู ุงูู ูู", "url": "https://qurango.net/radio/saud_alshuraim"}, | |
| {"name": "ุนุจุฏุงูุฑุญู ู ุงูุณุฏูุณ", "desc": "ุชูุงูุฉ ุงูุญุฑู ุงูู ูู ุงูุดุฑูู", "url": "https://qurango.net/radio/abdulrahman_alsudaes"}, | |
| {"name": "ู ุญู ูุฏ ุฎููู ุงูุญุตุฑู", "desc": "ุชูุงูุฉ ู ุฑุชูุฉ ุฏูููุฉ", "url": "https://qurango.net/radio/mahmoud_khalil_alhussary"}, | |
| {"name": "ุนูู ุนุจุฏุงููู ุฌุงุจุฑ", "desc": "ุชูุงูุฉ ู ู ูุฒุฉ", "url": "https://qurango.net/radio/ali_jaber"}, | |
| {"name": "ู ุญู ุฏ ุฃููุจ", "desc": "ุชูุงูุฉ ุญุฌุงุฒูุฉ", "url": "https://qurango.net/radio/mohammed_ayyub"}, | |
| {"name": "ู ุญู ุฏ ุตุฏูู ุงูู ูุดุงูู", "desc": "ุชูุงูุฉ ุฎุงุดุนุฉ ุฌุฏุงู", "url": "https://qurango.net/radio/mohammed_siddiq_alminshawi"}, | |
| {"name": "ุฃุจูุจูุฑ ุงูุดุงุทุฑู", "desc": "ุชูุงูุฉ ูุงุฏุฆุฉ", "url": "https://qurango.net/radio/abubakr_alshatri"}, | |
| {"name": "ุนุจุฏุงููู ุจุตูุฑ", "desc": "ุชูุงูุฉ ุนุฐุจุฉ", "url": "https://qurango.net/radio/abdullah_basfer"}, | |
| {"name": "ุนุจุฏุงูู ุญุณู ุงููุงุณู ", "desc": "ุฅู ุงู ุงูู ุณุฌุฏ ุงููุจูู", "url": "https://qurango.net/radio/abdulmohsin_alqasim"}, | |
| {"name": "ุนุจุฏุงููุฏูุฏ ุญููู", "desc": "ุชูุงูุฉ ุฑุงุฆุนุฉ", "url": "https://qurango.net/radio/abdulwadood_haneef"}, | |
| {"name": "ุนูู ุนุจุฏุงูุฑุญู ู ุงูุญุฐููู", "desc": "ู ู ุชูุงูุงุช ุงูู ุณุฌุฏ ุงููุจูู", "url": "https://qurango.net/radio/ali_alhuthaifi"}, | |
| {"name": "ูุงุฑุณ ุนุจุงุฏ", "desc": "ุชูุงูุฉ ู ุคุซุฑุฉ", "url": "https://qurango.net/radio/fares_abbad"}, | |
| {"name": "ู ุญู ุฏ ุฌุจุฑูู", "desc": "ุชูุงูุฉ ู ุดููุฑุฉ", "url": "https://qurango.net/radio/mohammed_jibreel"}, | |
| {"name": "ู ุญู ุฏ ุงูุทุจูุงูู", "desc": "ู ู ูุจุงุฑ ุงููุฑุงุก", "url": "https://qurango.net/radio/mohammad_altablaway"}, | |
| {"name": "ู ุญู ูุฏ ุนูู ุงูุจูุง", "desc": "ุชูุงูุฉ ููุงุณูููุฉ", "url": "https://qurango.net/radio/mahmoud_ali__albanna"}, | |
| {"name": "ู ุตุทูู ุฅุณู ุงุนูู", "desc": "ุชูุงูุฉ ู ุฌูุฏุฉ", "url": "https://qurango.net/radio/mustafa_ismail"}, | |
| {"name": "ูุงูู ุงูุฑูุงุนู", "desc": "ุชูุงูุฉ ุจูุงุฆูุฉ", "url": "https://qurango.net/radio/hani_arrifai"}, | |
| {"name": "ูุญูู ุญูุง", "desc": "ุชูุงูุฉ ูุงุฏุฆุฉ", "url": "https://qurango.net/radio/yahya_hawwa"}, | |
| {"name": "ุฎุงูุฏ ุงููุญุทุงูู", "desc": "ุชูุงูุฉ ุฎุงุดุนุฉ", "url": "https://qurango.net/radio/khalid_alqahtani"}, | |
| {"name": "ุตูุงุญ ุงูุจุฏูุฑ", "desc": "ุฅู ุงู ุงูู ุณุฌุฏ ุงููุจูู", "url": "https://qurango.net/radio/salah_albudair"}, | |
| {"name": "ุตูุงุญ ุจู ุฎุงุทุฑ", "desc": "ุชูุงูุฉ ูุฏูุฉ", "url": "https://qurango.net/radio/salah_bukhatir"}, | |
| {"name": "ุนุจุฏุงูุฑุดูุฏ ุตููู", "desc": "ุชูุงูุฉ ู ู ูุฒุฉ ุจุฑูุงูุงุช", "url": "https://qurango.net/radio/abdulrasheed_soufi"}, | |
| {"name": "ุนุจุฏุงููู ุนูุงุฏ ุงูุฌููู", "desc": "ุฅู ุงู ุงูุญุฑู ุงูู ูู", "url": "https://qurango.net/radio/abdullah_aljuhani"} | |
| ] | |
| # --- ู ุชุบูุฑุงุช ุงูุชุญูู ุจุงูุจุซ --- | |
| current_reciter_index = 0 | |
| current_volume = 1.0 | |
| # ุฅุนุฏุงุฏุงุช ุฃูุซุฑ ุฃู ุงูุงู ูุชุฌูุจ ุญุธุฑ IP ู ู ุงูุณูุฑูุฑุงุช ุงูุตูุชูุฉ | |
| FFMPEG_OPTIONS = { | |
| 'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', | |
| 'options': '-vn -sn -dn -bufsize 500k -max_muxing_queue_size 1024' | |
| } | |
| # ======================================================= | |
| # ุชุฌููุฒ ูุงุฌูุฉ ุงูุฃุฒุฑุงุฑ (Control Panel) | |
| # ======================================================= | |
| class ReciterSelect(Select): | |
| def __init__(self): | |
| options = [] | |
| for i, r in enumerate(RECITERS[:25]): | |
| options.append(discord.SelectOption(label=r['name'], description=r['desc'][:50], value=str(i))) | |
| super().__init__(placeholder="ุงุฎุชุฑ ุงููุงุฑุฆ ู ู ุงููุงุฆู ุฉ ุงูุณุฑูุนุฉ...", min_values=1, max_values=1, options=options, custom_id="select_reciter") | |
| async def callback(self, interaction: discord.Interaction): | |
| role = interaction.guild.get_role(OWNER_ROLE_ID) | |
| if role not in interaction.user.roles: | |
| return await interaction.response.send_message("โ ูุง ุชู ูู ุตูุงุญูุฉ.", ephemeral=True) | |
| global current_reciter_index | |
| current_reciter_index = int(self.values[0]) | |
| vc = interaction.guild.voice_client | |
| if vc: await play_current_reciter(vc) | |
| try: | |
| await interaction.response.send_message(f"๐๏ธ ุชู ุงูุชุบููุฑ ุฅูู: {RECITERS[current_reciter_index]['name']}", ephemeral=True) | |
| await log_event(interaction.guild, f"๐๏ธ **{interaction.user.name}** ูุงู ุจุชุบููุฑ ุงููุงุฑุฆ ุฅูู: {RECITERS[current_reciter_index]['name']}") | |
| except: pass | |
| class ControlPanelView(View): | |
| def __init__(self): | |
| super().__init__(timeout=None) | |
| self.add_item(ReciterSelect()) | |
| async def check_owner(self, interaction: discord.Interaction): | |
| role = interaction.guild.get_role(OWNER_ROLE_ID) | |
| if role and role in interaction.user.roles: | |
| return True | |
| try: | |
| await interaction.response.send_message("โ ุนุฐุฑุงูุ ูุง ุชู ูู ุงูุตูุงุญูุฉ (ุฑุชุจุฉ ุงูู ุงูู ุงูู ุทููุจุฉ).", ephemeral=True) | |
| except: pass | |
| return False | |
| async def toggle_btn(self, interaction: discord.Interaction, button: Button): | |
| if not await self.check_owner(interaction): return | |
| vc = interaction.guild.voice_client | |
| try: | |
| if vc: | |
| if vc.is_paused(): | |
| vc.resume() | |
| await interaction.response.send_message("โถ๏ธ ุชู ุงุณุชุฆูุงู ุงูุจุซ.", ephemeral=True) | |
| await log_event(interaction.guild, f"โถ๏ธ **{interaction.user.name}** ูุงู ุจุงุณุชุฆูุงู ุงูุจุซ.") | |
| elif vc.is_playing(): | |
| vc.pause() | |
| await interaction.response.send_message("โธ๏ธ ุชู ุฅููุงู ุงูุจุซ ู ุคูุชุงู.", ephemeral=True) | |
| await log_event(interaction.guild, f"โธ๏ธ **{interaction.user.name}** ูุงู ุจุฅููุงู ุงูุจุซ ูุฏููุงู.") | |
| else: | |
| await play_current_reciter(vc) | |
| await interaction.response.send_message("โถ๏ธ ุชู ุชุดุบูู ุงูุจุซ.", ephemeral=True) | |
| else: | |
| await interaction.response.send_message("โ ุงูุจูุช ุบูุฑ ู ุชุตู.", ephemeral=True) | |
| except: pass | |
| async def next_btn(self, interaction: discord.Interaction, button: Button): | |
| if not await self.check_owner(interaction): return | |
| global current_reciter_index | |
| current_reciter_index = (current_reciter_index + 1) % len(RECITERS) | |
| vc = interaction.guild.voice_client | |
| if vc: await play_current_reciter(vc) | |
| try: | |
| await interaction.response.send_message(f"โญ๏ธ ุชู ุงูุงูุชูุงู ุฅูู: {RECITERS[current_reciter_index]['name']}", ephemeral=True) | |
| await log_event(interaction.guild, f"โญ๏ธ **{interaction.user.name}** ุงูุชูู ูููุงุฑุฆ: {RECITERS[current_reciter_index]['name']}") | |
| except: pass | |
| async def prev_btn(self, interaction: discord.Interaction, button: Button): | |
| if not await self.check_owner(interaction): return | |
| global current_reciter_index | |
| current_reciter_index = (current_reciter_index - 1) % len(RECITERS) | |
| vc = interaction.guild.voice_client | |
| if vc: await play_current_reciter(vc) | |
| try: | |
| await interaction.response.send_message(f"โฎ๏ธ ุชู ุงูุฑุฌูุน ุฅูู: {RECITERS[current_reciter_index]['name']}", ephemeral=True) | |
| await log_event(interaction.guild, f"โฎ๏ธ **{interaction.user.name}** ุฑุฌุน ูููุงุฑุฆ: {RECITERS[current_reciter_index]['name']}") | |
| except: pass | |
| class QuranBot(commands.Bot): | |
| def __init__(self): | |
| intents = discord.Intents.default() | |
| intents.message_content = True | |
| intents.voice_states = True | |
| intents.guilds = True | |
| super().__init__(command_prefix="!", intents=intents) | |
| async def setup_hook(self): | |
| self.add_view(ControlPanelView()) | |
| await self.tree.sync() | |
| print("โ ุชู ู ุฒุงู ูุฉ ุงูุฃูุงู ุฑ ูุงูุฃุฒุฑุงุฑ ุจูุฌุงุญ.") | |
| bot = QuranBot() | |
| # ======================================================= | |
| # ุฏูุงู ู ุณุงุนุฏุฉ ูุญู ุงูุฉ ู ู ุงูุญุธุฑ | |
| # ======================================================= | |
| async def log_event(guild: discord.Guild, message: str): | |
| log_channel = discord.utils.get(guild.text_channels, name="๐-ุณุฌูุงุช-ุงูุจูุช") | |
| time_now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") | |
| if log_channel: | |
| try: | |
| await log_channel.send(f"`[{time_now}]` {message}") | |
| except: pass # ู ูุน ุชููู ุงูุจูุช ุฅุฐุง ุฑูุถ ุฏูุณููุฑุฏ ุฅุฑุณุงู ุงูุฑุณุงูุฉ ุจุณุจุจ Rate Limit | |
| print(f"[{time_now}] {message}") | |
| def is_owner_and_in_control(): | |
| async def predicate(interaction: discord.Interaction): | |
| if not interaction.guild: | |
| try: await interaction.response.send_message("โ ูุฐุง ุงูุฃู ุฑ ู ุฎุตุต ููุงุณุชุฎุฏุงู ุฏุงุฎู ุงูุณูุฑูุฑ ููุท.", ephemeral=True) | |
| except: pass | |
| return False | |
| if interaction.channel.name != "๐ ๏ธ ุบุฑูุฉ ุงูุชุญูู (ููู ุงูู)": | |
| try: await interaction.response.send_message("โ ุนุฐุฑุงูุ ูุง ูู ููู ุงุณุชุฎุฏุงู ุงูุฃูุงู ุฑ ุฅูุง ุฏุงุฎู ๐ ๏ธ ุบุฑูุฉ ุงูุชุญูู .", ephemeral=True) | |
| except: pass | |
| return False | |
| role = interaction.guild.get_role(OWNER_ROLE_ID) | |
| if role and role in interaction.user.roles: | |
| return True | |
| try: await interaction.response.send_message("โ ุนุฐุฑุงูุ ูุง ุชู ูู ุงูุตูุงุญูุฉ (ุฑุชุจุฉ ุงูู ุงูู ุงูู ุทููุจุฉ).", ephemeral=True) | |
| except: pass | |
| return False | |
| return app_commands.check(predicate) | |
| async def play_current_reciter(vc: discord.VoiceClient): | |
| try: | |
| if vc.is_playing() or vc.is_paused(): | |
| vc.stop() | |
| await asyncio.sleep(1) # ุชุฃุฎูุฑ ุจุณูุท ูุญู ุงูุฉ ุงูู API ู ู ุถุบุท ุงูุทูุจุงุช | |
| reciter = RECITERS[current_reciter_index] | |
| audio_source = discord.FFmpegPCMAudio(reciter["url"], **FFMPEG_OPTIONS) | |
| vc.play(discord.PCMVolumeTransformer(audio_source, volume=current_volume)) | |
| except Exception as e: | |
| print(f"โ ๏ธ ุฎุทุฃ ุฃุซูุงุก ุงูุชุดุบูู (ุชู ุชุฌุงูุฒู): {e}") | |
| # ======================================================= | |
| # ููุฏุณุฉ ุงููููุงุช ูุงูุฃุญุฏุงุซ | |
| # ======================================================= | |
| async def on_ready(): | |
| # ุญุงูุฉ ู ุณุชูุฑุฉ ูุขู ูุฉ ุชุธูุฑ ููู ุณุชุฎุฏู ูู | |
| await bot.change_presence(status=discord.Status.online, activity=discord.Activity(type=discord.ActivityType.listening, name="ุงููุฑุขู ุงููุฑูู 24/7 ๐ง")) | |
| print(f"๐ค ุงูุจูุช {bot.user} ู ุชุตู ุจุดุจูุฉ ุฏูุณููุฑุฏ ุจูุฌุงุญ ููู ุงูุขู (Online).") | |
| # ูุญุต ูุงุฏุฆ ููุณูุฑูุฑุงุช | |
| for guild in bot.guilds: | |
| if guild.id != TARGET_GUILD_ID: | |
| print(f"๐ข ุฌุงุฑู ู ุบุงุฏุฑุฉ ุณูุฑูุฑ ุบุฑูุจ ุจูุฏูุก: {guild.name}") | |
| await asyncio.sleep(2) # ุชุฃุฎูุฑ ูู ูุน ุงูุทุฑุฏ ุงูู ุชุนุฏุฏ ุงูุณุฑูุน | |
| try: await guild.leave() | |
| except: pass | |
| else: | |
| await check_and_create_channels(guild) | |
| await log_event(guild, "๐ **ุชู ุฅููุงุน ุงููุธุงู ูุงูุจูุช ู ุชุตู ุงูุขู.**") | |
| # ุชุดุบูู ูุจุถ ุงูููุจ (ูุญุต ูู 5 ุฏูุงุฆู) | |
| if not heartbeat_task.is_running(): | |
| heartbeat_task.start() | |
| async def on_guild_join(guild): | |
| print(f"๐ฅ ุงูุจูุช ุฏุฎู ุณูุฑูุฑ ุฌุฏูุฏ: {guild.name}") | |
| await asyncio.sleep(2) # ุญู ุงูุฉ API ุฏูุณููุฑุฏ | |
| if guild.id != TARGET_GUILD_ID: | |
| try: await guild.leave() | |
| except: pass | |
| else: | |
| await check_and_create_channels(guild) | |
| await log_event(guild, "๐ **ุชู ุฅุถุงูุฉ ุงูุจูุช ููุณูุฑูุฑ ุงูุตุญูุญ ูุจุฏุก ุงูุชุดุบูู!**") | |
| async def check_and_create_channels(guild): | |
| category_name = "ุฅุฐุงุนุฉ ุงููุฑุขู ุงููุฑูู " | |
| broadcast_vc_name = "๐ง ุงุณุชู ุงุน ุงููุฑุขู (ุจุซ ุนุงู )" | |
| control_vc_name = "๐ ๏ธ ุบุฑูุฉ ุงูุชุญูู (ููู ุงูู)" | |
| log_channel_name = "๐-ุณุฌูุงุช-ุงูุจูุช" | |
| category = discord.utils.get(guild.categories, name=category_name) | |
| broadcast_vc = discord.utils.get(guild.voice_channels, name=broadcast_vc_name) | |
| control_vc = discord.utils.get(guild.voice_channels, name=control_vc_name) | |
| log_tc = discord.utils.get(guild.text_channels, name=log_channel_name) | |
| owner_role = guild.get_role(OWNER_ROLE_ID) | |
| try: | |
| if not category: | |
| category = await guild.create_category(category_name) | |
| await asyncio.sleep(1) | |
| if not log_tc: | |
| overwrites_log = { | |
| guild.default_role: discord.PermissionOverwrite(view_channel=False), | |
| bot.user: discord.PermissionOverwrite(view_channel=True, send_messages=True, read_message_history=True) | |
| } | |
| if owner_role: overwrites_log[owner_role] = discord.PermissionOverwrite(view_channel=True, read_message_history=True) | |
| log_tc = await guild.create_text_channel(log_channel_name, category=category, overwrites=overwrites_log) | |
| await asyncio.sleep(1) | |
| if not broadcast_vc: | |
| overwrites_broadcast = { | |
| guild.default_role: discord.PermissionOverwrite( | |
| view_channel=True, connect=True, read_message_history=True, | |
| speak=False, send_messages=False, add_reactions=False, stream=False | |
| ), | |
| bot.user: discord.PermissionOverwrite(connect=True, speak=True, send_messages=True, administrator=True) | |
| } | |
| broadcast_vc = await guild.create_voice_channel(broadcast_vc_name, category=category, overwrites=overwrites_broadcast) | |
| await asyncio.sleep(1) | |
| if not control_vc: | |
| overwrites_control = { | |
| guild.default_role: discord.PermissionOverwrite(view_channel=False, connect=False), | |
| bot.user: discord.PermissionOverwrite(view_channel=True, connect=True, send_messages=True) | |
| } | |
| if owner_role: overwrites_control[owner_role] = discord.PermissionOverwrite(view_channel=True, connect=True, send_messages=True) | |
| control_vc = await guild.create_voice_channel(control_vc_name, category=category, overwrites=overwrites_control, user_limit=99) | |
| embed = discord.Embed( | |
| title="๐๏ธ ููุญุฉ ุชุญูู ุงูุฅุฐุงุนุฉ ุงูุฐููุฉ", | |
| description="ุงุณุชุฎุฏู ุงูุฃุฒุฑุงุฑ ุฃุฏูุงู ููุชุญูู ุงูุณุฑูุน ูู ุงูุจุซุ ุฃู ุงุฎุชุฑ ุงููุงุฑุฆ ู ู ุงููุงุฆู ุฉ ุงูู ูุณุฏูุฉ.\n\n*ู ูุงุญุธุฉ: ูู ููู ุฃูุถุงู ุงุณุชุฎุฏุงู ุงูุฃูุงู ุฑ ู ุซู `/volume` ููุง ููุท.*", | |
| color=discord.Color.dark_theme() | |
| ) | |
| embed.set_footer(text="SaaS Pro Dashboard") | |
| await control_vc.send(embed=embed, view=ControlPanelView()) | |
| # ุงุชุตุงู ุงูุจูุช | |
| if not guild.voice_client: | |
| vc = await broadcast_vc.connect() | |
| await asyncio.sleep(2) # ุงุณุชูุฑุงุฑ ุงูุงุชุตุงู | |
| await play_current_reciter(vc) | |
| human_members = sum(1 for m in broadcast_vc.members if not m.bot) | |
| if human_members == 0: | |
| vc.pause() | |
| await log_event(guild, "โธ๏ธ ุงูููุงุฉ ูุงุฑุบุฉุ ุชู ูุถุน ุงูุจุซ ูู ูุถุน ุงูุงุณุชุนุฏุงุฏ (ูุชุฌูุจ ุถุบุท ุงูุดุจูุฉ).") | |
| else: | |
| await log_event(guild, "โถ๏ธ ุชู ุงูุจุฏุก ุจุงูุจุซ ููุฌูุฏ ู ุณุชู ุนูู ูู ุงูููุงุฉ.") | |
| except Exception as e: | |
| print(f"โ ๏ธ ุชุญุฐูุฑ ุฃุซูุงุก ุฅูุดุงุก ุงููููุงุช (ูุฏ ูููู ุจุณุจุจ ุถุบุท ุงูุทูุจุงุช): {e}") | |
| async def on_voice_state_update(member, before, after): | |
| if member.bot: return | |
| guild = member.guild | |
| if guild.id != TARGET_GUILD_ID: return | |
| bot_vc = guild.voice_client | |
| if not bot_vc: return | |
| try: | |
| # ุญุงูุฉ ุฏุฎูู ุนุถู | |
| if after.channel and after.channel.id == bot_vc.channel.id: | |
| if bot_vc.is_paused(): | |
| bot_vc.resume() | |
| await log_event(guild, f"โถ๏ธ ุงุณุชุฆูุงู ุงูุจุซ ุงูุชููุงุฆู ูุฏุฎูู ู ุณุชู ุน.") | |
| embed = discord.Embed( | |
| title="ุฃููุงู ุจู ูู ู ุฌูุณ ุงูุฐูุฑ ๐๏ธ", | |
| description=random.choice(REMINDERS), | |
| color=discord.Color.gold() | |
| ) | |
| embed.set_footer(text=f"ุงููุงุฑุฆ ุงูุญุงูู: {RECITERS[current_reciter_index]['name']}") | |
| try: | |
| await after.channel.send(content=f"ู ุฑุญุจุงู ุจู {member.mention}", embed=embed, delete_after=60) | |
| except: pass | |
| # ุญุงูุฉ ุฎุฑูุฌ ุนุถู | |
| elif before.channel and before.channel.id == bot_vc.channel.id: | |
| human_members = sum(1 for m in before.channel.members if not m.bot) | |
| if human_members == 0 and bot_vc.is_playing(): | |
| bot_vc.pause() | |
| except: pass # ู ูุน ุฃู ุฎุทุฃ ู ูุงุฌุฆ ู ู ุฅููุงู ุงูุจูุช | |
| # ======================================================= | |
| # ู ูู ุฉ ุงููุญุต ุงููุงุฏุฆ (Heartbeat) | |
| # ======================================================= | |
| async def heartbeat_task(): | |
| """ูุฐู ุงูุฏุงูุฉ ุชูุญุต ุงูุจูุช ูู 5 ุฏูุงุฆู ูุถู ุงู ุนุฏู ูุตูู ู ู ุฏูุณููุฑุฏ""" | |
| try: | |
| guild = bot.get_guild(TARGET_GUILD_ID) | |
| if guild and guild.voice_client: | |
| human_members = sum(1 for m in guild.voice_client.channel.members if not m.bot) | |
| # ุฅุฐุง ูุงู ููุงู ูุงุณ ูุงูุตูุช ู ุชููู ุจุงูุฎุทุฃุ ูููู ุจุชุดุบููู | |
| if human_members > 0 and not guild.voice_client.is_playing() and not guild.voice_client.is_paused(): | |
| await play_current_reciter(guild.voice_client) | |
| await log_event(guild, "๐ ุชู ุฅุนุงุฏุฉ ุฅูุนุงุด ุงูุจุซ ุงูุชููุงุฆู ุจูุงุณุทุฉ ูุธุงู ุงูุญู ุงูุฉ (Heartbeat).") | |
| except: pass | |
| # ======================================================= | |
| # ุฃูุงู ุฑ ุงูุณูุงุด (ู ุญุตูุฑุฉ ูู ุบุฑูุฉ ุงูุชุญูู ) | |
| # ======================================================= | |
| async def play_radio(interaction: discord.Interaction): | |
| vc = interaction.guild.voice_client | |
| try: | |
| if not vc: return await interaction.response.send_message("โ ุงูุจูุช ุบูุฑ ู ุชุตู.", ephemeral=True) | |
| if vc.is_paused(): vc.resume() | |
| else: await play_current_reciter(vc) | |
| await interaction.response.send_message(f"โถ๏ธ ุชู ุงูุชุดุบูู: **{RECITERS[current_reciter_index]['name']}**", ephemeral=True) | |
| await log_event(interaction.guild, f"โถ๏ธ ุชู ุงูุชุดุบูู ุนุจุฑ ุฃู ุฑ /play_radio") | |
| except: pass | |
| async def stop_radio(interaction: discord.Interaction): | |
| vc = interaction.guild.voice_client | |
| try: | |
| if vc and vc.is_playing(): | |
| vc.pause() | |
| await interaction.response.send_message("โน๏ธ ุชู ุงูุฅููุงู.", ephemeral=True) | |
| await log_event(interaction.guild, f"โน๏ธ ุชู ุงูุฅููุงู ุนุจุฑ ุฃู ุฑ /stop_radio") | |
| else: | |
| await interaction.response.send_message("โ ๏ธ ู ุชููู ุจุงููุนู.", ephemeral=True) | |
| except: pass | |
| async def set_volume(interaction: discord.Interaction, level: int): | |
| global current_volume | |
| try: | |
| if level < 1 or level > 100: | |
| return await interaction.response.send_message("โ ูุฑุฌู ุฅุฏุฎุงู ุฑูู ุจูู 1 ู 100.", ephemeral=True) | |
| current_volume = level / 100.0 | |
| vc = interaction.guild.voice_client | |
| if vc and vc.source: vc.source.volume = current_volume | |
| await interaction.response.send_message(f"๐ ุชู ุชุบููุฑ ุฏุฑุฌุฉ ุงูุตูุช ุฅูู: **{level}%**", ephemeral=True) | |
| await log_event(interaction.guild, f"๐ ุชู ุชุบููุฑ ุฏุฑุฌุฉ ุงูุตูุช ุฅูู {level}%") | |
| except: pass | |
| # ======================================================= | |
| # ุงูุชุดุบูู ูุงูู Keep Alive | |
| # ======================================================= | |
| try: | |
| from keep_alive import keep_alive | |
| keep_alive() | |
| except Exception: pass | |
| if __name__ == "__main__": | |
| TOKEN = os.environ.get("DISCORD_TOKEN") | |
| if TOKEN: bot.run(TOKEN) | |
| else: print("โ ุงูุชููู ู ูููุฏ! ูุฑุฌู ุงูุชุฃูุฏ ู ู ูุถุนู ูู ุงูู ุชุบูุฑุงุช ุงูุจูุฆูุฉ (Secrets).") | |