From 83b04d76b5a3bf1b89bfe46b2e52e5fc1a77b9a0 Mon Sep 17 00:00:00 2001 From: yasirarism <55983182+yasirarism@users.noreply.github.com> Date: Sat, 1 Apr 2023 12:06:47 +0700 Subject: [PATCH] Beta MultiLang (#26) --- database/karma_db.py | 4 +- database/locale_db.py | 2 +- locales/en-US/admin.json | 2 +- locales/en-US/afk.json | 13 + locales/en-US/dev.json | 11 + locales/en-US/genss.json | 13 + locales/en-US/nightmodev2.json | 17 + locales/en-US/start_help.json | 11 + locales/en-US/web_scraper.json | 19 +- locales/en-US/ytdl_plugins.json | 13 + locales/id-ID/admin.json | 26 +- locales/id-ID/afk.json | 13 + locales/id-ID/chatbot_ai.json | 4 +- locales/id-ID/dev.json | 11 + locales/id-ID/genss.json | 13 + locales/id-ID/lang_setting.json | 2 +- locales/id-ID/mediainfo.json | 6 +- locales/id-ID/nightmodev2.json | 17 + locales/id-ID/start_help.json | 11 + locales/id-ID/stickers.json | 2 +- locales/id-ID/web_scraper.json | 19 +- locales/id-ID/ytdl_plugins.json | 13 + locales/id-JW/admin.json | 12 +- locales/id-JW/afk.json | 13 + locales/id-JW/chatbot_ai.json | 4 +- locales/id-JW/dev.json | 11 + locales/id-JW/genss.json | 13 + locales/id-JW/mediainfo.json | 6 +- locales/id-JW/nightmodev2.json | 17 + locales/id-JW/start_help.json | 11 + locales/id-JW/stickers.json | 2 +- locales/id-JW/web_scraper.json | 19 +- locales/id-JW/ytdl_plugins.json | 13 + misskaty/__main__.py | 299 +------------- misskaty/core/decorator/permissions.py | 42 +- misskaty/helper/localization.py | 2 +- misskaty/plugins/admin.py | 56 +-- misskaty/plugins/afk.py | 252 +++++++++++- misskaty/plugins/bypass.py | 1 + misskaty/plugins/detect_afk.py | 234 ----------- misskaty/plugins/dev.py | 39 +- misskaty/plugins/fun.py | 1 - misskaty/plugins/genss.py | 32 +- misskaty/plugins/karma.py | 92 +++-- misskaty/plugins/mediainfo.py | 8 +- misskaty/plugins/nightmodev2.py | 46 ++- misskaty/plugins/ocr.py | 2 +- misskaty/plugins/start_help.py | 292 ++++++++++++++ misskaty/plugins/web_scraper.py | 375 ++++++++++-------- .../{ytdl_download_new.py => ytdl_plugins.py} | 61 +-- 50 files changed, 1296 insertions(+), 901 deletions(-) create mode 100644 locales/en-US/afk.json create mode 100644 locales/en-US/dev.json create mode 100644 locales/en-US/genss.json create mode 100644 locales/en-US/nightmodev2.json create mode 100644 locales/en-US/start_help.json create mode 100644 locales/en-US/ytdl_plugins.json create mode 100644 locales/id-ID/afk.json create mode 100644 locales/id-ID/dev.json create mode 100644 locales/id-ID/genss.json create mode 100644 locales/id-ID/nightmodev2.json create mode 100644 locales/id-ID/start_help.json create mode 100644 locales/id-ID/ytdl_plugins.json create mode 100644 locales/id-JW/afk.json create mode 100644 locales/id-JW/dev.json create mode 100644 locales/id-JW/genss.json create mode 100644 locales/id-JW/nightmodev2.json create mode 100644 locales/id-JW/start_help.json create mode 100644 locales/id-JW/ytdl_plugins.json delete mode 100644 misskaty/plugins/detect_afk.py create mode 100644 misskaty/plugins/start_help.py rename misskaty/plugins/{ytdl_download_new.py => ytdl_plugins.py} (78%) diff --git a/database/karma_db.py b/database/karma_db.py index 0ef04570..2d6ff454 100644 --- a/database/karma_db.py +++ b/database/karma_db.py @@ -48,7 +48,9 @@ async def update_karma(chat_id: int, name: str, karma: dict): async def is_karma_on(chat_id: int) -> bool: chat = await karmadb.find_one({"chat_id_toggle": chat_id}) - return bool(chat) + if not chat: + return True + return False async def karma_on(chat_id: int): diff --git a/database/locale_db.py b/database/locale_db.py index d8385dff..e81dd0f3 100644 --- a/database/locale_db.py +++ b/database/locale_db.py @@ -11,6 +11,6 @@ async def set_db_lang(chat_id: int, chat_type: str, lang_code: str): await localesdb.update_one({"chat_id": chat_id}, {"$set": {"lang": lang_code, "chat_type": chat_type.value}}, upsert=True) -async def get_db_lang(chat_id: int, chat_type: str) -> str: +async def get_db_lang(chat_id: int) -> str: ul = await localesdb.find_one({"chat_id": chat_id}) return ul["lang"] if ul else {} diff --git a/locales/en-US/admin.json b/locales/en-US/admin.json index 161af3d3..8470d1ee 100644 --- a/locales/en-US/admin.json +++ b/locales/en-US/admin.json @@ -1,7 +1,7 @@ { "no_admin_error": "You must be an administrator to use this command.", "no_permission_error": "I'm sorry but you don't have the required permissions to run this command. Missing permissions: {permissions}", - "private_not_allowed": "This command can't be used in a private chat. If you need any help, please use the /help command.", + "private_not_allowed": "This command can't be used in a private chat. If you need any help, please use the /help command.", "purge_no_reply": "Reply to a message to purge from.", "delete_no_reply": "Reply To A Message To Delete It", "pin_no_reply": "Reply to a message to pin/unpin it.", diff --git a/locales/en-US/afk.json b/locales/en-US/afk.json new file mode 100644 index 00000000..bdd7f0f7 --- /dev/null +++ b/locales/en-US/afk.json @@ -0,0 +1,13 @@ +{ + "no_channel": "This feature not supported for channel.", + "on_afk_msg_no_r": "**{usr}** [{id}] is back online and was away for {tm}\n\n", + "on_afk_msg_with_r": "**{usr}** [{id}] is back online and was away for {tm}\n\n**Reason:** `{reas}`\n\n", + "is_afk_msg_no_r": "**{usr}** [{id}] is AFK since {tm} ago.\n\n", + "is_afk_msg_with_r": "**{usr}** [{id}] is AFK since {tm} ago.\n\n**Reason:** {reas}\n\n", + "is_online": "**{usr}** [{id}] is back online", + "now_afk": "{usr} [{id}] is now AFK!.", + "afkdel_help": "**Usage:**\n/{cmd} [ENABLE|DISABLE] to enable or disable auto delete message.", + "afkdel_disable": "Disabled auto delete AFK message.", + "afkdel_enable": "Enabled auto delete AFK message in this chat.", + "is_afk": "{usr} [{id}] is AFK!." +} \ No newline at end of file diff --git a/locales/en-US/dev.json b/locales/en-US/dev.json new file mode 100644 index 00000000..111ef725 --- /dev/null +++ b/locales/en-US/dev.json @@ -0,0 +1,11 @@ +{ + "already_up": "Its already up-to date!", + "up_and_rest": "Updated with default branch, restarting now.", + "cl_btn": "❌ Close", + "no_eval": "__No evaluate message!__", + "run_eval": "Processing eval pyrogram..", + "run_exec": "Processing exec pyrogram..", + "no_cmd": "No command to execute was given.", + "success": "Success", + "no_reply": "No Reply" +} \ No newline at end of file diff --git a/locales/en-US/genss.json b/locales/en-US/genss.json new file mode 100644 index 00000000..964ea1c1 --- /dev/null +++ b/locales/en-US/genss.json @@ -0,0 +1,13 @@ +{ + "wait_msg": "Give me some time to process your request!! 😴", + "wait_dl": "Processing, please wait..", + "dl_progress": "Trying to download, please wait..", + "up_progress": "Trying to upload...", + "success_dl_msg": "File has been downloaded to {path}.", + "fail_open": "😟 Sorry! I cannot open the file.", + "limit_dl": "Sorry, download limited to 2GB to reduce flood. You can convert your files to link.", + "err_ssgen": "Failed screenshoot generation.\n\n{exc}", + "up_msg": "β˜‘οΈ Generation screenshot successfully.\n\n{namma} ({id})\n#️⃣ #ssgen #id{id}\n\nSS Generate by @{bot_uname}", + "no_reply": "Reply to a Telegram video or document or use direct link after command to generate screenshoot from media!", + "choose_no_ss": "Now choose how many result for screenshot? πŸ₯³.\n\nTotal duration: `{td}` (`{dur} second`)" +} \ No newline at end of file diff --git a/locales/en-US/nightmodev2.json b/locales/en-US/nightmodev2.json new file mode 100644 index 00000000..d952bc8f --- /dev/null +++ b/locales/en-US/nightmodev2.json @@ -0,0 +1,17 @@ +{ + "nmd_disabled": "Nightmode disabled.", + "nmd_not_enabled": "Nightmode isn't enabled in this chat.", + "invalid_time_format": "Invalid time format. Use HH:MM format.", + "invalid_lockdur": "Invalid time duration. Use proper format.\nExample: 6h (for 6 hours), 10m for 10 minutes.", + "schedule_already_on": "Already a schedule is running in this chat. Disable it using `-d` flag.", + "nmd_enable_success": "Successfully enabled nightmode in this chat.\nGroup will be locked at {st} and will be opened after {lockdur} everyday.", + "nmd_cb": "πŸ”– Hai, Aku {bname} dibuat menggunakan Framework Pyrogram v{ver} dan Python 3.10.\n\nMau buat bot seperti ini? Yuuk belajar di @botindonesia\nOwner: @YasirArisM", + "nmd_off_not_admin": "#NIGHTMODE_FAIL\nFailed to turn off nightmode at `{chat_id}`, since {bname} is not an admin in chat `{chat_id}`", + "nmd_off_not_present": "#NIGHTMODE_FAIL\nFailed to turn off nightmode at `{chat_id}`, since {bname} is not present in chat `{chat_id}`. Removed group from list.", + "nmd_off_err": "#NIGHTMODE_FAIL\nFailed to turn off nightmode at `{chat_id}`\nERROR: `{e}`", + "nmd_off_success": "#NIGHTMODE_HANDLER\nπŸ“† {dt}\n\nβ˜€οΈ Group is Opening.\nWill be closed at {close_at}", + "nmd_on_not_admin": "#NIGHTMODE_FAIL\nFailed to enable nightmode at `{chat_id}`, since {bname} is not an admin in chat `{chat_id}`", + "nmd_on_not_present": "#NIGHTMODE_FAIL\nFailed to enable nightmode at `{chat_id}`, since {bname} is not present in chat `{chat_id}`. Removed group from list.", + "nmd_on_err": "#NIGHTMODE_FAIL\nFailed to enable nightmode at `{chat_id}`\nERROR: `{e}`", + "nmd_on_success": "#NIGHTMODE_HANDLER\nπŸ“† {dt}\n\nπŸŒ— Group is closing.\nWill be opened at {open_at}" +} \ No newline at end of file diff --git a/locales/en-US/start_help.json b/locales/en-US/start_help.json new file mode 100644 index 00000000..adf6384d --- /dev/null +++ b/locales/en-US/start_help.json @@ -0,0 +1,11 @@ +{ + "newgroup_log": "#NewGroup\nGroup = {jdl}({id})\nMembers Count = {c}", + "newuser_log": "#NewUser\nID - {id}\nName - {nm}", + "help_name": "Here is the help for **{mod}**:\n", + "help_txt": "Hello {kamuh}, My name is {bot}.\nI'm a pyrogram bot that developed by kind owner with some useful features.\nYou can look by clicking a button below.\n\nGeneral command are:\n - /start: Start the bot\n - /help: Give this message\n - /setlang: Change bot language [BETA]", + "click_me": "Click Me", + "back_btn": "Back", + "click_btn": "Click on the below button to get help about {nm}", + "pm_detail": "PM Me For More Details.", + "start_msg": "Hi {kamuh}, PM me to know about all my features. You can change bot language in bot using /setlang command but it's still in beta stage." +} \ No newline at end of file diff --git a/locales/en-US/web_scraper.json b/locales/en-US/web_scraper.json index 9e26dfee..d364a6ee 100644 --- a/locales/en-US/web_scraper.json +++ b/locales/en-US/web_scraper.json @@ -1 +1,18 @@ -{} \ No newline at end of file +{ + "no_result": "Sorry, i couldn't find any results!", + "no_result_w_query": "Sorry, i could not find query: {kueri}", + "get_data": "⏳ Please wait, getting data from web..", + "cl_btn": "❌ Close", + "back_btn": "↩️ Back", + "dl_text": "⬇️ Download", + "cat_text": "Category", + "quality": "Quality", + "ex_data": "πŸ‘‡ Extract Data ", + "unauth": "This button is not for you..", + "invalid_cb": "Invalid callback data, please send command again..", + "res_scrape": "Scrape result from {link}:\n\n{kl}", + "header_with_query": "#{web} Results For: {kueri}\n\n", + "header_no_query": "#{web} Latest:\nπŸŒ€ Use /{cmd} [title] to start search with title.\n\n", + "invalid_cmd_scrape": "Gunakan command /{cmd} [link] untuk scrap link download", + "unsupport_dl_btn": "Some result will not appear in extract button because unsupported link." +} \ No newline at end of file diff --git a/locales/en-US/ytdl_plugins.json b/locales/en-US/ytdl_plugins.json new file mode 100644 index 00000000..85f2269a --- /dev/null +++ b/locales/en-US/ytdl_plugins.json @@ -0,0 +1,13 @@ +{ + "no_channel": "This feature not supported for channel or anonymous user.", + "no_query": "Please input a query..!", + "no_res": "No result found for `{kweri}`", + "dl_btn": "Download", + "back": "Back", + "yts_msg": "Published {pub}\n\n❯ Duration: {dur}\n❯ Views: {vi}\n❯ Uploader: {cname}\n\n", + "invalid_link": "Please input a valid YT-DLP Supported URL", + "err_parse": "Failed parse URL, check logs..", + "wait": "Please wait..", + "unauth": "Not Your Task..", + "endlist": "That's the end of list" +} \ No newline at end of file diff --git a/locales/id-ID/admin.json b/locales/id-ID/admin.json index 2b2af807..dcd08954 100644 --- a/locales/id-ID/admin.json +++ b/locales/id-ID/admin.json @@ -1,8 +1,8 @@ { - "no_admin_error": "Anda harus merupakan administrator untuk menggunakan perintah ini.", + "no_admin_error": "Anda harus menjadi administrator untuk menggunakan perintah ini.", "no_permission_error": "Maaf, tapi anda tidak memiliki izin yang diperlukan untuk menjalankan perintah ini. Izin yang hilang: {permissions}", - "private_not_allowed": "Perintah ini tidak dapat digunakan dalam obrolan pribadi, Jika anda membutuhkan bantuan, mohon gunakan perintah /help.", - "purge_no_reply": "Balas pesan untuk dihapus.", + "private_not_allowed": "Perintah ini tidak dapat digunakan dalam obrolan pribadi, Jika anda membutuhkan bantuan, mohon gunakan perintah /help.", + "purge_no_reply": "Balas ke pesan yang ingin dihapus.", "delete_no_reply": "Balas Pesan Untuk Menghapusnya", "pin_no_reply": "Balas pesan untuk menyematkan/melepas pin.", "report_no_reply": "Balas Pesan Untuk Melaporkan Pengguna Itu.", @@ -13,12 +13,12 @@ "kick_self_err": "Saya tidak dapat menendang diri sendiri, saya dapat pergi jika Anda mau.", "ban_self_err": "Saya tidak dapat melarang diri saya sendiri, saya dapat pergi jika Anda mau.", "report_self_err": "Mengapa Anda melaporkan diri sendiri?", - "demote_self_err": "Saya tidak dapat menurunkan pangkat diri saya sendiri.", + "demote_self_err": "Saya tidak dapat menurunkan keanggotaan diri saya sendiri.", "warn_self_err": "Saya tidak dapat memperingatkan diri sendiri.", - "mute_self_err": "Saya sendiri tidak dapat membisukan.", - "kick_sudo_err": "Wow, Anda ingin menendang pemilik saya?", - "ban_sudo_err": "Wow, Anda ingin mencoba mencekal pemilik saya?", - "demote_sudo_err": "Wow, Anda ingin mencoba menurunkan pemilik saya?", + "mute_self_err": "Saya tidak dapat membisukan diri sendiri.", + "kick_sudo_err": "Wow, Anda ingin menendang pemilik saya yang spesial?", + "ban_sudo_err": "Wow, Anda ingin mencoba membanned pemilik saya?", + "demote_sudo_err": "Wow, Anda ingin mencoba mendemote pemilik saya?", "warn_sudo_err": "Wow, Anda ingin mencoba memberi peringatan kepada pemilik saya?", "mute_sudo_err": "Wow, Anda ingin mencoba membisukan pemilik saya?", "kick_admin_err": "Hah, sungguh gila jika saya bisa menendang seorang admin.", @@ -28,13 +28,13 @@ "kick_msg": "**Pengguna yang Ditendang:** {mention} [{id}]\n**Ditendang Oleh:** {kicker}\n**Alasan:** {reasonmsg}", "ban_msg": "**Pengguna yang Dilarang:** {mention} [{id}]\n**Dilarang Oleh:** {banner}\n", "unban_msg": "__Banned dihapus oleh {mention}__", - "no_ban_permission": "Tolong beri saya izin larangan untuk melarang pengguna di grup ini.", + "no_ban_permission": "Tolong beri saya izin banned untuk membanned pengguna di grup ini.", "no_more_99": "Anda tidak dapat menggunakan lebih dari 99", "banned_time": "**Dilarang Untuk:** {val}\n", - "muted_time": "**Dimatikan Untuk:** {val}\n", + "muted_time": "**Dimute Untuk:** {val}\n", "banned_reason": "**Alasan:** {reas}", "unban_channel_err": "Anda tidak dapat membatalkan pemblokiran saluran", - "give_unban_user": "Berikan nama pengguna atau balas pesan pengguna untuk membatalkan larangan.", + "give_unban_user": "Berikan nama pengguna atau balas pesan pengguna untuk membatalkan banned.", "unban_success": "Berhasil membatalkan pemblokiran {umention}!", "give_idban_with_msg_link": "Berikan userid/nama pengguna beserta tautan pesan dan alasan pelarangan daftar", "give_idunban_with_msg_link": "Berikan userid/nama pengguna beserta tautan pesan dan alasan untuk membatalkan larangan", @@ -55,7 +55,7 @@ "report_msg": "Melaporkan {user_mention} ke admin!", "reported_is_admin": "Apakah Anda tahu bahwa pengguna yang Anda balas adalah seorang admin?", "user_no_warn": "Pengguna {mention} tidak memiliki peringatan.", - "ch_warn_msg": "User {mention} memiliki {warns}/3 peringatan.", + "ch_warn_msg": "Pengguna {mention} memiliki {warns}/3 peringatan.", "warn_msg": "**Pengguna yang Diperingatkan:** {mention}\n**Diperingatkan Oleh:** {warner}\n**Alasan:** {reas}\n**Peringatan:** {twarn}/ 3", "rmwarn_msg": "Peringatan {mention} telah dihapus.", "unwarn_msg": "Peringatan dihapus oleh {mention}.", @@ -63,6 +63,6 @@ "unmute_msg": "Disuarakan! {umention}", "reply_to_rm_warn": "Balas pesan untuk menghapus peringatan pengguna.", "exceed_warn_msg": "Jumlah peringatan dari {mention} terlampaui, DILARANG!", - "mute_msg": "**Pengguna yang Dibungkam:** {mention}\n**Dimatikan Oleh:** {muter}\n", + "mute_msg": "**Pengguna yang Dimute:** {mention}\n**Dimute Oleh:** {muter}\n", "rm_warn_btn": "🚨 Hapus Peringatan 🚨" } diff --git a/locales/id-ID/afk.json b/locales/id-ID/afk.json new file mode 100644 index 00000000..7ca88cb2 --- /dev/null +++ b/locales/id-ID/afk.json @@ -0,0 +1,13 @@ +{ + "no_channel": "Fitur ini tidak didukung untuk channel.", + "on_afk_msg_no_r": "**{usr}** [{id}] kembali online dan pergi selama {tm}\n\n", + "on_afk_msg_with_r": "**{usr}** [{id}] kembali online dan pergi untuk {tm}\n\n**Alasan:** `{reas}`\n\n", + "is_afk_msg_no_r": "**{usr}** [{id}] telah AFK sejak {tm} yang lalu.\n\n", + "is_afk_msg_with_r": "**{usr}** [{id}] telah AFK sejak {tm} yang lalu.\n\n**Alasan:** {reas}\n\n" , + "is_online": "**{usr}** [{id}] kembali online", + "now_afk": "{usr} [{id}] sekarang AFK!.", + "afkdel_help": "**Penggunaan:**\n/{cmd} [ENABLE|DISABLE] untuk mengaktifkan atau menonaktifkan hapus pesan AFK secara otomatis.", + "afkdel_disable": "Penghapusan otomatis pesan AFK dinonaktifkan.", + "afkdel_enable": "Penghapusan otomatis pesan AFK di obrolan ini diaktifkan.", + "is_afk": "{usr} [{id}] sedang AFK!." +} \ No newline at end of file diff --git a/locales/id-ID/chatbot_ai.json b/locales/id-ID/chatbot_ai.json index 266270fb..5080d9a4 100644 --- a/locales/id-ID/chatbot_ai.json +++ b/locales/id-ID/chatbot_ai.json @@ -1,5 +1,5 @@ { - "no_question": "Harap gunakan perintah /{cmd} [question] untuk mengajukan pertanyaan Anda.", - "find_answers_str": "Tunggu sebentar untuk mencari jawaban Anda..", + "no_question": "Harap gunakan perintah /{cmd} [question] untuk mengajukan pertanyaan Anda menggunakan OpenAI.", + "find_answers_str": "Sedang mencari jawaban terbaik buat Anda..", "answers_too_long": "Pertanyaan untuk jawaban Anda telah melampaui batas teks TG, periksa tautan ini untuk melihatnya.\n\n{answerlink}" } \ No newline at end of file diff --git a/locales/id-ID/dev.json b/locales/id-ID/dev.json new file mode 100644 index 00000000..f2e855e6 --- /dev/null +++ b/locales/id-ID/dev.json @@ -0,0 +1,11 @@ +{ + "already_up": "Sudah paling update!", + "up_and_rest": "Diperbarui dengan branch default, dimulai ulang sekarang.", + "cl_btn": "❌ Tutup", + "no_eval": "__Tidak ada pesan eval!__", + "run_eval": "Memproses pyrogram eval..", + "run_exec": "Memproses pyrogram eksekutif..", + "no_cmd": "Tidak ada perintah untuk dieksekusi.", + "sukses": "Sukses", + "no_reply": "Tidak ada balasan" +} \ No newline at end of file diff --git a/locales/id-ID/genss.json b/locales/id-ID/genss.json new file mode 100644 index 00000000..980b0522 --- /dev/null +++ b/locales/id-ID/genss.json @@ -0,0 +1,13 @@ +{ + "wait_msg": "Beri saya waktu untuk memproses permintaan Anda!! 😴", + "wait_dl": "Sedang diproses, harap tunggu..", + "dl_progress": "Mencoba mengunduh, harap tunggu..", + "up_progress": "Mencoba mengunggah...", + "success_dl_msg": "Berkas telah diunduh ke {path}.", + "fail_open": "😟 Maaf! Saya tidak dapat membuka file.", + "limit_dl": "Maaf, unduh terbatas hingga 2GB untuk mengurangi flood. Anda dapat mengkonversi file Anda menjadi tautan.", + "err_ssgen": "Pembuatan screenshot gagal.\n\n{exc}", + "up_msg": "β˜‘οΈ Pembuatan screenshot berhasil.\n\n{namma} ({id})\n#️⃣ #ssgen #id{id}\n\nSS Dibuat oleh @{bot_uname} ", + "no_reply": "Balas video atau dokumen Telegram atau gunakan tautan langsung setelah perintah untuk membuat screenshot dari media!", + "choose_no_ss": "Sekarang pilih berapa hasil screenshot? πŸ₯³.\n\nTotal durasi: `{td}` (`{dur} detik`)" +} \ No newline at end of file diff --git a/locales/id-ID/lang_setting.json b/locales/id-ID/lang_setting.json index 7c70197e..bae662bf 100644 --- a/locales/id-ID/lang_setting.json +++ b/locales/id-ID/lang_setting.json @@ -1,5 +1,5 @@ { "language_changed_successfully": "Bahasa telah berhasil diubah.", "language_changer_chat": "Di sini Anda dapat mengubah bahasa yang digunakan bot selama obrolan.\nJika bahasa Anda tidak ada di sini dan Anda ingin berkontribusi, Anda dapat membuka masalah di github saya. .", - "language_changer_private": "Di sini Anda dapat mengubah bahasa yang digunakan oleh bot dalam obrolan pribadi ini.\n\nJika Anda ingin mengubah bahasa grup Anda, buka perintah /setchatlang. \nJika bahasa Anda tidak ada di sini dan Anda ingin berkontribusi, kunjungi repo misskaty." + "language_changer_private": "Di sini Anda dapat mengubah bahasa yang digunakan oleh bot dalam obrolan pribadi ini.\n\nJika Anda ingin mengubah bahasa grup Anda, buka perintah /setchatlang. \nJika bahasa Anda tidak ada di sini dan Anda ingin berkontribusi, buka repo misskaty di github." } \ No newline at end of file diff --git a/locales/id-ID/mediainfo.json b/locales/id-ID/mediainfo.json index 74ee7ade..6c719fec 100644 --- a/locales/id-ID/mediainfo.json +++ b/locales/id-ID/mediainfo.json @@ -3,9 +3,9 @@ "wait_msg": "`Mohon tunggu sementara...`", "err_link": "Sepertinya tautan yang Anda kirim tidak valid, pastikan tautan langsung dan bisa di unduh.", "media_invalid": "Silakan balas ke media yang valid.", - "dl_limit_exceeded": "Maaf, unduh dibatasi hingga 2GB untuk mengurangi banjir. Anda dapat mengonversi berkas Anda menjadi tautan.", + "dl_limit_exceeded": "Maaf, unduh dibatasi hingga 2GB untuk mengurangi flood. Anda dapat mengonversi berkas Anda menjadi tautan.", "dl_args_text": "Mencoba mengunduh..", "mediainfo_help": "Gunakan perintah /{cmd} [tautan], atau balas telegram media dengan /{cmd}.", - "capt_media": "ℹ️ Hasil mediainfo anda..\n\n**Request Oleh:** {ment}", - "viewweb": "πŸ’¬ Buka di Web" + "capt_media": "ℹ️ Hasil mediainfo anda..\n\n**Diminta Oleh:** {ment}", + "viweb": "πŸ’¬ Buka di Web" } \ No newline at end of file diff --git a/locales/id-ID/nightmodev2.json b/locales/id-ID/nightmodev2.json new file mode 100644 index 00000000..f8cf223d --- /dev/null +++ b/locales/id-ID/nightmodev2.json @@ -0,0 +1,17 @@ +{ + "nmd_disabled": "Mode malam dinonaktifkan.", + "nmd_not_enabled": "Mode malam tidak diaktifkan di obrolan ini.", + "invalid_time_format": "Format waktu tidak sah. Gunakan format HH:MM.", + "invalid_lockdur": "Durasi waktu tidak valid. Gunakan format yang tepat.\nContoh: 6j (selama 6 jam), 10m selama 10 menit.", + "schedule_already_on": "Sudah ada jadwal yang berjalan di obrolan ini. Nonaktifkan menggunakan tanda `-d`.", + "nmd_enable_success": "Berhasil mengaktifkan mode malam dalam obrolan ini.\nGrup akan dikunci pada {st} dan akan dibuka setelah {lockdur} setiap hari.", + "nmd_cb": "πŸ”– Hai, Saya {bname} dibuat menggunakan Framework Pyrogram v{ver} dan Python 3.10.\n\nMau buat bot seperti ini? Yuuk belajar di @botindonesia\nOwner: @YasirArisM", + "nmd_off_not_admin": "#NIGHTMODE_FAIL\nGagal mematikan mode malam di `{chat_id}`, karena {bname} bukan admin di obrolan `{chat_id}`", + "nmd_off_not_present": "#NIGHTMODE_FAIL\nGagal mematikan mode malam di `{chat_id}`, karena {bname} tidak ada di obrolan `{chat_id}`. Menghapus grup dari daftar.", + "nmd_off_err": "#NIGHTMODE_FAIL\nGagal mematikan mode malam di `{chat_id}`\nERROR: `{e}`", + "nmd_off_success": "#NIGHTMODE_HANDLER\nπŸ“† {dt}\n\nβ˜€οΈ Grup sedang dibuka.\nAkan ditutup pada {close_at}", + "nmd_on_not_admin": "#NIGHTMODE_FAIL\nGagal mengaktifkan mode malam di `{chat_id}`, karena {bname} bukan admin di obrolan `{chat_id}`", + "nmd_on_not_present": "#NIGHTMODE_FAIL\nGagal mengaktifkan mode malam di `{chat_id}`, karena {bname} tidak ada di obrolan `{chat_id}`. Grup dihapus dari daftar.", + "nmd_on_err": "#NIGHTMODE_FAIL\nGagal mengaktifkan mode malam di `{chat_id}`\nERROR: `{e}`", + "nmd_on_success": "#NIGHTMODE_HANDLER\nπŸ“† {dt}\n\nπŸŒ— Grup ditutup.\nAkan dibuka pada {open_at}" +} \ No newline at end of file diff --git a/locales/id-ID/start_help.json b/locales/id-ID/start_help.json new file mode 100644 index 00000000..2919aa50 --- /dev/null +++ b/locales/id-ID/start_help.json @@ -0,0 +1,11 @@ +{ + "newgroup_log": "#NewGroup\nGroup = {jdl}({id})\nJumlah Anggota = {c}", + "newuser_log": "#PenggunaBaru\nID - {id}\nNama - {nm}", + "help_name": "Ini bantuan untuk **{mod}**:\n", + "help_txt": "Halo {kamuh}, Nama saya {bot}.\nSaya adalah bot pyrogram yang dikembangkan oleh pemilik yang baik hati dengan beberapa fitur berguna.\nAnda dapat melihat dengan mengeklik tombol di bawah.\n\nPerintah umum adalah :\n - /start: Mulai bot\n - /help: Berikan pesan ini\n - /setlang: Ubah bahasa bot [BETA]", + "click_me": "Klik Saya", + "back_btn": "Kembali", + "click_btn": "Klik tombol di bawah untuk mendapatkan bantuan tentang {nm}", + "pm_detail": "PM Saya Untuk Detail Lebih Lanjut.", + "start_msg": "Hai {kamuh}, PM saya untuk mengetahui semua fitur saya. Anda dapat mengubah bahasa bot di bot menggunakan perintah /setlang tetapi ini masih dalam tahap beta." +} \ No newline at end of file diff --git a/locales/id-ID/stickers.json b/locales/id-ID/stickers.json index 82869f12..cd69b711 100644 --- a/locales/id-ID/stickers.json +++ b/locales/id-ID/stickers.json @@ -14,6 +14,6 @@ "please_start_msg": "Tampaknya Anda belum pernah berinteraksi dengan saya dalam obrolan pribadi, Anda harus melakukannya dulu..", "click_me": "Klik Saya", "pack_full": "Paket Stiker Anda penuh jika paket Anda tidak dalam Tipe v1 /kang 1, jika tidak dalam Tipe v2 /kang 2 dan seterusnya.", - "viewpack": "πŸ‘€ Lihat Paket Anda", + "viewpack": "πŸ‘€ Lihat Paket", "kang_success": "Stiker berhasil dicuri!\nEmoji: {emot}" } \ No newline at end of file diff --git a/locales/id-ID/web_scraper.json b/locales/id-ID/web_scraper.json index 9e26dfee..fc77e00d 100644 --- a/locales/id-ID/web_scraper.json +++ b/locales/id-ID/web_scraper.json @@ -1 +1,18 @@ -{} \ No newline at end of file +{ + "no_result": "Maaf, saya tidak dapat menemukan hasil apa pun!", + "no_result_w_query": "Maaf, saya tidak dapat menemukan kueri: {kueri}", + "get_data": "⏳ Mohon tunggu, mengambil data dari web..", + "cl_btn": "❌ Tutup", + "back_btn": "↩️ Kembali", + "dl_text": "⬇️ Unduh", + "cat_text": "Kategori", + "kualitas": "Kualitas", + "ex_data": "πŸ‘‡ Ekstrak Data", + "unauth": "Tombol ini bukan untuk Anda..", + "invalid_cb": "Data callback tidak valid, silakan kirim perintah lagi..", + "res_scrape": "Hasil Scrape dari {link}:\n\n{kl}", + "header_with_query": "Hasil Pencarian #{web} Untuk: {kueri}\n\n", + "header_no_query": "#{web} Terbaru:\nπŸŒ€ Gunakan /{cmd} [judul] untuk memulai pencarian dengan judul.\n\n", + "invalid_cmd_scrape": "Gunakan perintah /{cmd} [tautan] untuk mengambil link unduhan.", + "unsupport_dl_btn": "Beberapa hasil tidak akan muncul di tombol ekstrak karena tautan tidak didukung." +} \ No newline at end of file diff --git a/locales/id-ID/ytdl_plugins.json b/locales/id-ID/ytdl_plugins.json new file mode 100644 index 00000000..88605d0b --- /dev/null +++ b/locales/id-ID/ytdl_plugins.json @@ -0,0 +1,13 @@ +{ + "no_channel": "Fitur ini tidak didukung untuk channel atau pengguna anonim.", + "no_query": "Silakan kirim link yang mau diunduh..!", + "no_res": "Tidak ada hasil yang ditemukan untuk `{kweri}`", + "dl_btn": "Unduh", + "kembali": "kembali", + "yts_msg": "Dipublikasikan {pub}\n\n❯ Durasi: {dur}\n❯ Penayangan: {vi}\n❯ Pengunggah:< /b> {cname}\n\n", + "invalid_link": "Masukkan URL yang Didukung YT-DLP yang valid", + "err_parse": "Gagal menguraikan URL, periksa log..", + "tunggu": "Harap tunggu..", + "unauth": "Bukan Tugas Anda..", + "endlist": "Itu adalah akhir dari daftar" +} \ No newline at end of file diff --git a/locales/id-JW/admin.json b/locales/id-JW/admin.json index 2c944aa6..ed529ee6 100644 --- a/locales/id-JW/admin.json +++ b/locales/id-JW/admin.json @@ -1,21 +1,21 @@ { "no_admin_error": "Sampeyan kudu dadi administrator kanggo nggunakake perintah iki.", - "no_permission_error": "Ngapunten, nanging sampeyan ora duwe idin sing dibutuhake kanggo nindakake perintah iki. Izin sing ilang: {idin}", - "private_not_allowed": "Perintah iki ora bisa digunakake ing obrolan pribadi, Yen sampeyan butuh bantuan, mohon nggunakake perintah /help.", + "no_permission_error": "Ngapunten, nanging sampeyan ora duwe izin sing dibutuhake kanggo nindakake perintah iki. Izin sing ilang: {permissions}", + "private_not_allowed": "Perintah iki ora bisa digunakake ing obrolan pribadi, Yen sampeyan butuh bantuan, mohon nggunakake perintah /help.", "purge_no_reply": "Bales pesen sing arep dibusak.", "delete_no_reply": "Bales Pesen Kanggo Mbusak", "pin_no_reply": "Bales pesen sing arep disematke/copot.", "report_no_reply": "Bales Pesen Kanggo Nglaporake Panganggo.", - "no_delete_perm": "Tulung aku idin mbusak pesen.", + "no_delete_perm": "Tulung aku kei izin mbusak pesen.", "purge_success": "Kasil mbusak {del_total} pesen..", "user_not_found": "Aku ora bisa nemokake panganggo kuwi.", "invalid_id_uname": "⚠️ panganggo/jeneng panganggo ora sah", "kick_self_err": "Aku ora bisa nyepak awakku dhewe, aku bisa lunga yen sampeyan pengin.", "ban_self_err": "Aku ora bisa nglarang aku, aku bisa lunga yen sampeyan pengin.", "report_self_err": "Kenging menapa panjenengan lapor piyambak?", - "demote_self_err": "Aku ora bisa mudhun mudhun.", + "demote_self_err": "Aku ora bisa mudhun dhewe.", "warn_self_err": "Aku ora bisa ngelekake awakku dhewe.", - "mute_self_err": "Aku ora bisa bisu.", + "mute_self_err": "Aku ora bisa bisu awakku dhewe.", "kick_sudo_err": "Wah, kowe arep nyepak juraganku?", "ban_sudo_err": "Wah, sampeyan pengin nyoba nglarang pemilikku?", "demote_sudo_err": "Wah, sampeyan pengin nyoba nurunake pemilikku?", @@ -51,7 +51,7 @@ "normal_promote": "Dipromosikan {umention}!", "pin_success": "**Semat [iki]({link}) pesen.**", "unpin_success": "**Pesen [iki] ({pranala}) ora disemat.**", - "pin_no_perm": "Tulung wenehi pin idin kanggo nggunakake printah iki!.", + "pin_no_perm": "Tulung wenehi pin izin kanggo nggunakake printah iki!.", "report_msg": "Kacarita {user_mention} menyang admin!", "reported_is_admin": "Apa sampeyan ngerti yen pangguna sing sampeyan bales iku admin?", "user_no_warn": "Panganggo {mention} ora ana bebaya.", diff --git a/locales/id-JW/afk.json b/locales/id-JW/afk.json new file mode 100644 index 00000000..0f37044a --- /dev/null +++ b/locales/id-JW/afk.json @@ -0,0 +1,13 @@ +{ + "no_channel": "Fitur iki ora didhukung kanggo channel.", + "on_afk_msg_no_r": "**{usr}** [{id}] wis online maneh lan ora ana ing {tm}\n\n", + "on_afk_msg_with_r": "**{usr}** [{id}] wis online maneh lan ora ana {tm}\n\n**Alesan:** `{reas}`\n\n", + "is_afk_msg_no_r": "**{usr}** [{id}] iku AFK wiwit {tm} kepungkur.\n\n", + "is_afk_msg_with_r": "**{usr}** [{id}] iku AFK wiwit {tm} kepungkur.\n\n**Alesan:** {reas}\n\n" , + "is_online": "**{usr}** [{id}] wis online maneh", + "now_afk": "{usr} [{id}] saiki dadi AFK!.", + "afkdel_help": "**Panganggone:**\n/{cmd} [ENABLE|DISABLE] kanggo ngaktifake utawa mateni pesen otomatis mbusak.", + "afkdel_disable": "Mbusak pesen AFK otomatis dipateni.", + "afkdel_enable": "Mbusak pesen AFK otomatis ing obrolan iki diaktifake.", + "is_afk": "{usr} [{id}] iku AFK!." +} \ No newline at end of file diff --git a/locales/id-JW/chatbot_ai.json b/locales/id-JW/chatbot_ai.json index 1e2c1b1a..e674a2e2 100644 --- a/locales/id-JW/chatbot_ai.json +++ b/locales/id-JW/chatbot_ai.json @@ -1,5 +1,5 @@ { - "no_question": "Tulung gunakake printah /{cmd} [pitakon] kanggo takon.", - "find_answers_str": "Ngenteni sedhela goleki jawabanmu..", + "no_question": "Tulung gunakake printah /{cmd} [pitakon] kanggo takon nganggo fitur OpenAI.", + "find_answers_str": "Lagi goleki jawaban paling apik kanggo sampeyan..", "answers_too_long": "Pitakonan kanggo jawaban sampeyan wis ngluwihi wates teks TG, priksa pranala iki kanggo ndeleng.\n\n{answerlink}" } \ No newline at end of file diff --git a/locales/id-JW/dev.json b/locales/id-JW/dev.json new file mode 100644 index 00000000..490736f9 --- /dev/null +++ b/locales/id-JW/dev.json @@ -0,0 +1,11 @@ +{ + "already_up": "Wis up-to-date!", + "up_and_rest": "Dianyari nganggo branch standar, diwiwiti maneh saiki.", + "cl_btn": "❌ Tutup", + "no_eval": "__Ora ana pesen eval!__", + "run_eval": "Ngolah pyrogram eval..", + "run_exec": "Ngolah pyrogram exec..", + "no_cmd": "Ora ana prentah kanggo nglakokakΓ©.", + "success": "Sukses", + "no_reply": "Ora Wangsulan" +} \ No newline at end of file diff --git a/locales/id-JW/genss.json b/locales/id-JW/genss.json new file mode 100644 index 00000000..85155ab0 --- /dev/null +++ b/locales/id-JW/genss.json @@ -0,0 +1,13 @@ +{ + "wait_msg": "Wenehi wektu kanggo ngolah panjalukmu!! 😴", + "wait_dl": "Lagi diproses, mangga ngenteni..", + "dl_progress": "Nyoba ngundhuh, mangga ngenteni..", + "up_progress": "Nyoba ngunggah...", + "success_dl_msg": "Berkas wis diundhuh menyang {path}.", + "fail_open": "😟 Nuwun sewu! Aku ora bisa mbukak file.", + "limit_dl": "Nuwun sewu, download dibatesi nganti 2GB kanggo nyuda flood. Sampeyan bisa ngowahi file dadi link.", + "err_ssgen": "Gagal nggawe screenshoot.\n\n{exc}", + "up_msg": "β˜‘οΈ Screenshot generasi kasil.\n\n{namma} ({id})\n#️⃣ #ssgen #id{id}\n\nSS Digawe kalo @{bot_uname} ", + "no_reply": "Bales menyang video utawa dokumen Telegram utawa gunakake link langsung sawise printah kanggo ngasilake screenshot saka media!", + "choose_no_ss": "Saiki pilih pira asil kanggo screenshot? πŸ₯³.\n\nTotal durasi: `{td}` (`{dur} second`)" +} \ No newline at end of file diff --git a/locales/id-JW/mediainfo.json b/locales/id-JW/mediainfo.json index 447eefb0..00372a45 100644 --- a/locales/id-JW/mediainfo.json +++ b/locales/id-JW/mediainfo.json @@ -1,11 +1,11 @@ { "processing_text": "`Pengolahan, wektu total adhedhasar ukuran berkas panjenengan...`", - "wait_msg": "`Mohon tunggu sejenak...`", + "wait_msg": "`Tulung enteni sedhela...`", "err_link": "Kayak'e pranala sing dikirim ora valid, priksa link langsung lan bisa diundhuh.", "media_invalid": "Mangga mbales media sing bener.", - "dl_limit_exceeded": "Nuwun sewu, download diwatesi 2GB kanggo nyuda banjir. Sampeyan bisa ngowahi file dadi link.", + "dl_limit_exceeded": "Nuwun sewu, download diwatesi 2GB kanggo nyuda flood. Sampeyan bisa ngowahi file dadi link.", "dl_args_text": "Nyoba ngundhuh..", "mediainfo_help": "Gunakake printah /{cmd} [link], utawa bales media telegram nganggo /{cmd}.", - "capt_media": "ℹ️ Hasil mediainfo anda..\n\n**Panjalukan Oleh:** {ment}", + "capt_media": "ℹ️ Hasil mediainfo sampeyan..\n\n**Panjalukan Saka:** {ment}", "viweb": "πŸ’¬ Bukak Web" } \ No newline at end of file diff --git a/locales/id-JW/nightmodev2.json b/locales/id-JW/nightmodev2.json new file mode 100644 index 00000000..045218a7 --- /dev/null +++ b/locales/id-JW/nightmodev2.json @@ -0,0 +1,17 @@ +{ + "nmd_disabled": "Mode wengi dipateni.", + "nmd_not_enabled": "Mode wengi ora diaktifake ing obrolan iki.", + "invalid_time_format": "Format wektu ora valid. Gunakake format HH:MM.", + "invalid_lockdur": "Suwene wektu ora bener. Gunakake format sing bener.\nConto: 6h (6 jam), 10m kanggo 10 menit.", + "schedule_already_on": "Wis ana jadwal ing obrolan iki. Pateni nganggo gendΓ©ra `-d`.", + "nmd_enable_success": "Kasil ngaktifake mode wengi ing obrolan iki.\nGrup bakal dikunci ing {st} lan bakal dibukak sawise {lockdur} saben dina.", + "nmd_cb": "πŸ”– Hai, Aku {bname} digawe nganggo Framework Pyrogram v{ver} lan Python 3.10.\n\nMau gawe bot kaya iki? Yuuk belajar di @botindonesia\nOwner: @YasirArisM", + "nmd_off_not_admin": "#NIGHTMODE_FAIL\nGagal mateni nightmode ing `{chat_id}`, amarga {bname} dudu admin ing chat `{chat_id}`", + "nmd_off_not_present": "#NIGHTMODE_FAIL\nGagal mateni nightmode ing `{chat_id}`, amarga {bname} ora ana ing chat `{chat_id}`. Dibusak grup saka dhaptar.", + "nmd_off_err": "#NIGHTMODE_FAIL\nGagal mateni nightmode ing `{chat_id}`\nERROR: `{e}`", + "nmd_off_success": "#NIGHTMODE_HANDLER\nπŸ“† {dt}\n\nβ˜€οΈ Grup dibukak.\nBakal ditutup jam {close_at}", + "nmd_on_not_admin": "#NIGHTMODE_FAIL\nGagal ngaktifake mode wengi ing `{chat_id}`, amarga {bname} dudu admin ing chat `{chat_id}`", + "nmd_on_not_present": "#NIGHTMODE_FAIL\nGagal ngaktifake mode wengi ing `{chat_id}`, amarga {bname} ora ana ing obrolan `{chat_id}`. Grup dibusak saka dhaptar.", + "nmd_on_err": "#NIGHTMODE_FAIL\nGagal ngaktifake mode wengi ing `{chat_id}`\nERROR: `{e}`", + "nmd_on_success": "#NIGHTMODE_HANDLER\nπŸ“† {dt}\n\nπŸŒ— Grup ditutup.\nBakal dibukak ing {open_at}" +} \ No newline at end of file diff --git a/locales/id-JW/start_help.json b/locales/id-JW/start_help.json new file mode 100644 index 00000000..afc95879 --- /dev/null +++ b/locales/id-JW/start_help.json @@ -0,0 +1,11 @@ +{ + "newgroup_log": "#NewGroup\nGroup = {jdl}({id})\nJumlah Anggota = {c}", + "newuser_log": "#NewUser\nID - {id}\nJeneng - {nm}", + "help_name": "Iki bantuan kanggo **{mod}**:\n", + "help_txt": "Halo {kamuh}, jenengku {bot}.\nAku bot pyrogram sing dikembangake dening pemilik apik karo sawetara fitur migunani.\nSampeyan bisa ndeleng kanthi ngeklik tombol ing ngisor iki.\n\nPrentah umum yaiku :\n - /start: Miwiti bot\n - /help: Wenehi pesen iki\n - /setlang: Ganti basa bot [BETA]", + "click_me": "Klik Aku", + "back_btn": "Mbalik", + "click_btn": "Klik tombol ing ngisor iki kanggo njaluk bantuan babagan {nm}", + "pm_detail": "PM Aku Kanggo Rincian Liyane.", + "start_msg": "Halo {kamuh}, PM aku kanggo ngerti kabeh fiturku. Sampeyan bisa ngganti basa bot ing bot nggunakake perintah /setlang nanging isih ing tahap beta." +} \ No newline at end of file diff --git a/locales/id-JW/stickers.json b/locales/id-JW/stickers.json index 9936309a..19e38a7e 100644 --- a/locales/id-JW/stickers.json +++ b/locales/id-JW/stickers.json @@ -14,6 +14,6 @@ "please_start_msg": "Koyone sampeyan ora tau sesambungan karo aku ing obrolan pribadi, sampeyan kudu nglakoni dhisik..", "click_me": "Klik Aku", "pack_full": "Paket Stiker sampeyan kebak yen paket sampeyan ora ana ing tipe v1 /kang 1, yen ora ana ing Tipe v2 /kang 2 lan sapiturute.", - "viewpack": "πŸ‘€ Deleng Paket Sampeyan", + "viewpack": "πŸ‘€ Deleng Paket", "kang_success": "Stiker kasil dicolong!\nEmoji: {emot}" } \ No newline at end of file diff --git a/locales/id-JW/web_scraper.json b/locales/id-JW/web_scraper.json index 9e26dfee..99dd9162 100644 --- a/locales/id-JW/web_scraper.json +++ b/locales/id-JW/web_scraper.json @@ -1 +1,18 @@ -{} \ No newline at end of file +{ + "no_result": "Nuwun sewu, kula mboten nemu kasil!", + "no_result_w_query": "Nuwun sewu, kula mboten saged manggihaken pitakon: {kueri}", + "get_data": "⏳ Mangga dienteni, lagi njupuk data saka web..", + "cl_btn": "❌ Tutup", + "back_btn": "↩️ Mbalik", + "dl_text": "⬇️ Unduh", + "cat_text": "πŸ’  Kategori", + "kualitas": "Kualitas", + "ex_data": "πŸ‘‡ Ekstrak Data ", + "unauth": "Tombol iki dudu kanggo sampeyan..", + "invalid_cb": "Data callback ora valid, kirim printah maneh..", + "res_scrape": "Asil scrape saka {link}:\n\n{kl}", + "header_with_query": "Asil Nggoleki #{web} Kanggo: {kueri}\n\n", + "header_no_query": "#{web} Paling anyar:\nπŸŒ€ Gunakake /{cmd} [judhul] kanggo miwiti nggoleki kanthi judhul.\n\n", + "invalid_cmd_scrape": "Gunakake prentah /{cmd} [pranala] kanggo ngunduh pranala kethokan", + "unsupport_dl_btn": "Sawetara asil ora bakal katon ing tombol ekstrak amarga pranala ora didhukung." +} \ No newline at end of file diff --git a/locales/id-JW/ytdl_plugins.json b/locales/id-JW/ytdl_plugins.json new file mode 100644 index 00000000..4170b220 --- /dev/null +++ b/locales/id-JW/ytdl_plugins.json @@ -0,0 +1,13 @@ +{ + "no_channel": "Fitur iki ora didhukung kanggo channel utawa pangguna anonim.", + "no_query": "Mangga lebokna url sing kepengen mbok unduh..!", + "no_res": "Ora ana asil kanggo `{kweri}`", + "dl_btn": "Ngunduh", + "back": "Mbalik", + "yts_msg": "Diterbitake {pub}\n\n❯ Duration: {dur}\n❯ Ndeleng: {vi}\n❯ Uploader:< /b> {cname}\n\n", + "invalid_link": "Mangga lebokna URL Dhukungan YT-DLP sing valid", + "err_parse": "Gagal ngurai URL, mriksa log..", + "ngenteni": "Tulung ngenteni..", + "unauth": "Ora Tugasmu..", + "endlist": "Iku pungkasan dhaptar" +} \ No newline at end of file diff --git a/misskaty/__main__.py b/misskaty/__main__.py index 9b89080c..fdad6cf0 100644 --- a/misskaty/__main__.py +++ b/misskaty/__main__.py @@ -7,17 +7,14 @@ """ import asyncio import importlib -import re import os import pickle import traceback from logging import getLogger -from pyrogram import __version__, filters, idle +from pyrogram import __version__, idle from pyrogram.raw.all import layer -from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup -from database.users_chats_db import db from misskaty import ( BOT_NAME, BOT_USERNAME, @@ -26,12 +23,9 @@ from misskaty import ( app, scheduler ) -from misskaty.core.message_utils import * -from misskaty.core.decorator.ratelimiter import ratelimiter -from misskaty.helper import bot_sys_stats, paginate_modules from misskaty.plugins import ALL_MODULES -from misskaty.vars import COMMAND_HANDLER, LOG_CHANNEL, SUDO -from utils import auto_clean, temp +from misskaty.vars import SUDO +from utils import auto_clean LOGGER = getLogger(__name__) loop = asyncio.get_event_loop() @@ -80,293 +74,6 @@ async def start_bot(): asyncio.create_task(auto_clean()) await idle() - -home_keyboard_pm = InlineKeyboardMarkup( - [ - [ - InlineKeyboardButton(text="Commands ❓", callback_data="bot_commands"), - InlineKeyboardButton( - text="Source Code πŸ› ", - url="https://github.com/yasirarism/MissKatyPyro", - ), - ], - [ - InlineKeyboardButton( - text="System Stats πŸ–₯", - callback_data="stats_callback", - ), - InlineKeyboardButton(text="Dev πŸ‘¨", url="https://t.me/YasirArisM"), - ], - [ - InlineKeyboardButton( - text="Add Me To Your Group πŸŽ‰", - url=f"http://t.me/{BOT_USERNAME}?startgroup=new", - ) - ], - ] -) - -home_text_pm = f"Hey there! My name is {BOT_NAME}. I have many useful features for you, feel free to add me to your group.\n\nIf you want give coffee to my owner you can send /donate command for more info." - -keyboard = InlineKeyboardMarkup( - [ - [ - InlineKeyboardButton(text="Help ❓", url=f"t.me/{BOT_USERNAME}?start=help"), - InlineKeyboardButton( - text="Source Code οΏ½", - url="https://github.com/yasirarism/MissKatyPyro", - ), - ], - [ - InlineKeyboardButton( - text="System Stats πŸ’»", - callback_data="stats_callback", - ), - InlineKeyboardButton(text="Dev πŸ‘¨", url="https://t.me/YasirArisM"), - ], - ] -) - - -@app.on_message(filters.command("start", COMMAND_HANDLER)) -@ratelimiter -async def start(_, message): - if not message.from_user: return - if message.chat.type.value != "private": - if not await db.get_chat(message.chat.id): - total = await app.get_chat_members_count(message.chat.id) - await app.send_message( - LOG_CHANNEL, - f"#NewGroup\nGroup = {message.chat.title}({message.chat.id})\nMembers Count = {total}\nAdded by - Unknown", - ) - - await db.add_chat(message.chat.id, message.chat.title) - nama = ( - message.from_user.mention - if message.from_user - else message.sender_chat.title - ) - return await message.reply_photo( - photo="https://telegra.ph/file/90e9a448bc2f8b055b762.jpg", - caption=f"Hi {nama}, PM me to know about all my features. You can change bot language in bot using /setlang command but it's in beta stage.", - reply_markup=keyboard, - ) - if not await db.is_user_exist(message.from_user.id): - await db.add_user(message.from_user.id, message.from_user.first_name) - await app.send_message( - LOG_CHANNEL, - f"#NewUser\nID - {message.from_user.id}\nName - {message.from_user.mention}", - ) - - if len(message.text.split()) > 1: - name = (message.text.split(None, 1)[1]).lower() - if "_" in name: - module = name.split("_", 1)[1] - text = ( - f"Here is the help for **{HELPABLE[module].__MODULE__}**:\n" - + HELPABLE[module].__HELP__ - ) - await kirimPesan(message, text, disable_web_page_preview=True) - elif name == "help": - text, keyb = await help_parser(message.from_user.first_name) - await kirimPesan( - message, - text, - reply_markup=keyb, - ) - else: - await message.reply_photo( - photo="https://telegra.ph/file/90e9a448bc2f8b055b762.jpg", - caption=home_text_pm, - reply_markup=home_keyboard_pm, - ) - - -@app.on_callback_query(filters.regex("bot_commands")) -@ratelimiter -async def commands_callbacc(_, CallbackQuery): - text, keyboard = await help_parser(CallbackQuery.from_user.mention) - await app.send_message( - CallbackQuery.message.chat.id, - text=text, - reply_markup=keyboard, - ) - await hapusPesan(CallbackQuery.message) - - -@app.on_callback_query(filters.regex("stats_callback")) -@ratelimiter -async def stats_callbacc(_, CallbackQuery): - text = await bot_sys_stats() - await app.answer_callback_query(CallbackQuery.id, text, show_alert=True) - - -@app.on_message(filters.command("help", COMMAND_HANDLER)) -@ratelimiter -async def help_command(_, message): - if not message.from_user: return - if message.chat.type.value != "private": - if not await db.get_chat(message.chat.id): - total = await app.get_chat_members_count(message.chat.id) - await app.send_message( - LOG_CHANNEL, - f"#NewGroup\nGroup = {message.chat.title}({message.chat.id})\nMembers Count = {total}\nAdded by - Unknown", - ) - - await db.add_chat(message.chat.id, message.chat.title) - if len(message.command) >= 2: - name = (message.text.split(None, 1)[1]).replace(" ", "_").lower() - if str(name) in HELPABLE: - key = InlineKeyboardMarkup( - [ - [ - InlineKeyboardButton( - text="Click here", - url=f"t.me/{BOT_USERNAME}?start=help_{name}", - ) - ], - ] - ) - await kirimPesan( - message, - f"Click on the below button to get help about {name}", - reply_markup=key, - ) - else: - await kirimPesan(message, "PM Me For More Details.", reply_markup=keyboard) - else: - await kirimPesan(message, "Pm Me For More Details.", reply_markup=keyboard) - else: - if not await db.is_user_exist(message.from_user.id): - await db.add_user(message.from_user.id, message.from_user.first_name) - await app.send_message( - LOG_CHANNEL, - f"#NewUser\nID - {message.from_user.id}\nName - {message.from_user.mention}", - ) - - if len(message.command) >= 2: - name = (message.text.split(None, 1)[1]).replace(" ", "_").lower() - if str(name) in HELPABLE: - text = ( - f"Here is the help for **{HELPABLE[name].__MODULE__}**:\n" - + HELPABLE[name].__HELP__ - ) - await kirimPesan(message, text, disable_web_page_preview=True) - else: - text, help_keyboard = await help_parser(message.from_user.first_name) - await kirimPesan( - message, - text, - reply_markup=help_keyboard, - disable_web_page_preview=True, - ) - else: - text, help_keyboard = await help_parser(message.from_user.first_name) - await kirimPesan( - message, text, reply_markup=help_keyboard, disable_web_page_preview=True - ) - return - - -async def help_parser(name, keyboard=None): - if not keyboard: - keyboard = InlineKeyboardMarkup(paginate_modules(0, HELPABLE, "help")) - return ( - """Hello {first_name}, My name is {bot_name}. -I'm a bot with some useful features. You can change language bot using /setlang command, but it's in beta stage. -You can choose an option below, by clicking a button. - -If you want give coffee to my owner you can send /donate command for more info. -""".format( - first_name=name, - bot_name="MissKaty", - ), - keyboard, - ) - - -@app.on_callback_query(filters.regex(r"help_(.*?)")) -@ratelimiter -async def help_button(client, query): - home_match = re.match(r"help_home\((.+?)\)", query.data) - mod_match = re.match(r"help_module\((.+?)\)", query.data) - prev_match = re.match(r"help_prev\((.+?)\)", query.data) - next_match = re.match(r"help_next\((.+?)\)", query.data) - back_match = re.match(r"help_back", query.data) - create_match = re.match(r"help_create", query.data) - top_text = f""" -Hello {query.from_user.first_name}, My name is MissKaty. -I'm a bot with some usefule features. -You can choose an option below, by clicking a button below. - -General command are: - - /start: Start the bot - - /help: Give this message - - /setlang: Change bot language [BETA] - """ - if mod_match: - module = mod_match[1].replace(" ", "_") - text = f"Here is the help for **{HELPABLE[module].__MODULE__}**:\n{HELPABLE[module].__HELP__}" - - await editPesan( - query.message, - text=text, - reply_markup=InlineKeyboardMarkup( - [[InlineKeyboardButton("back", callback_data="help_back")]] - ), - disable_web_page_preview=True, - ) - elif home_match: - await app.send_message( - query.from_user.id, - text=home_text_pm, - reply_markup=home_keyboard_pm, - ) - await hapusPesan(query.message) - elif prev_match: - curr_page = int(prev_match[1]) - await editPesan( - query.message, - text=top_text, - reply_markup=InlineKeyboardMarkup( - paginate_modules(curr_page - 1, HELPABLE, "help") - ), - disable_web_page_preview=True, - ) - - elif next_match: - next_page = int(next_match[1]) - await editPesan( - query.message, - text=top_text, - reply_markup=InlineKeyboardMarkup( - paginate_modules(next_page + 1, HELPABLE, "help") - ), - disable_web_page_preview=True, - ) - - elif back_match: - await editPesan( - query.message, - text=top_text, - reply_markup=InlineKeyboardMarkup(paginate_modules(0, HELPABLE, "help")), - disable_web_page_preview=True, - ) - - elif create_match: - text, keyboard = await help_parser(query) - await editPesan( - query.message, - text=text, - reply_markup=keyboard, - disable_web_page_preview=True, - ) - - return await client.answer_callback_query(query.id) - - - - if __name__ == "__main__": try: loop.run_until_complete(start_bot()) diff --git a/misskaty/core/decorator/permissions.py b/misskaty/core/decorator/permissions.py index 6af18b93..cdf099f7 100644 --- a/misskaty/core/decorator/permissions.py +++ b/misskaty/core/decorator/permissions.py @@ -39,6 +39,47 @@ async def member_permissions(chat_id: int, user_id: int): perms.append("can_manage_video_chats") return perms +async def check_perms( + message: Union[CallbackQuery, Message], + permissions: Optional[Union[list, str]], + complain_missing_perms: bool, + strings, +) -> bool: + if isinstance(message, CallbackQuery): + sender = partial(message.answer, show_alert=True) + chat = message.message.chat + else: + sender = message.reply_text + chat = message.chat + # TODO: Cache all admin permissions in db. + user = await chat.get_member(message.from_user.id) + if user.status == enums.ChatMemberStatus.OWNER: + return True + + # No permissions specified, accept being an admin. + if not permissions and user.status == enums.ChatMemberStatus.ADMINISTRATOR: + return True + if user.status != enums.ChatMemberStatus.ADMINISTRATOR: + if complain_missing_perms: + await sender(strings("no_admin_error")) + return False + + if isinstance(permissions, str): + permissions = [permissions] + + missing_perms = [ + permission + for permission in permissions + if not getattr(user.privileges, permission) + ] + + if not missing_perms: + return True + if complain_missing_perms: + await sender( + strings("no_permission_error").format(permissions=", ".join(missing_perms)) + ) + return False async def check_perms( message: Union[CallbackQuery, Message], @@ -148,7 +189,6 @@ def adminsOnly(permission): return subFunc - def require_admin( permissions: Union[list, str] = None, allow_in_private: bool = False, diff --git a/misskaty/helper/localization.py b/misskaty/helper/localization.py index 30354544..6076e24b 100644 --- a/misskaty/helper/localization.py +++ b/misskaty/helper/localization.py @@ -79,7 +79,7 @@ async def get_lang(message) -> str: else: raise TypeError(f"Update type '{message.__name__}' is not supported.") - lang = await get_db_lang(chat.id, chat.type) + lang = await get_db_lang(chat.id) if chat.type == ChatType.PRIVATE: lang = lang or message.from_user.language_code or default_language diff --git a/misskaty/plugins/admin.py b/misskaty/plugins/admin.py index 8dcc5896..54f27b6d 100644 --- a/misskaty/plugins/admin.py +++ b/misskaty/plugins/admin.py @@ -365,32 +365,28 @@ async def promoteFunc(client, message, strings): return await message.reply_text(strings("no_promote_perm")) if message.command[0][0] == "f": await message.chat.promote_member( - user_id, - ChatPrivileges( - can_change_info=bot.can_change_info, - can_invite_users=bot.can_invite_users, - can_delete_messages=bot.can_delete_messages, - can_restrict_members=bot.can_restrict_members, - can_pin_messages=bot.can_pin_messages, - can_promote_members=bot.can_promote_members, - can_manage_chat=bot.can_manage_chat, - can_manage_voice_chats=bot.can_manage_voice_chats, - ), + user_id=user_id, + can_change_info=bot.privileges.can_change_info, + can_invite_users=bot.privileges.can_invite_users, + can_delete_messages=bot.privileges.can_delete_messages, + can_restrict_members=bot.privileges.can_restrict_members, + can_pin_messages=bot.privileges.can_pin_messages, + can_promote_members=bot.privileges.can_promote_members, + can_manage_chat=bot.privileges.can_manage_chat, + can_manage_video_chats=bot.privileges.can_manage_video_chats, ) return await message.reply_text(strings("full_promote").format(umention=umention)) await message.chat.promote_member( - user_id, - ChatPrivileges( - can_change_info=False, - can_invite_users=bot.can_invite_users, - can_delete_messages=bot.can_delete_messages, - can_restrict_members=False, - can_pin_messages=False, - can_promote_members=False, - can_manage_chat=bot.can_manage_chat, - can_manage_voice_chats=bot.can_manage_voice_chats, - ), + user_id=user_id, + can_change_info=False, + can_invite_users=bot.privileges.can_invite_users, + can_delete_messages=bot.privileges.can_delete_messages, + can_restrict_members=bot.privileges.can_restrict_members, + can_pin_messages=bot.privileges.can_pin_messages, + can_promote_members=False, + can_manage_chat=bot.privileges.can_manage_chat, + can_manage_video_chats=bot.privileges.can_manage_video_chats, ) await message.reply_text(strings("normal_promote").format(umention=umention)) @@ -410,7 +406,17 @@ async def demote(client, message, strings): return await message.reply_text(strings("demote_self_err")) if user_id in SUDO: return await message.reply_text(strings("demote_sudo_err")) - await message.chat.promote_member(user_id=user_id) + await message.chat.promote_member( + user_id=user_id, + can_change_info=False, + can_invite_users=False, + can_delete_messages=False, + can_restrict_members=False, + can_pin_messages=False, + can_promote_members=False, + can_manage_chat=False, + can_manage_video_chats=False, + ) umention = (await app.get_users(user_id)).mention await message.reply_text(f"Demoted! {umention}") @@ -507,8 +513,8 @@ async def unmute(_, message, strings): if not user_id: return await message.reply_text(strings("user_not_found")) await message.chat.unban_member(user_id) - (await app.get_users(user_id)).mention - await message.reply_text(strings("unmute_msg")) + umention = (await app.get_users(user_id)).mention + await message.reply_text(strings("unmute_msg").format(umention=umention)) @app.on_message(filters.command(["warn", "dwarn"], COMMAND_HANDLER) & filters.group) diff --git a/misskaty/plugins/afk.py b/misskaty/plugins/afk.py index dafb5fe2..0babe409 100644 --- a/misskaty/plugins/afk.py +++ b/misskaty/plugins/afk.py @@ -10,8 +10,9 @@ # Modified plugin by me from https://github.com/TeamYukki/YukkiAFKBot to make compatible with pyrogram v2 import time +import re -from pyrogram import filters +from pyrogram import filters, enums from database.afk_db import add_afk, cleanmode_off, cleanmode_on, is_afk, remove_afk from misskaty import app @@ -20,6 +21,7 @@ from misskaty.core.decorator.permissions import adminsOnly from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.message_utils import kirimPesan from misskaty.helper import get_readable_time2 +from misskaty.helper.localization import use_chat_lang from misskaty.vars import COMMAND_HANDLER from utils import put_cleanmode @@ -34,9 +36,10 @@ Just type something in group to remove AFK Status.""" @capture_err @app.on_message(filters.command(["afk"], COMMAND_HANDLER)) @ratelimiter -async def active_afk(_, message): +@use_chat_lang() +async def active_afk(_, message, strings): if message.sender_chat: - return await kirimPesan(message, "This feature not supported for channel.") + return await kirimPesan(message, strings("no_channel")) user_id = message.from_user.id verifier, reasondb = await is_afk(user_id) if verifier: @@ -51,39 +54,39 @@ async def active_afk(_, message): send = ( await message.reply_animation( data, - caption=f"**{message.from_user.first_name}** is back online and was away for {seenago}", + caption=strings("on_afk_msg_no_r").format(usr=message.from_user.mention, id=message.from_user.id, tm=seenago), ) if str(reasonafk) == "None" else await message.reply_animation( data, - caption=f"**{message.from_user.first_name}** is back online and was away for {seenago}\n\nReason: `{reasonafk}`", + caption=strings("on_afk_msg_with_r").format(usr=message.from_user.mention, id=message.from_user.id, tm=seenago, reas=reasonafk), ) ) elif afktype == "photo": send = ( await message.reply_photo( photo=f"downloads/{user_id}.jpg", - caption=f"**{message.from_user.first_name}** is back online and was away for {seenago}", + caption=strings("on_afk_msg_no_r").format(usr=message.from_user.mention, id=message.from_user.id, tm=seenago), ) if str(reasonafk) == "None" else await message.reply_photo( photo=f"downloads/{user_id}.jpg", - caption=f"**{message.from_user.first_name}** is back online and was away for {seenago}\n\nReason: `{reasonafk}`", + caption=strings("on_afk_msg_with_r").format(usr=message.from_user.first_name, tm=seenago, reas=reasonafk), ) ) elif afktype == "text": send = await message.reply_text( - f"**{message.from_user.first_name}** is back online and was away for {seenago}", + caption=strings("on_afk_msg_no_r").format(usr=message.from_user.mention, id=message.from_user.id, tm=seenago), disable_web_page_preview=True, ) elif afktype == "text_reason": send = await message.reply_text( - f"**{message.from_user.first_name}** is back online and was away for {seenago}\n\nReason: `{reasonafk}`", + caption=strings("on_afk_msg_with_r").format(usr=message.from_user.mention, id=message.from_user.id, tm=seenago, reas=reasonafk), disable_web_page_preview=True, ) except Exception: send = await message.reply_text( - f"**{message.from_user.first_name}** is back online", + strings("is_online").format(usr=message.from_user.first_name), disable_web_page_preview=True, ) await put_cleanmode(message.chat.id, send.id) @@ -179,27 +182,242 @@ async def active_afk(_, message): } await add_afk(user_id, details) - send = await kirimPesan(message, f"{message.from_user.mention} [{message.from_user.id}] is now AFK!.") + send = await kirimPesan(message, strings("now_afk").format(usr=message.from_user.mention, id=message.from_user.id)) await put_cleanmode(message.chat.id, send.id) @app.on_message(filters.command("afkdel", COMMAND_HANDLER) & filters.group) @ratelimiter @adminsOnly("can_change_info") -async def afk_state(_, message): +@use_chat_lang() +async def afk_state(_, message, strings): if not message.from_user: return - usage = "**Usage:**\n/afkdel [ENABLE|DISABLE] to enable or disable auto delete message." if len(message.command) == 1: - return await kirimPesan(message, usage) + return await kirimPesan(message, strings("afkdel_help").format(cmd=message.command[0])) chat_id = message.chat.id state = message.text.split(None, 1)[1].strip() state = state.lower() if state == "enable": await cleanmode_on(chat_id) - await kirimPesan(message, "Enabled auto delete AFK message in this chat.") + await kirimPesan(message, strings("afkdel_enable")) elif state == "disable": await cleanmode_off(chat_id) - await kirimPesan(message, "Disabled auto delete AFK message.") + await kirimPesan(message, strings("afkdel_disable")) else: - await kirimPesan(message, usage) + await kirimPesan(message, strings("afkdel_help").format(cmd=message.command[0])) + + +# Detect user that AFK based on Yukki Repo +@app.on_message( + filters.group & ~filters.bot & ~filters.via_bot, + group=1, +) +@use_chat_lang() +async def chat_watcher_func(client, message, strings): + if message.sender_chat: + return + userid = message.from_user.id + user_name = message.from_user.mention + if message.entities: + possible = ["/afk", f"/afk@{client.me.username}", "!afk"] + message_text = message.text or message.caption + for entity in message.entities: + if entity.type == enums.MessageEntityType.BOT_COMMAND: + if (message_text[0 : 0 + entity.length]).lower() in possible: + return + + msg = "" + replied_user_id = 0 + + # Self AFK + verifier, reasondb = await is_afk(userid) + if verifier: + await remove_afk(userid) + try: + afktype = reasondb["type"] + timeafk = reasondb["time"] + data = reasondb["data"] + reasonafk = reasondb["reason"] + seenago = get_readable_time2((int(time.time() - timeafk))) + if afktype == "text": + msg += strings("on_afk_msg_no_r").format(usr=user_name, id=userid, tm=seenago) + if afktype == "text_reason": + msg += strings("on_afk_msg_with_r").format(usr=user_name, id=userid, tm=seenago, reas=reasonafk) + if afktype == "animation": + if str(reasonafk) == "None": + send = await message.reply_animation( + data, + caption=strings("on_afk_msg_no_r").format(usr=user_name, id=userid, tm=seenago), + ) + else: + send = await message.reply_animation( + data, + caption=strings("on_afk_msg_with_r").format(usr=user_name, id=userid, tm=seenago, reas=reasonafk), + ) + if afktype == "photo": + if str(reasonafk) == "None": + send = await message.reply_photo( + photo=f"downloads/{userid}.jpg", + caption=strings("on_afk_msg_no_r").format(usr=user_name, id=userid, tm=seenago), + ) + else: + send = await message.reply_photo( + photo=f"downloads/{userid}.jpg", + caption=strings("on_afk_msg_with_r").format(usr=user_name, id=userid, tm=seenago, reas=reasonafk), + ) + except: + msg += strings("is_online").format(usr=user_name, id=userid) + + # Replied to a User which is AFK + if message.reply_to_message: + try: + replied_first_name = message.reply_to_message.from_user.mention + replied_user_id = message.reply_to_message.from_user.id + verifier, reasondb = await is_afk(replied_user_id) + if verifier: + try: + afktype = reasondb["type"] + timeafk = reasondb["time"] + data = reasondb["data"] + reasonafk = reasondb["reason"] + seenago = get_readable_time2((int(time.time() - timeafk))) + if afktype == "text": + msg += strings("is_afk_msg_no_r").format(usr=replied_first_name, id=replied_user_id, tm=seenago) + if afktype == "text_reason": + msg += strings("is_afk_msg_with_r").format(usr=replied_first_name, id=replied_user_id, tm=seenago, reas=reasonafk) + if afktype == "animation": + if str(reasonafk) == "None": + send = await message.reply_animation( + data, + caption=strings("is_afk_msg_no_r").format(usr=replied_first_name, id=replied_user_id, tm=seenago), + ) + else: + send = await message.reply_animation( + data, + caption=strings("is_afk_msg_with_r").format(usr=replied_first_name, id=replied_user_id, tm=seenago, reas=reasonafk), + ) + if afktype == "photo": + if str(reasonafk) == "None": + send = await message.reply_photo( + photo=f"downloads/{replied_user_id}.jpg", + caption=strings("is_afk_msg_no_r").format(usr=replied_first_name, id=replied_user_id, tm=seenago), + ) + else: + send = await message.reply_photo( + photo=f"downloads/{replied_user_id}.jpg", + caption=strings("is_afk_msg_with_r").format(usr=replied_first_name, id=replied_user_id, tm=seenago, reas=reasonafk), + ) + except Exception: + msg += strings("is_afk").format(usr=replied_first_name, id=replied_user_id) + except: + pass + + # If username or mentioned user is AFK + if message.entities: + entity = message.entities + j = 0 + for x in range(len(entity)): + if (entity[j].type) == enums.MessageEntityType.MENTION: + found = re.findall("@([_0-9a-zA-Z]+)", message.text) + try: + get_user = found[j] + user = await app.get_users(get_user) + if user.id == replied_user_id: + j += 1 + continue + except: + j += 1 + continue + verifier, reasondb = await is_afk(user.id) + if verifier: + try: + afktype = reasondb["type"] + timeafk = reasondb["time"] + data = reasondb["data"] + reasonafk = reasondb["reason"] + seenago = get_readable_time2((int(time.time() - timeafk))) + if afktype == "text": + msg += strings("is_afk_msg_no_r").format(usr=user.first_name[:25], id=user.id, tm=seenago) + if afktype == "text_reason": + msg += strings("is_afk_msg_with_r").format(usr=user.first_name[:25], id=user.id, tm=seenago, reas=reasonafk) + if afktype == "animation": + if str(reasonafk) == "None": + send = await message.reply_animation( + data, + caption=strings("is_afk_msg_no_r").format(usr=user.first_name[:25], id=user.id, tm=seenago), + ) + else: + send = await message.reply_animation( + data, + caption=strings("is_afk_msg_with_r").format(usr=user.first_name[:25], id=user.id, tm=seenago, reas=reasonafk), + ) + if afktype == "photo": + if str(reasonafk) == "None": + send = await message.reply_photo( + photo=f"downloads/{user.id}.jpg", + caption=strings("is_afk_msg_no_r").format(usr=user.first_name[:25], id=user.id, tm=seenago), + ) + else: + send = await message.reply_photo( + photo=f"downloads/{user.id}.jpg", + caption=strings("is_afk_msg_with_r").format(usr=user.first_name[:25], id=user.id, tm=seenago, reas=reasonafk), + ) + except: + msg += strings("is_afk").format(usr=user.first_name[:25], id=user.id) + elif (entity[j].type) == enums.MessageEntityType.TEXT_MENTION: + try: + user_id = entity[j].user.id + if user_id == replied_user_id: + j += 1 + continue + first_name = entity[j].user.first_name + except: + j += 1 + continue + verifier, reasondb = await is_afk(user_id) + if verifier: + try: + afktype = reasondb["type"] + timeafk = reasondb["time"] + data = reasondb["data"] + reasonafk = reasondb["reason"] + seenago = get_readable_time2((int(time.time() - timeafk))) + if afktype == "text": + msg += strings("is_afk_msg_no_r").format(usr=first_name[:25], id=user_id, tm=seenago) + if afktype == "text_reason": + msg += strings("is_afk_msg_with_r").format(usr=first_name[:25], id=user_id, tm=seenago, reas=reasonafk) + if afktype == "animation": + if str(reasonafk) == "None": + send = await message.reply_animation( + data, + caption=strings("is_afk_msg_no_r").format(usr=first_name[:25], id=user_id, tm=seenago), + ) + else: + send = await message.reply_animation( + data, + caption=strings("is_afk_msg_with_r").format(usr=first_name[:25], id=user_id, tm=seenago, reas=reasonafk), + ) + if afktype == "photo": + if str(reasonafk) == "None": + send = await message.reply_photo( + photo=f"downloads/{user_id}.jpg", + caption=strings("is_afk_msg_no_r").format(usr=first_name[:25], id=user_id, tm=seenago), + ) + else: + send = await message.reply_photo( + photo=f"downloads/{user_id}.jpg", + caption=strings("is_afk_msg_with_r").format(usr=first_name[:25], id=user_id, tm=seenago, reas=reasonafk), + ) + except: + msg += strings("is_afk").format(usr=first_name[:25], id=user_id) + j += 1 + if msg != "": + try: + send = await message.reply_text(msg, disable_web_page_preview=True) + except: + pass + try: + await put_cleanmode(message.chat.id, send.id) + except: + pass \ No newline at end of file diff --git a/misskaty/plugins/bypass.py b/misskaty/plugins/bypass.py index d1c76b1e..cf35a2aa 100644 --- a/misskaty/plugins/bypass.py +++ b/misskaty/plugins/bypass.py @@ -37,6 +37,7 @@ Supported Link: Credit: PyBypass """ +# Stopped development for this plugin since always changed time by time. async def pling_bypass(url): try: diff --git a/misskaty/plugins/detect_afk.py b/misskaty/plugins/detect_afk.py deleted file mode 100644 index ce93a984..00000000 --- a/misskaty/plugins/detect_afk.py +++ /dev/null @@ -1,234 +0,0 @@ -# -# Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >. -# -# This file is part of < https://github.com/TeamYukki/YukkiAFKBot > project, -# and is released under the "GNU v3.0 License Agreement". -# Please see < https://github.com/TeamYukki/YukkiAFKBot/blob/master/LICENSE > -# -# All rights reserved. -# - -# Modified plugin by me from https://github.com/TeamYukki/YukkiAFKBot to make compatible with pyrogram v2 -import re -import time - -from pyrogram import enums, filters - -from database.afk_db import is_afk, remove_afk -from misskaty import BOT_USERNAME, app -from misskaty.helper.human_read import get_readable_time2 -from utils import put_cleanmode - - -# Detect user that AFK based on Yukki Repo -@app.on_message( - filters.group & ~filters.bot & ~filters.via_bot, - group=1, -) -async def chat_watcher_func(_, message): - if message.sender_chat: - return - userid = message.from_user.id - user_name = message.from_user.first_name - if message.entities: - possible = ["/afk", f"/afk@{BOT_USERNAME}", "!afk"] - message_text = message.text or message.caption - for entity in message.entities: - if entity.type == enums.MessageEntityType.BOT_COMMAND: - if (message_text[0 : 0 + entity.length]).lower() in possible: - return - - msg = "" - replied_user_id = 0 - - # Self AFK - verifier, reasondb = await is_afk(userid) - if verifier: - await remove_afk(userid) - try: - afktype = reasondb["type"] - timeafk = reasondb["time"] - data = reasondb["data"] - reasonafk = reasondb["reason"] - seenago = get_readable_time2((int(time.time() - timeafk))) - if afktype == "text": - msg += f"**{user_name[:25]}** is back online and was away for {seenago}\n\n" - if afktype == "text_reason": - msg += f"**{user_name[:25]}** is back online and was away for {seenago}\n\n**Reason:** {reasonafk}\n\n" - if afktype == "animation": - if str(reasonafk) == "None": - send = await message.reply_animation( - data, - caption=f"**{user_name[:25]}** is back online and was away for {seenago}\n\n", - ) - else: - send = await message.reply_animation( - data, - caption=f"**{user_name[:25]}** is back online and was away for {seenago}\n\n**Reason:** {reasonafk}\n\n", - ) - if afktype == "photo": - if str(reasonafk) == "None": - send = await message.reply_photo( - photo=f"downloads/{userid}.jpg", - caption=f"**{user_name[:25]}** is back online and was away for {seenago}\n\n", - ) - else: - send = await message.reply_photo( - photo=f"downloads/{userid}.jpg", - caption=f"**{user_name[:25]}** is back online and was away for {seenago}\n\n**Reason:** {reasonafk}\n\n", - ) - except: - msg += f"**{user_name[:25]}** is back online.\n\n" - - # Replied to a User which is AFK - if message.reply_to_message: - try: - replied_first_name = message.reply_to_message.from_user.first_name - replied_user_id = message.reply_to_message.from_user.id - verifier, reasondb = await is_afk(replied_user_id) - if verifier: - try: - afktype = reasondb["type"] - timeafk = reasondb["time"] - data = reasondb["data"] - reasonafk = reasondb["reason"] - seenago = get_readable_time2((int(time.time() - timeafk))) - if afktype == "text": - msg += f"**{replied_first_name[:25]}** is AFK since {seenago} ago.\n\n" - if afktype == "text_reason": - msg += f"**{replied_first_name[:25]}** is AFK since {seenago} ago.\n\n**Reason:** {reasonafk}\n\n" - if afktype == "animation": - if str(reasonafk) == "None": - send = await message.reply_animation( - data, - caption=f"**{replied_first_name[:25]}** is AFK since {seenago} ago.\n\n", - ) - else: - send = await message.reply_animation( - data, - caption=f"**{replied_first_name[:25]}** is AFK since {seenago} ago.\n\n**Reason:** {reasonafk}\n\n", - ) - if afktype == "photo": - if str(reasonafk) == "None": - send = await message.reply_photo( - photo=f"downloads/{replied_user_id}.jpg", - caption=f"**{replied_first_name[:25]}** is AFK since {seenago} ago.\n\n", - ) - else: - send = await message.reply_photo( - photo=f"downloads/{replied_user_id}.jpg", - caption=f"**{replied_first_name[:25]}** is AFK since {seenago} ago.\n\n**Reason:** {reasonafk}\n\n", - ) - except Exception: - msg += f"**{replied_first_name}** is AFK\n\n" - except: - pass - - # If username or mentioned user is AFK - if message.entities: - entity = message.entities - j = 0 - for x in range(len(entity)): - if (entity[j].type) == enums.MessageEntityType.MENTION: - found = re.findall("@([_0-9a-zA-Z]+)", message.text) - try: - get_user = found[j] - user = await app.get_users(get_user) - if user.id == replied_user_id: - j += 1 - continue - except: - j += 1 - continue - verifier, reasondb = await is_afk(user.id) - if verifier: - try: - afktype = reasondb["type"] - timeafk = reasondb["time"] - data = reasondb["data"] - reasonafk = reasondb["reason"] - seenago = get_readable_time2((int(time.time() - timeafk))) - if afktype == "text": - msg += f"**{user.first_name[:25]}** is AFK since {seenago} ago.\n\n" - if afktype == "text_reason": - msg += f"**{user.first_name[:25]}** is AFK since {seenago} ago.\n\n**Reason:** {reasonafk}\n\n" - if afktype == "animation": - if str(reasonafk) == "None": - send = await message.reply_animation( - data, - caption=f"**{user.first_name[:25]}** is AFK since {seenago} ago.\n\n", - ) - else: - send = await message.reply_animation( - data, - caption=f"**{user.first_name[:25]}** is AFK since {seenago} ago.\n\n**Reason**: {reasonafk}\n\n", - ) - if afktype == "photo": - if str(reasonafk) == "None": - send = await message.reply_photo( - photo=f"downloads/{user.id}.jpg", - caption=f"**{user.first_name[:25]}** is AFK since {seenago} ago.\n\n", - ) - else: - send = await message.reply_photo( - photo=f"downloads/{user.id}.jpg", - caption=f"**{user.first_name[:25]}** is AFK since {seenago} ago.\n\n**Reason:** {reasonafk}\n\n", - ) - except: - msg += f"**{user.first_name[:25]}** is AFK\n\n" - elif (entity[j].type) == enums.MessageEntityType.TEXT_MENTION: - try: - user_id = entity[j].user.id - if user_id == replied_user_id: - j += 1 - continue - first_name = entity[j].user.first_name - except: - j += 1 - continue - verifier, reasondb = await is_afk(user_id) - if verifier: - try: - afktype = reasondb["type"] - timeafk = reasondb["time"] - data = reasondb["data"] - reasonafk = reasondb["reason"] - seenago = get_readable_time2((int(time.time() - timeafk))) - if afktype == "text": - msg += f"**{first_name[:25]}** is AFK since {seenago} ago.\n\n" - if afktype == "text_reason": - msg += f"**{first_name[:25]}** is AFK since {seenago} ago.\n\n**Reason:** {reasonafk}\n\n" - if afktype == "animation": - if str(reasonafk) == "None": - send = await message.reply_animation( - data, - caption=f"**{first_name[:25]}** is AFK since {seenago} ago.\n\n", - ) - else: - send = await message.reply_animation( - data, - caption=f"**{first_name[:25]}** is AFK since {seenago} ago.\n\n**Reason:** {reasonafk}\n\n", - ) - if afktype == "photo": - if str(reasonafk) == "None": - send = await message.reply_photo( - photo=f"downloads/{user_id}.jpg", - caption=f"**{first_name[:25]}** is AFK since {seenago} ago.\n\n", - ) - else: - send = await message.reply_photo( - photo=f"downloads/{user_id}.jpg", - caption=f"**{first_name[:25]}** is AFK since {seenago} ago.\n\n**Reason:** {reasonafk}\n\n", - ) - except: - msg += f"**{first_name[:25]}** is AFK\n\n" - j += 1 - if msg != "": - try: - send = await message.reply_text(msg, disable_web_page_preview=True) - except: - return - try: - await put_cleanmode(message.chat.id, send.id) - except: - return diff --git a/misskaty/plugins/dev.py b/misskaty/plugins/dev.py index 7eeedd65..66f11a9c 100644 --- a/misskaty/plugins/dev.py +++ b/misskaty/plugins/dev.py @@ -17,6 +17,7 @@ from pyrogram import enums, filters from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup from misskaty import app, user, botStartTime, BOT_NAME +from misskaty.helper.localization import use_chat_lang from misskaty.helper.human_read import get_readable_file_size, get_readable_time from misskaty.core.message_utils import editPesan, hapusPesan, kirimPesan from misskaty.vars import COMMAND_HANDLER, SUDO @@ -40,7 +41,8 @@ async def edit_or_reply(msg, **kwargs): @app.on_message(filters.command(["logs"], COMMAND_HANDLER) & filters.user(SUDO)) -async def log_file(bot, message): +@use_chat_lang() +async def log_file(bot, message, strings): """Send log file""" try: await message.reply_document( @@ -50,7 +52,7 @@ async def log_file(bot, message): [ [ InlineKeyboardButton( - "❌ Close", + strings("cl_btn"), f"close#{message.from_user.id}", ) ] @@ -105,11 +107,12 @@ RAM Usage: `{virtual_memory().percent}%` @app.on_message(filters.command(["shell", "sh"], COMMAND_HANDLER) & filters.user(SUDO)) @app.on_edited_message(filters.command(["shell", "sh"], COMMAND_HANDLER) & filters.user(SUDO)) @user.on_message(filters.command(["shell", "sh"], ".") & filters.me) -async def shell(_, m): +@use_chat_lang() +async def shell(_, m, strings): cmd = m.text.split(" ", 1) if len(m.command) == 1: - return await edit_or_reply(m, text="No command to execute was given.") - msg = await editPesan(m, "Processing exec pyrogram...") if m.from_user.is_self else await kirimPesan(m, "Processing exec pyrogram...") + return await edit_or_reply(m, text=strings("no_cmd")) + msg = await editPesan(m, strings("run_exec")) if m.from_user.is_self else await kirimPesan(m, strings("run_exec")) shell = (await shell_exec(cmd[1]))[0] if len(shell) > 3000: with open("shell_output.txt", "w") as file: @@ -118,7 +121,7 @@ async def shell(_, m): await m.reply_document( document=doc, file_name=doc.name, - reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text="❌ Close", callback_data=f"close#{m.from_user.id}")]]), + reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text=strings("cl_btn"), callback_data=f"close#{m.from_user.id}")]]), ) await msg.delete() try: @@ -130,22 +133,23 @@ async def shell(_, m): m, text=shell, parse_mode=enums.ParseMode.HTML, - reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text="❌ Close", callback_data=f"close#{m.from_user.id}")]]), + reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text=strings("cl_btn"), callback_data=f"close#{m.from_user.id}")]]), ) if not m.from_user.is_self: await msg.delete() else: - await m.reply("No Reply") + await m.reply(strings("no_reply")) @app.on_message((filters.command(["ev", "run"], COMMAND_HANDLER) | filters.regex(r"app.run\(\)$")) & filters.user(SUDO)) @app.on_edited_message((filters.command(["ev", "run"]) | filters.regex(r"app.run\(\)$")) & filters.user(SUDO)) @user.on_message(filters.command(["ev", "run"], ".") & filters.me) -async def evaluation_cmd_t(_, m): +@use_chat_lang() +async def evaluation_cmd_t(_, m, strings): if (m.command and len(m.command) == 1) or m.text == "app.run()": - return await edit_or_reply(m, text="__No evaluate message!__") + return await edit_or_reply(m, text=strings("no_eval")) cmd = m.text.split(" ", 1)[1] if m.command else m.text.split("\napp.run()")[0] - status_message = await editPesan(m, "Processing eval pyrogram..") if m.from_user.is_self else await kirimPesan(m, "Processing eval pyrogram..", quote=True) + status_message = await editPesan(m, strings("run_eval")) if m.from_user.is_self else await kirimPesan(m, strings("run_eval"), quote=True) old_stderr = sys.stderr old_stdout = sys.stdout @@ -201,7 +205,7 @@ async def evaluation_cmd_t(_, m): elif stdout: evaluation = stdout else: - evaluation = "Success" + evaluation = strings("success") final_output = f"**EVAL**:\n`{cmd}`\n\n**OUTPUT**:\n`{evaluation.strip()}`\n" @@ -213,7 +217,7 @@ async def evaluation_cmd_t(_, m): caption=f"{cmd[1][: 4096 // 4 - 1]}", disable_notification=True, thumb="assets/thumb.jpg", - reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text="❌ Close", callback_data=f"close#{m.from_user.id}")]]), + reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text=strings("cl_btn"), callback_data=f"close#{m.from_user.id}")]]), ) os.remove("MissKatyEval.txt") await status_message.delete() @@ -222,7 +226,7 @@ async def evaluation_cmd_t(_, m): m, text=final_output, parse_mode=enums.ParseMode.MARKDOWN, - reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text="❌ Close", callback_data=f"close#{m.from_user.id}")]]), + reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text=strings("cl_btn"), callback_data=f"close#{m.from_user.id}")]]), ) if not m.from_user.is_self: await status_message.delete() @@ -230,15 +234,16 @@ async def evaluation_cmd_t(_, m): # Update and restart bot @app.on_message(filters.command(["update"], COMMAND_HANDLER) & filters.user(SUDO)) -async def update_restart(_, message): +@use_chat_lang() +async def update_restart(_, message, strings): try: out = (await shell_exec("git pull"))[0] if "Already up to date." in str(out): - return await message.reply_text("Its already up-to date!") + return await message.reply_text(strings("already_up")) await message.reply_text(f"{out}") except Exception as e: return await message.reply_text(str(e)) - msg = await message.reply_text("Updated with default branch, restarting now.") + msg = await message.reply_text(strings("up_and_rest")) with open("restart.pickle", "wb") as status: pickle.dump([message.chat.id, msg.id], status) os.execvp(sys.executable, [sys.executable, "-m", "misskaty"]) diff --git a/misskaty/plugins/fun.py b/misskaty/plugins/fun.py index d4c74e95..7ca7ff24 100644 --- a/misskaty/plugins/fun.py +++ b/misskaty/plugins/fun.py @@ -159,7 +159,6 @@ async def memify(client, message): else: await message.reply("Gunakan command /mmf dengan reply ke sticker, pisahkan dengan ; untuk membuat posisi text dibawah.") - @app.on_message(filters.command(["dice"], COMMAND_HANDLER)) @use_chat_lang() async def dice(c, m, strings): diff --git a/misskaty/plugins/genss.py b/misskaty/plugins/genss.py index 2b447424..644d77b0 100644 --- a/misskaty/plugins/genss.py +++ b/misskaty/plugins/genss.py @@ -15,10 +15,11 @@ from pyrogram import enums, filters from pyrogram.errors import FloodWait from pyrogram.types import InlineKeyboardMarkup -from misskaty import BOT_USERNAME, app +from misskaty import app from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.message_utils import * from misskaty.helper import gen_ik_buttons, get_duration, is_url, progress_for_pyrogram, screenshot_flink, take_ss +from misskaty.helper.localization import use_chat_lang from misskaty.vars import COMMAND_HANDLER LOGGER = getLogger(__name__) @@ -32,40 +33,41 @@ __HELP__ = """" @app.on_message(filters.command(["genss"], COMMAND_HANDLER)) @ratelimiter -async def genss(client, m): +@use_chat_lang() +async def genss(c, m, strings): if not m.from_user: return replied = m.reply_to_message if len(m.command) == 2 and is_url(m.command[1]): - snt = await kirimPesan(m, "Give me some time to process your request!! 😴", quote=True) + snt = await kirimPesan(m, strings("wait_msg"), quote=True) duration = await get_duration(m.command[1]) if isinstance(duration, str): - return await editPesan(snt, "😟 Sorry! I cannot open the file.") + return await editPesan(snt, strings("fail_open")) btns = gen_ik_buttons() - await editPesan(snt, f"Now choose how many result for screenshot? πŸ₯³.\n\nTotal duration: `{datetime.timedelta(seconds=duration)}` (`{duration}s`)", reply_markup=InlineKeyboardMarkup(btns)) + await editPesan(snt, strings("choose_no_ss").format(td=datetime.timedelta(seconds=duration), dur=duration), reply_markup=InlineKeyboardMarkup(btns)) elif replied and replied.media: vid = [replied.video, replied.document] media = next((v for v in vid if v is not None), None) if media is None: - return await kirimPesan(m, "Reply to a Telegram Video or document as video to generate screenshoot!", quote=True) - process = await kirimPesan(m, "Processing, please wait..", quote=True) + return await kirimPesan(m, strings("no_reply"), quote=True) + process = await kirimPesan(m, strings("wait_dl"), quote=True) if media.file_size > 2097152000: - return await editPesan(process, "Sorry, download limited to 2GB to reduce flood. You can convert your files to link.") + return await editPesan(process, strings("limit_dl")) c_time = time.time() dl = await replied.download( file_name="/downloads/", progress=progress_for_pyrogram, - progress_args=("Trying to download, please wait..", process, c_time), + progress_args=(strings("dl_progress"), process, c_time), ) the_real_download_location = os.path.join("/downloads/", os.path.basename(dl)) if the_real_download_location is not None: try: - await editPesan(process, f"File video berhasil didownload dengan path {the_real_download_location}.") + await editPesan(process, strings("success_dl_msg")) await sleep(2) images = await take_ss(the_real_download_location) - await editPesan(process, "Mencoba mengupload, hasil generate screenshot..") - await client.send_chat_action(chat_id=m.chat.id, action=enums.ChatAction.UPLOAD_PHOTO) + await editPesan(process, strings("up_progress")) + await c.send_chat_action(chat_id=m.chat.id, action=enums.ChatAction.UPLOAD_PHOTO) try: await gather( @@ -84,7 +86,7 @@ async def genss(client, m): ) await kirimPesan( m, - f"β˜‘οΈ Uploaded [1] screenshoot.\n\n{m.from_user.first_name} ({m.from_user.id})\n#️⃣ #ssgen #id{m.from_user.id}\n\nSS Generate by @{BOT_USERNAME}", + strings("up_msg").format(namma=m.from_user.mention, id=m.from_user.id, bot_uname=c.me.username), reply_to_message_id=m.id, ) await process.delete() @@ -94,14 +96,14 @@ async def genss(client, m): except: pass except Exception as exc: - await kirimPesan(m, f"Gagal generate screenshot.\n\n{exc}") + await kirimPesan(m, strings("err_ssgen").format(exc=exc)) try: os.remove(images) os.remove(the_real_download_location) except: pass else: - await kirimPesan(m, "Reply to a Telegram media to get screenshots from media..") + await kirimPesan(m, strings("no_reply")) @app.on_callback_query(filters.regex(r"^scht")) diff --git a/misskaty/plugins/karma.py b/misskaty/plugins/karma.py index 939405fb..971d826b 100644 --- a/misskaty/plugins/karma.py +++ b/misskaty/plugins/karma.py @@ -27,18 +27,16 @@ Give reputation to other people in group. karma_positive_group = 3 karma_negative_group = 4 -regex_upvote = r"^(\+|\+\+|\+1|thx|tnx|ty|thank you|thanx|thanks|pro|cool|good|makasih|πŸ‘|\+\+ .+)$" -regex_downvote = r"^(-|--|-1|πŸ‘Ž|-- .+)$" +regex_upvote = r"^(\+|\+\+|\+1|thx|tnx|ty|tq|thank you|thanx|thanks|pro|cool|good|agree|makasih|πŸ‘|\+\+ .+)$" +regex_downvote = r"^(-|--|-1|not cool|disagree|worst|bad|πŸ‘Ž|-- .+)$" n = "\n" w = " " bold = lambda x: f"**{x}:** " bold_ul = lambda x: f"**--{x}:**-- " - mono = lambda x: f"`{x}`{n}" - def section( title: str, body: dict, @@ -48,18 +46,32 @@ def section( text = (bold_ul(title) + n) if underline else bold(title) + n for key, value in body.items(): - text += indent * w + bold(key) + ((value[0] + n) if isinstance(value, list) else mono(value)) + text += ( + indent * w + + bold(key) + + ((value[0] + n) if isinstance(value, list) else mono(value)) + ) return text - async def get_user_id_and_usernames(client) -> dict: with client.storage.lock, client.storage.conn: - users = client.storage.conn.execute('SELECT * FROM peers WHERE type in ("user", "bot") AND username NOT null').fetchall() - return {user[0]: user[3] for user in users} + users = client.storage.conn.execute( + 'SELECT * FROM peers WHERE type in ("user", "bot") AND username NOT null' + ).fetchall() + users_ = {} + for user in users: + users_[user[0]] = user[3] + return users_ @app.on_message( - filters.text & filters.group & filters.incoming & filters.reply & filters.regex(regex_upvote, re.IGNORECASE) & ~filters.via_bot & ~filters.bot, + filters.text + & filters.group + & filters.incoming + & filters.reply + & filters.regex(regex_upvote, re.IGNORECASE) + & ~filters.via_bot + & ~filters.bot, group=karma_positive_group, ) @capture_err @@ -79,15 +91,25 @@ async def upvote(_, message): if current_karma: current_karma = current_karma["karma"] karma = current_karma + 1 + new_karma = {"karma": karma} + await update_karma(chat_id, await int_to_alpha(user_id), new_karma) else: karma = 1 - new_karma = {"karma": karma} - await update_karma(chat_id, await int_to_alpha(user_id), new_karma) - await message.reply_text(f"Incremented Karma of {user_mention} By 1 \nTotal Points: {karma}") + new_karma = {"karma": karma} + await update_karma(chat_id, await int_to_alpha(user_id), new_karma) + await message.reply_text( + f"Incremented Karma of {user_mention} By 1 \nTotal Points: {karma}" + ) @app.on_message( - filters.text & filters.group & filters.incoming & filters.reply & filters.regex(regex_downvote, re.IGNORECASE) & ~filters.via_bot & ~filters.bot, + filters.text + & filters.group + & filters.incoming + & filters.reply + & filters.regex(regex_downvote, re.IGNORECASE) + & ~filters.via_bot + & ~filters.bot, group=karma_negative_group, ) @capture_err @@ -102,22 +124,37 @@ async def downvote(_, message): return chat_id = message.chat.id + user_id = message.from_user.id + current_karma = await get_karma(chat_id, await int_to_alpha(user_id)) + if current_karma: + current_karma = current_karma["karma"] + karma = current_karma - 1 + new_karma = {"karma": karma} + await update_karma(chat_id, await int_to_alpha(user_id), new_karma) + else: + karma = 1 + new_karma = {"karma": karma} + await update_karma(chat_id, await int_to_alpha(user_id), new_karma) + user_id = message.reply_to_message.from_user.id user_mention = message.reply_to_message.from_user.mention current_karma = await get_karma(chat_id, await int_to_alpha(user_id)) if current_karma: current_karma = current_karma["karma"] karma = current_karma - 1 + new_karma = {"karma": karma} + await update_karma(chat_id, await int_to_alpha(user_id), new_karma) else: karma = 1 - new_karma = {"karma": karma} - await update_karma(chat_id, await int_to_alpha(user_id), new_karma) - await message.reply_text(f"Decremented Karma Of {user_mention} By 1 \nTotal Points: {karma}") + new_karma = {"karma": karma} + await update_karma(chat_id, await int_to_alpha(user_id), new_karma) + await message.reply_text( + f"Decremented Karma of {user_mention} By 1 \nTotal Points: {karma}" + ) @app.on_message(filters.command("karma") & filters.group) @capture_err -@ratelimiter async def command_karma(_, message): chat_id = message.chat.id if not message.reply_to_message: @@ -149,22 +186,25 @@ async def command_karma(_, message): if int(user_idd) not in list(userdb.keys()): continue username = userdb[int(user_idd)] - karma[f"@{username}"] = [f"**{str(karma_count)}**"] + karma["@" + username] = ["**" + str(karma_count) + "**"] limit += 1 await m.edit(section(msg, karma)) else: if not message.reply_to_message.from_user: - return await message.reply("Anon user hash no karma.") + return await message.reply("Anon user has no karma.") user_id = message.reply_to_message.from_user.id karma = await get_karma(chat_id, await int_to_alpha(user_id)) - karma = karma["karma"] if karma else 0 - await message.reply_text(f"**Total Points**: __{karma}__") + if karma: + karma = karma["karma"] + await message.reply_text(f"**Total Points**: __{karma}__") + else: + karma = 0 + await message.reply_text(f"**Total Points**: __{karma}__") @app.on_message(filters.command("karma_toggle") & ~filters.private) -@adminsOnly -@ratelimiter +@adminsOnly("can_change_info") async def captcha_state(_, message): usage = "**Usage:**\n/karma_toggle [ENABLE|DISABLE]" if len(message.command) != 2: @@ -174,9 +214,9 @@ async def captcha_state(_, message): state = state.lower() if state == "enable": await karma_on(chat_id) - await message.reply_text("Enabled karma system.") + await message.reply_text("Enabled Karma System for this chat.") elif state == "disable": await karma_off(chat_id) - await message.reply_text("Disabled karma system.") + await message.reply_text("Disabled Karma System for this chat.") else: - await message.reply_text(usage) + await message.reply_text(usage) \ No newline at end of file diff --git a/misskaty/plugins/mediainfo.py b/misskaty/plugins/mediainfo.py index 27525c59..d50b41d1 100644 --- a/misskaty/plugins/mediainfo.py +++ b/misskaty/plugins/mediainfo.py @@ -56,11 +56,11 @@ DETAILS file_info.message_type try: link = await mediainfo_paste(out, "MissKaty Mediainfo") - markup = InlineKeyboardMarkup([[InlineKeyboardButton(text=strings("vweb"), url=link)]]) + markup = InlineKeyboardMarkup([[InlineKeyboardButton(text=strings("viweb"), url=link)]]) except: try: link = await post_to_telegraph(False, "MissKaty MediaInfo", body_text) - markup = InlineKeyboardMarkup([[InlineKeyboardButton(text=strings("vweb"), url=link)]]) + markup = InlineKeyboardMarkup([[InlineKeyboardButton(text=strings("viweb"), url=link)]]) except: markup = None with io.BytesIO(str.encode(body_text)) as out_file: @@ -91,11 +91,11 @@ DETAILS # link = await post_to_telegraph(False, title, body_text) try: link = await mediainfo_paste(out, "MissKaty Mediainfo") - markup = InlineKeyboardMarkup([[InlineKeyboardButton(text=strings("vweb"), url=link)]]) + markup = InlineKeyboardMarkup([[InlineKeyboardButton(text=strings("viweb"), url=link)]]) except: try: link = await post_to_telegraph(False, "MissKaty MediaInfo", body_text) - markup = InlineKeyboardMarkup([[InlineKeyboardButton(text=strings("vweb"), url=link)]]) + markup = InlineKeyboardMarkup([[InlineKeyboardButton(text=strings("viweb"), url=link)]]) except: markup = None with io.BytesIO(str.encode(output)) as out_file: diff --git a/misskaty/plugins/nightmodev2.py b/misskaty/plugins/nightmodev2.py index 6c60e871..191c4698 100644 --- a/misskaty/plugins/nightmodev2.py +++ b/misskaty/plugins/nightmodev2.py @@ -7,10 +7,12 @@ from pyrogram import filters, __version__ from pyrogram.errors import ChannelInvalid, ChannelPrivate, ChatAdminRequired, ChatNotModified from pyrogram.types import ChatPermissions, InlineKeyboardButton, InlineKeyboardMarkup -from misskaty import BOT_NAME, BOT_USERNAME, app, scheduler +from database.locale_db import get_db_lang +from misskaty import BOT_NAME, app, scheduler from misskaty.core.message_utils import * from misskaty.core.decorator.ratelimiter import ratelimiter -from misskaty.core.decorator.permissions import adminsOnly +from misskaty.core.decorator.permissions import require_admin +from misskaty.helper.localization import use_chat_lang, langdict from misskaty.vars import COMMAND_HANDLER, LOG_CHANNEL, TZ __MODULE__ = "NightMode" @@ -85,46 +87,49 @@ def extract_time(time_val: str): async def un_mute_chat(chat_id: int, perm: ChatPermissions): + getlang = await get_db_lang(chat_id) try: await app.set_chat_permissions(chat_id, perm) except ChatAdminRequired: - await app.send_message(LOG_CHANNEL, f"#NIGHTMODE_FAIL\nFailed to turn off nightmode at `{chat_id}`," f"since {BOT_NAME} is not an admin in chat `{chat_id}`") + await app.send_message(LOG_CHANNEL, langdict[getlang]["nightmodev2"]["nmd_off_not_admin"].format(chat_id=chat_id, bname=BOT_NAME)) except (ChannelInvalid, ChannelPrivate): scheduler.remove_job(f"enable_nightmode_{chat_id}") scheduler.remove_job(f"disable_nightmode_{chat_id}") - await app.send_message(LOG_CHANNEL, f"#NIGHTMODE_FAIL\nFailed to turn off nightmode at `{chat_id}`," f"since {BOT_NAME} is not present in chat `{chat_id}`" " Removed group from list.") + await app.send_message(LOG_CHANNEL, langdict[getlang]["nightmodev2"]["nmd_off_not_present"].format(chat_id=chat_id, bname=BOT_NAME)) except ChatNotModified: pass except Exception as e: - await app.send_message(LOG_CHANNEL, f"#NIGHTMODE_FAIL\nFailed to turn off nightmode at `{chat_id}`\n" f"ERROR: `{e}`") + await app.send_message(LOG_CHANNEL, langdict[getlang]["nightmodev2"]["nmd_off_err"].format(chat_id=chat_id, e=e)) else: job = scheduler.get_job(f"enable_nightmode_{chat_id}") close_at = job.next_run_time - await app.send_message(chat_id, f"#NIGHTMODE_HANDLER\nπŸ“† {tglsekarang()}\n\nβ˜€οΈ Group is Opening.\nWill be closed at {close_at}", reply_markup=reply_markup) + await app.send_message(chat_id, langdict[getlang]["nightmodev2"]["nmd_off_success"].format(dt=tglsekarang(), close_at=close_at), reply_markup=reply_markup) async def mute_chat(chat_id: int): + getlang = await get_db_lang(chat_id) try: await app.set_chat_permissions(chat_id, ChatPermissions()) except ChatAdminRequired: - await app.send_message(LOG_CHANNEL, f"#NIGHTMODE_FAIL\nFailed to enable nightmode at `{chat_id}`," f"since {BOT_NAME} is not an admin in chat `{chat_id}`") + await app.send_message(LOG_CHANNEL, langdict[getlang]["nightmodev2"]["nmd_on_not_admin"].format(chat_id=chat_id, bname=BOT_NAME)) except (ChannelInvalid, ChannelPrivate): scheduler.remove_job(f"enable_nightmode_{chat_id}") scheduler.remove_job(f"disable_nightmode_{chat_id}") - await app.send_message(LOG_CHANNEL, f"#NIGHTMODE_FAIL\nFailed to enable nightmode at `{chat_id}`," f"since {BOT_NAME} is not present in chat `{chat_id}`" " Removed group from list.") + await app.send_message(LOG_CHANNEL, langdict[getlang]["nightmodev2"]["nmd_on_not_present"].format(chat_id=chat_id, bname=BOT_NAME)) except ChatNotModified: pass except Exception as e: - await app.send_message(LOG_CHANNEL, f"#NIGHTMODE_FAIL\nFailed to enable nightmode at `{chat_id}`\n" f"ERROR: `{e}`") + await app.send_message(LOG_CHANNEL, langdict[getlang]["nightmodev2"]["nmd_on_err"].format(chat_id=chat_id, e=e)) else: job = scheduler.get_job(f"disable_nightmode_{chat_id}") open_at = job.next_run_time - await app.send_message(chat_id, f"#NIGHTMODE_HANDLER\nπŸ“† {tglsekarang()}\n\nπŸŒ— Group is closing.\nWill be opened at {open_at}", reply_markup=reply_markup) + await app.send_message(chat_id, langdict[getlang]["nightmodev2"]["nmd_on_success"].format(dt=tglsekarang(), open_at=open_at), reply_markup=reply_markup) @app.on_message(filters.command("nightmode", COMMAND_HANDLER) & filters.group) -@adminsOnly("can_change_info") -async def nightmode_handler(c, msg): +@require_admin(permissions=["can_change_info"]) +@use_chat_lang() +async def nightmode_handler(c, msg, strings): chat_id = msg.chat.id if "-d" in msg.text: @@ -134,8 +139,8 @@ async def nightmode_handler(c, msg): scheduler.remove_job(job_id=f"disable_nightmode_{chat_id}") if not bool(scheduler.get_jobs()) and bool(scheduler.state): scheduler.shutdown() - return await kirimPesan(msg, "Nightmode disabled.") - return await kirimPesan(msg, "Nightmode isn't enabled in this chat.") + return await kirimPesan(msg, strings("nmd_disabled")) + return await kirimPesan(msg, strings("nmd_not_enabled")) starttime = re.findall(r"-s=(\d+:\d+)", msg.text) start = starttime[0] if starttime else "00:00" @@ -144,13 +149,13 @@ async def nightmode_handler(c, msg): try: start_timestamp = TIME_ZONE.localize(datetime.strptime((now.strftime("%m:%d:%Y - ") + start), "%m:%d:%Y - %H:%M")) except ValueError: - return await kirimPesan(msg, "Invalid time format. Use HH:MM format.") + return await kirimPesan(msg, strings("invalid_time_format")) lockdur = re.findall(r"-e=(\w+)", msg.text) lockdur = lockdur[0] if lockdur else "6h" lock_dur = extract_time(lockdur.lower()) if not lock_dur: - return await kirimPesan(msg, "Invalid time duration. Use proper format." "\nExample: 6h (for 6 hours), 10m for 10 minutes.") + return await kirimPesan(msg, strings("invalid_lockdur")) if start_timestamp < now: start_timestamp = start_timestamp + timedelta(days=1) @@ -162,13 +167,14 @@ async def nightmode_handler(c, msg): # schedule to disable nightmode scheduler.add_job(un_mute_chat, "interval", [chat_id, msg.chat.permissions], id=f"disable_nightmode_{chat_id}", days=1, next_run_time=end_time_stamp, max_instances=50, misfire_grace_time=None) except ConflictingIdError: - return await kirimPesan(msg, "Already a schedule is running in this chat. Disable it using `-d` flag.") - await kirimPesan(msg, "Successfully enabled nightmode in this chat.\n" f'Group will be locked at {start_timestamp.strftime("%H:%M:%S")}' f" and will be opened after {lockdur} everyday.") + return await kirimPesan(msg, strings("schedule_already_on")) + await kirimPesan(msg, strings("nmd_enable_success").format(st=start_timestamp.strftime("%H:%M:%S"), lockdur=lockdur)) if not bool(scheduler.state): scheduler.start() @app.on_callback_query(filters.regex(r"^nightmd$")) @ratelimiter -async def callbackanightmd(c, q): - await q.answer(f"πŸ”– Hai, Aku {BOT_USERNAME} dibuat menggunakan Framework Pyrogram v{__version__} dan Python 3.10.\n\nMau buat bot seperti ini? Yuuk belajar di @botindonesia\nOwner: @YasirArisM", show_alert=True) +@use_chat_lang() +async def callbackanightmd(c, q, strings): + await q.answer(strings("nmd_cb").format(bname=c.me.first_name, ver=__version__), show_alert=True) diff --git a/misskaty/plugins/ocr.py b/misskaty/plugins/ocr.py index d770bab2..44e6e960 100644 --- a/misskaty/plugins/ocr.py +++ b/misskaty/plugins/ocr.py @@ -20,7 +20,7 @@ from misskaty.helper.http import http from misskaty.vars import COMMAND_HANDLER __MODULE__ = "OCR" -__HELP__ = "/ocr [reply to photo] - Read Text From Image" +__HELP__ = f"/ocr [reply to photo] - Read Text From Image" @app.on_message(filters.command(["ocr"], COMMAND_HANDLER)) diff --git a/misskaty/plugins/start_help.py b/misskaty/plugins/start_help.py new file mode 100644 index 00000000..6738760a --- /dev/null +++ b/misskaty/plugins/start_help.py @@ -0,0 +1,292 @@ +""" + * @author yasir + * @date 2022-12-01 09:12:27 + * @lastModified 2023-03-30 09:33:16 + * @projectName MissKatyPyro + * Copyright @YasirPedia All rights reserved + """ +import re +from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup +from database.users_chats_db import db +from pyrogram import filters +from misskaty import app, BOT_USERNAME, HELPABLE, BOT_NAME +from misskaty.vars import COMMAND_HANDLER, LOG_CHANNEL +from misskaty.core.message_utils import * +from misskaty.core.decorator.ratelimiter import ratelimiter +from misskaty.helper import bot_sys_stats, paginate_modules +from misskaty.helper.localization import use_chat_lang + + +home_keyboard_pm = InlineKeyboardMarkup( + [ + [ + InlineKeyboardButton(text="Commands ❓", callback_data="bot_commands"), + InlineKeyboardButton( + text="Source Code πŸ› ", + url="https://github.com/yasirarism/MissKatyPyro", + ), + ], + [ + InlineKeyboardButton( + text="System Stats πŸ–₯", + callback_data="stats_callback", + ), + InlineKeyboardButton(text="Dev πŸ‘¨", url="https://t.me/YasirArisM"), + ], + [ + InlineKeyboardButton( + text="Add Me To Your Group πŸŽ‰", + url=f"http://t.me/{BOT_USERNAME}?startgroup=new", + ) + ], + ] +) + +home_text_pm = f"Hey there! My name is {BOT_NAME}. I have many useful features for you, feel free to add me to your group.\n\nIf you want give coffee to my owner you can send /donate command for more info." + +keyboard = InlineKeyboardMarkup( + [ + [ + InlineKeyboardButton(text="Help ❓", url=f"t.me/{BOT_USERNAME}?start=help"), + InlineKeyboardButton( + text="Source Code οΏ½", + url="https://github.com/yasirarism/MissKatyPyro", + ), + ], + [ + InlineKeyboardButton( + text="System Stats πŸ’»", + callback_data="stats_callback", + ), + InlineKeyboardButton(text="Dev πŸ‘¨", url="https://t.me/YasirArisM"), + ], + ] +) + + +@app.on_message(filters.command("start", COMMAND_HANDLER)) +@use_chat_lang() +async def start(_, message, strings): + if message.chat.type.value != "private": + if not await db.get_chat(message.chat.id): + total = await app.get_chat_members_count(message.chat.id) + await app.send_message( + LOG_CHANNEL, + strings("newgroup_log").format(jdl=message.chat.title, id=message.chat.id, c=total), + ) + + await db.add_chat(message.chat.id, message.chat.title) + nama = ( + message.from_user.mention + if message.from_user + else message.sender_chat.title + ) + return await message.reply_photo( + photo="https://telegra.ph/file/90e9a448bc2f8b055b762.jpg", + caption=strings("start_msg").format(kamuh=nama), + reply_markup=keyboard, + ) + if not await db.is_user_exist(message.from_user.id): + await db.add_user(message.from_user.id, message.from_user.first_name) + await app.send_message( + LOG_CHANNEL, + strings("newuser_log").format(id=message.from_user.id, nm=message.from_user.mention), + ) + + if len(message.text.split()) > 1: + name = (message.text.split(None, 1)[1]).lower() + if "_" in name: + module = name.split("_", 1)[1] + text = ( + strings("help_name").format(mod=HELPABLE[module].__MODULE__) + + HELPABLE[module].__HELP__ + ) + await kirimPesan(message, text, disable_web_page_preview=True) + elif name == "help": + text, keyb = await help_parser(message.from_user.first_name) + await kirimPesan( + message, + text, + reply_markup=keyb, + ) + else: + await message.reply_photo( + photo="https://telegra.ph/file/90e9a448bc2f8b055b762.jpg", + caption=home_text_pm, + reply_markup=home_keyboard_pm, + ) + + +@app.on_callback_query(filters.regex("bot_commands")) +@ratelimiter +async def commands_callbacc(_, CallbackQuery): + text, keyboard = await help_parser(CallbackQuery.from_user.mention) + await app.send_message( + CallbackQuery.message.chat.id, + text=text, + reply_markup=keyboard, + ) + await hapusPesan(CallbackQuery.message) + + +@app.on_callback_query(filters.regex("stats_callback")) +@ratelimiter +async def stats_callbacc(_, CallbackQuery): + text = await bot_sys_stats() + await app.answer_callback_query(CallbackQuery.id, text, show_alert=True) + + +@app.on_message(filters.command("help", COMMAND_HANDLER)) +@ratelimiter +@use_chat_lang() +async def help_command(_, message, strings): + if not message.from_user: return + if message.chat.type.value != "private": + if not await db.get_chat(message.chat.id): + total = await app.get_chat_members_count(message.chat.id) + await app.send_message( + LOG_CHANNEL, + strings("newgroup_log").format(jdl=message.chat.title, id=message.chat.id, c=total), + ) + + await db.add_chat(message.chat.id, message.chat.title) + if len(message.command) >= 2: + name = (message.text.split(None, 1)[1]).replace(" ", "_").lower() + if str(name) in HELPABLE: + key = InlineKeyboardMarkup( + [ + [ + InlineKeyboardButton( + text=strings("click_me"), + url=f"t.me/{BOT_USERNAME}?start=help_{name}", + ) + ], + ] + ) + await kirimPesan( + message, + strings("click_btn"), + reply_markup=key, + ) + else: + await kirimPesan(message, strings("pm_detail"), reply_markup=keyboard) + else: + await kirimPesan(message, strings("pm_detail"), reply_markup=keyboard) + else: + if not await db.is_user_exist(message.from_user.id): + await db.add_user(message.from_user.id, message.from_user.first_name) + await app.send_message( + LOG_CHANNEL, + strings("newuser_log").format(id=message.from_user.id, nm=message.from_user.mention), + ) + + if len(message.command) >= 2: + name = (message.text.split(None, 1)[1]).replace(" ", "_").lower() + if str(name) in HELPABLE: + text = ( + strings("help_name").format(mod=HELPABLE[name].__MODULE__) + + HELPABLE[name].__HELP__ + ) + await kirimPesan(message, text, disable_web_page_preview=True) + else: + text, help_keyboard = await help_parser(message.from_user.first_name) + await kirimPesan( + message, + text, + reply_markup=help_keyboard, + disable_web_page_preview=True, + ) + else: + text, help_keyboard = await help_parser(message.from_user.first_name) + await kirimPesan( + message, text, reply_markup=help_keyboard, disable_web_page_preview=True + ) + + +async def help_parser(name, keyboard=None): + if not keyboard: + keyboard = InlineKeyboardMarkup(paginate_modules(0, HELPABLE, "help")) + return ( + """Hello {first_name}, My name is {bot_name}. +I'm a bot with some useful features. You can change language bot using /setlang command, but it's still in beta stage. +You can choose an option below, by clicking a button. + +If you want give coffee to my owner you can send /donate command for more info. +""".format( + first_name=name, + bot_name="MissKaty", + ), + keyboard, + ) + + +@app.on_callback_query(filters.regex(r"help_(.*?)")) +@ratelimiter +@use_chat_lang() +async def help_button(client, query, strings): + home_match = re.match(r"help_home\((.+?)\)", query.data) + mod_match = re.match(r"help_module\((.+?)\)", query.data) + prev_match = re.match(r"help_prev\((.+?)\)", query.data) + next_match = re.match(r"help_next\((.+?)\)", query.data) + back_match = re.match(r"help_back", query.data) + create_match = re.match(r"help_create", query.data) + top_text = strings("help_txt").format(kamuh=query.from_user.first_name, bot=client.me.first_name) + if mod_match: + module = mod_match[1].replace(" ", "_") + text = strings("help_name").format(mod=HELPABLE[module].__MODULE__) + HELPABLE[module].__HELP__ + + await editPesan( + query.message, + text=text, + reply_markup=InlineKeyboardMarkup( + [[InlineKeyboardButton(strings("back_btn"), callback_data="help_back")]] + ), + disable_web_page_preview=True, + ) + elif home_match: + await app.send_message( + query.from_user.id, + text=home_text_pm, + reply_markup=home_keyboard_pm, + ) + await hapusPesan(query.message) + elif prev_match: + curr_page = int(prev_match[1]) + await editPesan( + query.message, + text=top_text, + reply_markup=InlineKeyboardMarkup( + paginate_modules(curr_page - 1, HELPABLE, "help") + ), + disable_web_page_preview=True, + ) + + elif next_match: + next_page = int(next_match[1]) + await editPesan( + query.message, + text=top_text, + reply_markup=InlineKeyboardMarkup( + paginate_modules(next_page + 1, HELPABLE, "help") + ), + disable_web_page_preview=True, + ) + + elif back_match: + await editPesan( + query.message, + text=top_text, + reply_markup=InlineKeyboardMarkup(paginate_modules(0, HELPABLE, "help")), + disable_web_page_preview=True, + ) + + elif create_match: + text, keyboard = await help_parser(query) + await editPesan( + query.message, + text=text, + reply_markup=keyboard, + disable_web_page_preview=True, + ) + + return await client.answer_callback_query(query.id) \ No newline at end of file diff --git a/misskaty/plugins/web_scraper.py b/misskaty/plugins/web_scraper.py index 89319c4d..656a4497 100644 --- a/misskaty/plugins/web_scraper.py +++ b/misskaty/plugins/web_scraper.py @@ -11,6 +11,7 @@ from pykeyboard import InlineKeyboard, InlineButton from pyrogram import filters from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.helper.http import http +from misskaty.helper.localization import use_chat_lang from misskaty.helper.kuso_utils import Kusonime from misskaty import app from misskaty.vars import COMMAND_HANDLER @@ -47,11 +48,11 @@ def split_arr(arr, size: 5): # Terbit21 GetData -async def getDataTerbit21(msg, kueri, CurrentPage): +async def getDataTerbit21(msg, kueri, CurrentPage, strings): if not SCRAP_DICT.get(msg.id): terbitjson = (await http.get(f"https://yasirapi.eu.org/terbit21?q={kueri}")).json() if kueri else (await http.get("https://yasirapi.eu.org/terbit21")).json() if not terbitjson.get("result"): - await editPesan(msg, "Sorry, could not find any results!") + await editPesan(msg, strings("no_result")) return None, None SCRAP_DICT[msg.id] = [split_arr(terbitjson["result"], 6), kueri] try: @@ -59,25 +60,25 @@ async def getDataTerbit21(msg, kueri, CurrentPage): PageLen = len(SCRAP_DICT[msg.id][0]) if kueri: - TerbitRes = f"#Terbit21 Results For: {kueri}\n\n" + TerbitRes = strings("header_with_query").format(web="Terbit21", kueri=kueri) else: - TerbitRes = "#Terbit21 Latest:\nπŸŒ€ Use /terbit21 [title] to start search with title.\n\n" + TerbitRes = strings("header_no_query").format(web="Terbit21", cmd="terbit21") for c, i in enumerate(SCRAP_DICT[msg.id][0][index], start=1): - TerbitRes += f"{c}. {i['judul']}\nCategory: {i['kategori']}\n" - TerbitRes += "\n" if re.search(r"Complete|Ongoing", i["kategori"]) else f"πŸ’  Download\n\n" + TerbitRes += f"{c}. {i['judul']}\n{strings('cat_text')}: {i['kategori']}\n" + TerbitRes += "\n" if re.search(r"Complete|Ongoing", i["kategori"]) else f"{strings('dl_text')}\n\n" TerbitRes = "".join(i for i in TerbitRes if i not in "[]") return TerbitRes, PageLen except (IndexError, KeyError): - await editPesan(msg, "Sorry, could not find any results!") + await editPesan(msg, strings("no_result")) return None, None # LK21 GetData -async def getDatalk21(msg, kueri, CurrentPage): +async def getDatalk21(msg, kueri, CurrentPage, strings): if not SCRAP_DICT.get(msg.id): lk21json = (await http.get(f"https://yasirapi.eu.org/lk21?q={kueri}")).json() if kueri else (await http.get("https://yasirapi.eu.org/lk21")).json() if not lk21json.get("result"): - await editPesan(msg, "Sorry could not find any matching results!") + await editPesan(msg, strings("no_result")) return None, None SCRAP_DICT[msg.id] = [split_arr(lk21json["result"], 6), kueri] try: @@ -85,46 +86,46 @@ async def getDatalk21(msg, kueri, CurrentPage): PageLen = len(SCRAP_DICT[msg.id][0]) if kueri: - lkResult = f"#Layarkaca21 Results For: {kueri}\n\n" + lkResult = strings("header_with_query").format(web="Layarkaca21", kueri=kueri) else: - lkResult = "#Layarkaca21 Latest:\nπŸŒ€ Use /lk21 [title] to start search with title.\n\n" + lkResult = strings("header_no_query").format(web="Layarkaca21", cmd="lk21") for c, i in enumerate(SCRAP_DICT[msg.id][0][index], start=1): - lkResult += f"{c}. {i['judul']}\nCategory: {i['kategori']}\n" - lkResult += "\n" if re.search(r"Complete|Ongoing", i["kategori"]) else f"πŸ’  Download\n\n" + lkResult += f"{c}. {i['judul']}\n{strings('cat_text')}: {i['kategori']}\n" + lkResult += "\n" if re.search(r"Complete|Ongoing", i["kategori"]) else f"{strings('dl_text')}\n\n" lkResult = "".join(i for i in lkResult if i not in "[]") return lkResult, PageLen except (IndexError, KeyError): - await editPesan(msg, "Sorry could not find any matching results!") + await editPesan(msg, strings("no_result")) return None, None # Pahe GetData -async def getDataPahe(msg, kueri, CurrentPage): +async def getDataPahe(msg, kueri, CurrentPage, strings): if not SCRAP_DICT.get(msg.id): pahejson = (await http.get(f"https://yasirapi.eu.org/pahe?q={kueri}")).json() if not pahejson.get("result"): - await editPesan(msg, "Sorry could not find any matching results!") + await editPesan(msg, strings("no_result")) return None, None SCRAP_DICT[msg.id] = [split_arr(pahejson["result"], 6), kueri] try: index = int(CurrentPage - 1) PageLen = len(SCRAP_DICT[msg.id][0]) - paheResult = f"#Pahe Results For: {kueri}\n\n" if kueri else f"#Pahe Latest:\nπŸŒ€ Use /pahe [title] to start search with title.\n\n" + paheResult = strings("header_with_query").format(web="Pahe", kueri=kueri) if kueri else strings("header_no_query").format(web="Pahe", cmd="pahe") for c, i in enumerate(SCRAP_DICT[msg.id][0][index], start=1): paheResult += f"{c}. {i['judul']}\n\n" paheResult = "".join(i for i in paheResult if i not in "[]") return paheResult, PageLen except (IndexError, KeyError): - await editPesan(msg, "Sorry could not find any matching results!") + await editPesan(msg, strings("no_result")) return None, None # Kusonime GetData -async def getDataKuso(msg, kueri, CurrentPage, user): +async def getDataKuso(msg, kueri, CurrentPage, user, strings): if not SCRAP_DICT.get(msg.id): kusodata = [] - data = await http.get(f"https://kusonime.com/?s={kueri}", headers=headers) + data = await http.get(f"https://kusonime.com/?s={kueri}", headers=headers, follow_redirects=True) res = BeautifulSoup(data, "lxml").find_all("h2", {"class": "episodeye"}) for i in res: ress = i.find_all("a")[0] @@ -132,7 +133,7 @@ async def getDataKuso(msg, kueri, CurrentPage, user): link = ress["href"] kusodata.append({"title": title, "link": link}) if not kusodata: - await editPesan(msg, "Sorry could not find any results!") + await editPesan(msg, strings("no_result")) return None, 0, None, None SCRAP_DICT[msg.id] = [split_arr(kusodata, 10), kueri] try: @@ -141,7 +142,7 @@ async def getDataKuso(msg, kueri, CurrentPage, user): extractbtn1 = [] extractbtn2 = [] - kusoResult = f"#Kusonime Latest Post\n\n" if kueri == "" else f"#Kusonime Results For: {kueri}\n\n" + kusoResult = strings("header_no_query").format(web="Kusonime", cmd="kusonime") if kueri == "" else strings("header_with_query").format(web="Kusonime", kueri=kueri) for c, i in enumerate(SCRAP_DICT[msg.id][0][index], start=1): kusoResult += f"{c}. {i['title']}\n{i['link']}\n\n" if c < 6: @@ -151,15 +152,15 @@ async def getDataKuso(msg, kueri, CurrentPage, user): kusoResult = "".join(i for i in kusoResult if i not in "[]") return kusoResult, PageLen, extractbtn1, extractbtn2 except (IndexError, KeyError): - await editPesan(msg, "Sorry could not find any matching results!") + await editPesan(msg, strings("no_result")) return None, 0, None, None # Movieku GetData -async def getDataMovieku(msg, kueri, CurrentPage): +async def getDataMovieku(msg, kueri, CurrentPage, strings): if not SCRAP_DICT.get(msg.id): moviekudata = [] - data = await http.get(f"https://107.152.37.223/?s={kueri}", headers=headers) + data = await http.get(f"https://107.152.37.223/?s={kueri}", headers=headers, follow_redirects=True) r = BeautifulSoup(data, "lxml") res = r.find_all(class_="bx") for i in res: @@ -169,35 +170,35 @@ async def getDataMovieku(msg, kueri, CurrentPage): typee = typ.strip() if typ.strip() != "" else "~" moviekudata.append({"judul": judul, "link": link, "type": typee}) if not moviekudata: - await editPesan(msg, "Sorry could not find any results!") + await editPesan(msg, strings("no_result")) return None, None SCRAP_DICT[msg.id] = [split_arr(moviekudata, 6), kueri] try: index = int(CurrentPage - 1) PageLen = len(SCRAP_DICT[msg.id][0]) - moviekuResult = f"#Movieku Latest:\nπŸŒ€ Use /movieku [title] to start search with title.\n\n" if kueri == "" else f"#Movieku Results For: {kueri}\n\n" + moviekuResult = strings("header_no_query").format(web="Movieku", cmd="movieku") if kueri == "" else strings("header_with_query").format(web="Movieku", kueri=kueri) for c, i in enumerate(SCRAP_DICT[msg.id][0][index], start=1): - moviekuResult += f"{c}. {i['judul']}\nQuality/Status: {i['type']}\nExtract: /movieku_scrap {i['link']}\n\n" + moviekuResult += f"{c}. {i['judul']}\n{strings('quality')}/Status: {i['type']}\nExtract: /movieku_scrap {i['link']}\n\n" moviekuResult = "".join(i for i in moviekuResult if i not in "[]") return moviekuResult, PageLen except (IndexError, KeyError): - await editPesan(msg, "Sorry could not find any matching results!") + await editPesan(msg, strings("no_result")) return None, None # Savefilm21 GetData -async def getDataSavefilm21(msg, kueri, CurrentPage, user): +async def getDataSavefilm21(msg, kueri, CurrentPage, user, strings): if not SCRAP_DICT.get(msg.id): sfdata = [] - data = await http.get(f"https://savefilm21.pro/?s={kueri}", headers=headers) + data = await http.get(f"https://savefilm21.pro/?s={kueri}", headers=headers, follow_redirects=True) text = BeautifulSoup(data, "lxml") entry = text.find_all(class_="entry-header") if "Tidak Ditemukan" in entry[0].text: if not kueri: - await editPesan(msg, "Sorry, could not find any result") + await editPesan(msg, strings("no_result")) else: - await editPesan(msg, f"Sorry, could not find any result for: {kueri}") + await editPesan(msg, strings("no_result_w_query").format(kueri=kueri)) return None, 0, None for i in entry: genre = i.find(class_="gmr-movie-on").text @@ -210,21 +211,21 @@ async def getDataSavefilm21(msg, kueri, CurrentPage, user): index = int(CurrentPage - 1) PageLen = len(SCRAP_DICT[msg.id][0]) extractbtn = [] - sfResult = f"#SaveFilm21 Latest:\nπŸŒ€ Use /savefilm21 [title] to start search with title.\n\n" if kueri == "" else f"#Savefilm21 Results For: {kueri}\n\n" + sfResult = strings("header_no_query").format(web="Savefilm21", cmd="savefilm21") if kueri == "" else strings("header_with_query").format(web="Savefilm21", kueri=kueri) for c, i in enumerate(SCRAP_DICT[msg.id][0][index], start=1): sfResult += f"{c}. {i['judul']}\nGenre: {i['genre']}\n\n" extractbtn.append(InlineButton(c, f"sf21extract#{CurrentPage}#{c}#{user}#{msg.id}")) sfResult = "".join(i for i in sfResult if i not in "[]") return sfResult, PageLen, extractbtn except (IndexError, KeyError): - await editPesan(msg, "Sorry could not find any matching results!") + await editPesan(msg, strings("no_result")) return None, 0, None # Lendrive GetData -async def getDataLendrive(msg, kueri, CurrentPage, user): +async def getDataLendrive(msg, kueri, CurrentPage, user, strings): if not SCRAP_DICT.get(msg.id): - data = await http.get(f"https://lendrive.web.id/?s={kueri}", headers=headers) + data = await http.get(f"https://lendrive.web.id/?s={kueri}", headers=headers, follow_redirects=True) soup = BeautifulSoup(data, "lxml") lenddata = [] for o in soup.find_all(class_="bsx"): @@ -234,7 +235,7 @@ async def getDataLendrive(msg, kueri, CurrentPage, user): kualitas = o.find(class_="typez TV").text if o.find(class_="typez TV") else o.find(class_="typez BD") lenddata.append({"judul": title, "link": link, "quality": kualitas, "status": status}) if not lenddata: - await editPesan(msg, "Sorry could not find any results!") + await editPesan(msg, strings("no_result")) return None, 0, None SCRAP_DICT[msg.id] = [split_arr(lenddata, 6), kueri] try: @@ -242,21 +243,21 @@ async def getDataLendrive(msg, kueri, CurrentPage, user): PageLen = len(SCRAP_DICT[msg.id][0]) extractbtn = [] - lenddataResult = f"#LenDrive Latest:\nπŸŒ€ Use /lendrive [title] to start search with title.\n\n" if kueri == "" else f"#LenDrive Results For: {kueri}\n\n" + lenddataResult = strings("header_no_query").format(web="Lendrive", cmd="lendrive") if kueri == "" else strings("header_with_query").format(web="Lendrive", kueri=kueri) for c, i in enumerate(SCRAP_DICT[msg.id][0][index], start=1): - lenddataResult += f"{c}. {i['judul']}\nQuality: {i['quality']}\nStatus: {i['status']}\n\n" + lenddataResult += f"{c}. {i['judul']}\n{strings('quality')}: {i['quality']}\nStatus: {i['status']}\n\n" extractbtn.append(InlineButton(c, f"lendriveextract#{CurrentPage}#{c}#{user}#{msg.id}")) lenddataResult = "".join(i for i in lenddataResult if i not in "[]") return lenddataResult, PageLen, extractbtn except (IndexError, KeyError): - await editPesan(msg, "Sorry could not find any matching results!") + await editPesan(msg, strings("no_result")) return None, 0, None # MelongMovie GetData -async def getDataMelong(msg, kueri, CurrentPage, user): +async def getDataMelong(msg, kueri, CurrentPage, user, strings): if not SCRAP_DICT.get(msg.id): - data = await http.get(f"https://melongmovie.info/?s={kueri}", headers=headers) + data = await http.get(f"https://melongmovie.info/?s={kueri}", headers=headers, follow_redirects=True) bs4 = BeautifulSoup(data, "lxml") melongdata = [] for res in bs4.select(".box"): @@ -269,7 +270,7 @@ async def getDataMelong(msg, kueri, CurrentPage, user): quality = "N/A" melongdata.append({"judul": title, "link": url, "quality": quality}) if not melongdata: - await editPesan(msg, "Sorry could not find any results!") + await editPesan(msg, strings("no_result")) return None, 0, None SCRAP_DICT[msg.id] = [split_arr(melongdata, 6), kueri] try: @@ -277,28 +278,28 @@ async def getDataMelong(msg, kueri, CurrentPage, user): PageLen = len(SCRAP_DICT[msg.id][0]) extractbtn = [] - melongResult = f"#MelongMovie Latest:\nπŸŒ€ Use /melongmovie [title] to start search with title.\n\n" if kueri == "" else f"#MelongMovie Results For: {kueri}\n\n" + melongResult = strings("header_no_query").format(web="Melongmovie", cmd="melongmovie") if kueri == "" else strings("header_with_query").format(web="Melongmovie", kueri=kueri) for c, i in enumerate(SCRAP_DICT[msg.id][0][index], start=1): - melongResult += f"{c}. {i['judul']}\nQuality: {i['quality']}\n\n" + melongResult += f"{c}. {i['judul']}\n{strings('quality')}: {i['quality']}\n\n" extractbtn.append(InlineButton(c, f"melongextract#{CurrentPage}#{c}#{user}#{msg.id}")) melongResult = "".join(i for i in melongResult if i not in "[]") return melongResult, PageLen, extractbtn except (IndexError, KeyError): - await editPesan(msg, "Sorry could not find any matching results!") + await editPesan(msg, strings("no_result")) return None, 0, None # GoMov GetData -async def getDataGomov(msg, kueri, CurrentPage, user): +async def getDataGomov(msg, kueri, CurrentPage, user, strings): if not SCRAP_DICT.get(msg.id): - gomovv = await http.get(f"https://gomov.club/?s={kueri}", headers=headers) + gomovv = await http.get(f"https://gomov.cfd/?s={kueri}", headers=headers, follow_redirects=True) text = BeautifulSoup(gomovv, "lxml") entry = text.find_all(class_="entry-header") if entry[0].text.strip() == "Nothing Found": if not kueri: - await editPesan(msg, "Sorry, i could not find anything.") + await editPesan(msg, strings("no_result")) else: - await editPesan(msg, f"Sorry, i could not find query: {kueri}") + await editPesan(msg, strings("no_result_w_query")) return None, 0, None data = [] for i in entry: @@ -313,420 +314,438 @@ async def getDataGomov(msg, kueri, CurrentPage, user): PageLen = len(SCRAP_DICT[msg.id][0]) extractbtn = [] - gomovResult = f"#Gomov Results For: {kueri}\n\n" if kueri else f"#Gomov Latest:\nπŸŒ€ Use /gomov [title] to start search with title.\n\n" + gomovResult = strings("header_with_query").format(web="GoMov", kueri=kueri) if kueri else strings("header_no_query").format(web="GoMov", cmd="gomov") for c, i in enumerate(SCRAP_DICT[msg.id][0][index], start=1): gomovResult += f"{c}. {i['judul']}\nGenre: {i['genre']}\n\n" if not re.search(r"Series", i["genre"]): extractbtn.append(InlineButton(c, f"gomovextract#{CurrentPage}#{c}#{user}#{msg.id}")) - gomovResult += "Some result will not appear in extract button because unsupported link." + gomovResult += strings("unsupport_dl_btn") gomovResult = "".join(i for i in gomovResult if i not in "[]") return gomovResult, PageLen, extractbtn except (IndexError, KeyError): - await editPesan(msg, "Sorry could not find any matching results!") + await editPesan(msg, strings("no_result")) return None, 0, None # Terbit21 CMD @app.on_message(filters.command(["terbit21"], COMMAND_HANDLER)) @ratelimiter -async def terbit21_s(client, message): +@use_chat_lang() +async def terbit21_s(client, message, strings): kueri = " ".join(message.command[1:]) if not kueri: kueri = None - pesan = await kirimPesan(message, "⏳ Please wait, scraping data from Terbit21..", quote=True) + pesan = await kirimPesan(message, strings("get_data"), quote=True) CurrentPage = 1 - terbitres, PageLen = await getDataTerbit21(pesan, kueri, CurrentPage) + terbitres, PageLen = await getDataTerbit21(pesan, kueri, CurrentPage, strings) if not terbitres: return keyboard = InlineKeyboard() keyboard.paginate(PageLen, CurrentPage, "page_terbit21#{number}" + f"#{pesan.id}#{message.from_user.id}") - keyboard.row(InlineButton("❌ Close", f"close#{message.from_user.id}")) + keyboard.row(InlineButton(strings("cl_btn"), f"close#{message.from_user.id}")) await editPesan(pesan, terbitres, reply_markup=keyboard) # LK21 CMD @app.on_message(filters.command(["lk21"], COMMAND_HANDLER)) @ratelimiter -async def lk21_s(client, message): +@use_chat_lang() +async def lk21_s(client, message, strings): message.chat.id kueri = " ".join(message.command[1:]) if not kueri: kueri = None - pesan = await kirimPesan(message, "⏳ Please wait, scraping data from LK21..", quote=True) + pesan = await kirimPesan(message, strings("get_data"), quote=True) CurrentPage = 1 - lkres, PageLen = await getDatalk21(pesan, kueri, CurrentPage) + lkres, PageLen = await getDatalk21(pesan, kueri, CurrentPage, strings) if not lkres: return keyboard = InlineKeyboard() keyboard.paginate(PageLen, CurrentPage, "page_lk21#{number}" + f"#{pesan.id}#{message.from_user.id}") - keyboard.row(InlineButton("❌ Close", f"close#{message.from_user.id}")) + keyboard.row(InlineButton(strings("cl_btn"), f"close#{message.from_user.id}")) await editPesan(pesan, lkres, disable_web_page_preview=True, reply_markup=keyboard) # Pahe CMD @app.on_message(filters.command(["pahe"], COMMAND_HANDLER)) @ratelimiter -async def pahe_s(client, message): +@use_chat_lang() +async def pahe_s(client, message, strings): message.chat.id kueri = " ".join(message.command[1:]) if not kueri: kueri = "" - pesan = await kirimPesan(message, "⏳ Please wait, scraping data from Pahe Web..", quote=True) + pesan = await kirimPesan(message, strings("get_data"), quote=True) CurrentPage = 1 - paheres, PageLen = await getDataPahe(pesan, kueri, CurrentPage) + paheres, PageLen = await getDataPahe(pesan, kueri, CurrentPage, strings) if not paheres: return keyboard = InlineKeyboard() keyboard.paginate(PageLen, CurrentPage, "page_pahe#{number}" + f"#{pesan.id}#{message.from_user.id}") - keyboard.row(InlineButton("❌ Close", f"close#{message.from_user.id}")) + keyboard.row(InlineButton(strings("cl_btn"), f"close#{message.from_user.id}")) await editPesan(pesan, paheres, disable_web_page_preview=True, reply_markup=keyboard) # Gomov CMD @app.on_message(filters.command(["gomov"], COMMAND_HANDLER)) @ratelimiter -async def gomov_s(client, message): +@use_chat_lang() +async def gomov_s(client, message, strings): kueri = " ".join(message.command[1:]) if not kueri: kueri = "" - pesan = await kirimPesan(message, "⏳ Please wait, scraping data Gomov Web..", quote=True) + pesan = await kirimPesan(message, strings("get_data"), quote=True) CurrentPage = 1 - gomovres, PageLen, btn = await getDataGomov(pesan, kueri, CurrentPage, message.from_user.id) + gomovres, PageLen, btn = await getDataGomov(pesan, kueri, CurrentPage, message.from_user.id, strings) if not gomovres: return keyboard = InlineKeyboard() keyboard.paginate(PageLen, CurrentPage, "page_gomov#{number}" + f"#{pesan.id}#{message.from_user.id}") - keyboard.row(InlineButton("πŸ‘‡ Extract Data ", "Hmmm")) + keyboard.row(InlineButton(strings("ex_data"), user_id=message.from_user.id)) keyboard.row(*btn) - keyboard.row(InlineButton("❌ Close", f"close#{message.from_user.id}")) + keyboard.row(InlineButton(strings("cl_btn"), f"close#{message.from_user.id}")) await editPesan(pesan, gomovres, disable_web_page_preview=True, reply_markup=keyboard) # MelongMovie CMD @app.on_message(filters.command(["melongmovie"], COMMAND_HANDLER)) @ratelimiter -async def melong_s(client, message): +@use_chat_lang() +async def melong_s(client, message, strings): kueri = " ".join(message.command[1:]) if not kueri: kueri = "" - pesan = await kirimPesan(message, "⏳ Please wait, scraping data from Melongmovie..", quote=True) + pesan = await kirimPesan(message, strings("get_data"), quote=True) CurrentPage = 1 - melongres, PageLen, btn = await getDataMelong(pesan, kueri, CurrentPage, message.from_user.id) + melongres, PageLen, btn = await getDataMelong(pesan, kueri, CurrentPage, message.from_user.id, strings) if not melongres: return keyboard = InlineKeyboard() keyboard.paginate(PageLen, CurrentPage, "page_melong#{number}" + f"#{pesan.id}#{message.from_user.id}") - keyboard.row(InlineButton("πŸ‘‡ Extract Data ", "Hmmm")) + keyboard.row(InlineButton(strings("ex_data"), user_id=message.from_user.id)) keyboard.row(*btn) - keyboard.row(InlineButton("❌ Close", f"close#{message.from_user.id}")) + keyboard.row(InlineButton(strings("cl_btn"), f"close#{message.from_user.id}")) await editPesan(pesan, melongres, disable_web_page_preview=True, reply_markup=keyboard) # Savefilm21 CMD @app.on_message(filters.command(["savefilm21"], COMMAND_HANDLER)) @ratelimiter -async def savefilm_s(client, message): +@use_chat_lang() +async def savefilm_s(client, message, strings): kueri = " ".join(message.command[1:]) if not kueri: kueri = "" - pesan = await kirimPesan(message, "⏳ Please wait, scraping data from Savefilm21..", quote=True) + pesan = await kirimPesan(message, strings("get_data"), quote=True) CurrentPage = 1 - savefilmres, PageLen, btn = await getDataSavefilm21(pesan, kueri, CurrentPage, message.from_user.id) + savefilmres, PageLen, btn = await getDataSavefilm21(pesan, kueri, CurrentPage, message.from_user.id, strings) if not savefilmres: return keyboard = InlineKeyboard() keyboard.paginate(PageLen, CurrentPage, "page_savefilm#{number}" + f"#{pesan.id}#{message.from_user.id}") - keyboard.row(InlineButton("πŸ‘‡ Extract Data ", "Hmmm")) + keyboard.row(InlineButton(strings("ex_data"), user_id=message.from_user.id)) keyboard.row(*btn) - keyboard.row(InlineButton("❌ Close", f"close#{message.from_user.id}")) + keyboard.row(InlineButton(strings("cl_btn"), f"close#{message.from_user.id}")) await editPesan(pesan, savefilmres, disable_web_page_preview=True, reply_markup=keyboard) # Kusonime CMD @app.on_message(filters.command(["kusonime"], COMMAND_HANDLER)) @ratelimiter -async def kusonime_s(client, message): +@use_chat_lang() +async def kusonime_s(client, message, strings): kueri = " ".join(message.command[1:]) if not kueri: kueri = "" - pesan = await kirimPesan(message, "⏳ Please wait, scraping data from Kusonime..", quote=True) + pesan = await kirimPesan(message, strings("get_data"), quote=True) CurrentPage = 1 - kusores, PageLen, btn1, btn2 = await getDataKuso(pesan, kueri, CurrentPage, message.from_user.id) + kusores, PageLen, btn1, btn2 = await getDataKuso(pesan, kueri, CurrentPage, message.from_user.id, strings) if not kusores: return keyboard = InlineKeyboard() keyboard.paginate(PageLen, CurrentPage, "page_kuso#{number}" + f"#{pesan.id}#{message.from_user.id}") - keyboard.row(InlineButton("πŸ‘‡ Extract Data ", "Hmmm")) + keyboard.row(InlineButton(strings("ex_data"), user_id=message.from_user.id)) keyboard.row(*btn1) if btn2: keyboard.row(*btn2) - keyboard.row(InlineButton("❌ Close", f"close#{message.from_user.id}")) + keyboard.row(InlineButton(strings("cl_btn"), f"close#{message.from_user.id}")) await editPesan(pesan, kusores, disable_web_page_preview=True, reply_markup=keyboard) # Lendrive CMD @app.on_message(filters.command(["lendrive"], COMMAND_HANDLER)) @ratelimiter -async def lendrive_s(client, message): +@use_chat_lang() +async def lendrive_s(client, message, strings): kueri = " ".join(message.command[1:]) if not kueri: kueri = "" - pesan = await kirimPesan(message, "⏳ Please wait, scraping data from Lendrive..", quote=True) + pesan = await kirimPesan(message, strings("get_data"), quote=True) CurrentPage = 1 - lendres, PageLen, btn = await getDataLendrive(pesan, kueri, CurrentPage, message.from_user.id) + lendres, PageLen, btn = await getDataLendrive(pesan, kueri, CurrentPage, message.from_user.id, strings) if not lendres: return keyboard = InlineKeyboard() keyboard.paginate(PageLen, CurrentPage, "page_lendrive#{number}" + f"#{pesan.id}#{message.from_user.id}") - keyboard.row(InlineButton("πŸ‘‡ Extract Data ", "Hmmm")) + keyboard.row(InlineButton(strings("ex_data"), user_id=message.from_user.id)) keyboard.row(*btn) - keyboard.row(InlineButton("❌ Close", f"close#{message.from_user.id}")) + keyboard.row(InlineButton(strings("cl_btn"), f"close#{message.from_user.id}")) await editPesan(pesan, lendres, disable_web_page_preview=True, reply_markup=keyboard) # Movieku CMD @app.on_message(filters.command(["movieku"], COMMAND_HANDLER)) @ratelimiter -async def movieku_s(client, message): +@use_chat_lang() +async def movieku_s(client, message, strings): kueri = " ".join(message.command[1:]) if not kueri: kueri = "" - pesan = await kirimPesan(message, "⏳ Please wait, scraping data from Movieku..", quote=True) + pesan = await kirimPesan(message, strings("get_data"), quote=True) CurrentPage = 1 - moviekures, PageLen = await getDataMovieku(pesan, kueri, CurrentPage) + moviekures, PageLen = await getDataMovieku(pesan, kueri, CurrentPage, strings) if not moviekures: return keyboard = InlineKeyboard() keyboard.paginate(PageLen, CurrentPage, "page_movieku#{number}" + f"#{pesan.id}#{message.from_user.id}") - keyboard.row(InlineButton("❌ Close", f"close#{message.from_user.id}")) + keyboard.row(InlineButton(strings("cl_btn"), f"close#{message.from_user.id}")) await editPesan(pesan, moviekures, disable_web_page_preview=True, reply_markup=keyboard) # Savefillm21 Page Callback @app.on_callback_query(filters.create(lambda _, __, query: "page_savefilm#" in query.data)) @ratelimiter -async def savefilmpage_callback(client, callback_query): +@use_chat_lang() +async def savefilmpage_callback(client, callback_query, strings): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): - return await callback_query.answer("Not yours..", True) + return await callback_query.answer(strings("unauth"), True) message_id = int(callback_query.data.split("#")[2]) CurrentPage = int(callback_query.data.split("#")[1]) try: kueri = SCRAP_DICT[message_id][1] except KeyError: - return await callback_query.answer("Invalid callback data, please send CMD again..") + return await callback_query.answer(strings("invalid_cb")) try: - savefilmres, PageLen, btn = await getDataSavefilm21(callback_query.message, kueri, CurrentPage, callback_query.from_user.id) + savefilmres, PageLen, btn = await getDataSavefilm21(callback_query.message, kueri, CurrentPage, callback_query.from_user.id, strings) except TypeError: return keyboard = InlineKeyboard() keyboard.paginate(PageLen, CurrentPage, "page_savefilm#{number}" + f"#{message_id}#{callback_query.from_user.id}") - keyboard.row(InlineButton("πŸ‘‡ Extract Data ", "Hmmm")) + keyboard.row(InlineButton(strings("ex_data"), user_id=callback_query.from_user.id)) keyboard.row(*btn) - keyboard.row(InlineButton("❌ Close", f"close#{callback_query.from_user.id}")) + keyboard.row(InlineButton(strings("cl_btn"), f"close#{callback_query.from_user.id}")) await editPesan(callback_query.message, savefilmres, disable_web_page_preview=True, reply_markup=keyboard) # Kuso Page Callback @app.on_callback_query(filters.create(lambda _, __, query: "page_kuso#" in query.data)) @ratelimiter -async def kusopage_callback(client, callback_query): +@use_chat_lang() +async def kusopage_callback(client, callback_query, strings): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): - return await callback_query.answer("Not yours..", True) + return await callback_query.answer(strings("unauth"), True) message_id = int(callback_query.data.split("#")[2]) CurrentPage = int(callback_query.data.split("#")[1]) try: kueri = SCRAP_DICT[message_id][1] except KeyError: - return await callback_query.answer("Invalid callback data, please send CMD again..") + return await callback_query.answer(strings("invalid_cb")) try: - kusores, PageLen, btn1, btn2 = await getDataKuso(callback_query.message, kueri, CurrentPage, callback_query.from_user.id) + kusores, PageLen, btn1, btn2 = await getDataKuso(callback_query.message, kueri, CurrentPage, callback_query.from_user.id, strings) except TypeError: return keyboard = InlineKeyboard() keyboard.paginate(PageLen, CurrentPage, "page_kuso#{number}" + f"#{message_id}#{callback_query.from_user.id}") - keyboard.row(InlineButton("πŸ‘‡ Extract Data ", "Hmmm")) + keyboard.row(InlineButton(strings("ex_data"), user_id=callback_query.from_user.id)) keyboard.row(*btn1) if btn2: keyboard.row(*btn2) - keyboard.row(InlineButton("❌ Close", f"close#{callback_query.from_user.id}")) + keyboard.row(InlineButton(strings("cl_btn"), f"close#{callback_query.from_user.id}")) await editPesan(callback_query.message, kusores, disable_web_page_preview=True, reply_markup=keyboard) # Lendrive Page Callback @app.on_callback_query(filters.create(lambda _, __, query: "page_lendrive#" in query.data)) @ratelimiter -async def moviekupage_callback(client, callback_query): +@use_chat_lang() +async def moviekupage_callback(client, callback_query, strings): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): - return await callback_query.answer("Not yours..", True) + return await callback_query.answer(strings("unauth"), True) message_id = int(callback_query.data.split("#")[2]) CurrentPage = int(callback_query.data.split("#")[1]) try: kueri = SCRAP_DICT[message_id][1] except KeyError: - return await callback_query.answer("Invalid callback data, please send CMD again..") + return await callback_query.answer(strings("invalid_cb")) try: - lendres, PageLen, btn = await getDataLendrive(callback_query.message, kueri, CurrentPage, callback_query.from_user.id) + lendres, PageLen, btn = await getDataLendrive(callback_query.message, kueri, CurrentPage, callback_query.from_user.id, strings) except TypeError: return keyboard = InlineKeyboard() keyboard.paginate(PageLen, CurrentPage, "page_lendrive#{number}" + f"#{message_id}#{callback_query.from_user.id}") - keyboard.row(InlineButton("πŸ‘‡ Extract Data ", "Hmmm")) + keyboard.row(InlineButton(strings("ex_data"), user_id=callback_query.from_user.id)) keyboard.row(*btn) - keyboard.row(InlineButton("❌ Close", f"close#{callback_query.from_user.id}")) + keyboard.row(InlineButton(strings("cl_btn"), f"close#{callback_query.from_user.id}")) await editPesan(callback_query.message, lendres, disable_web_page_preview=True, reply_markup=keyboard) # Movieku Page Callback @app.on_callback_query(filters.create(lambda _, __, query: "page_movieku#" in query.data)) @ratelimiter -async def moviekupage_callback(client, callback_query): +@use_chat_lang() +async def moviekupage_callback(client, callback_query, strings): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): - return await callback_query.answer("Not yours..", True) + return await callback_query.answer(strings("unauth"), True) message_id = int(callback_query.data.split("#")[2]) CurrentPage = int(callback_query.data.split("#")[1]) try: kueri = SCRAP_DICT[message_id][1] except KeyError: - return await callback_query.answer("Invalid callback data, please send CMD again..") + return await callback_query.answer(strings("invalid_cb")) try: - moviekures, PageLen = await getDataMovieku(callback_query.message, kueri, CurrentPage) + moviekures, PageLen = await getDataMovieku(callback_query.message, kueri, CurrentPage, strings) except TypeError: return keyboard = InlineKeyboard() keyboard.paginate(PageLen, CurrentPage, "page_movieku#{number}" + f"#{message_id}#{callback_query.from_user.id}") - keyboard.row(InlineButton("❌ Close", f"close#{callback_query.from_user.id}")) + keyboard.row(InlineButton(strings("cl_btn"), f"close#{callback_query.from_user.id}")) await editPesan(callback_query.message, moviekures, disable_web_page_preview=True, reply_markup=keyboard) # Terbit21 Page Callback @app.on_callback_query(filters.create(lambda _, __, query: "page_terbit21#" in query.data)) @ratelimiter -async def terbit21page_callback(client, callback_query): +@use_chat_lang() +async def terbit21page_callback(client, callback_query, strings): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): - return await callback_query.answer("Not yours..", True) + return await callback_query.answer(strings("unauth"), True) message_id = int(callback_query.data.split("#")[2]) CurrentPage = int(callback_query.data.split("#")[1]) try: kueri = SCRAP_DICT[message_id][1] except KeyError: - return await callback_query.answer("Invalid callback data, please send CMD again..") + return await callback_query.answer(strings("invalid_cb")) try: - terbitres, PageLen = await getDataTerbit21(callback_query.message, kueri, CurrentPage) + terbitres, PageLen = await getDataTerbit21(callback_query.message, kueri, CurrentPage, strings) except TypeError: return keyboard = InlineKeyboard() keyboard.paginate(PageLen, CurrentPage, "page_terbit21#{number}" + f"#{message_id}#{callback_query.from_user.id}") - keyboard.row(InlineButton("❌ Close", f"close#{callback_query.from_user.id}")) + keyboard.row(InlineButton(strings("cl_btn"), f"close#{callback_query.from_user.id}")) await editPesan(callback_query.message, terbitres, disable_web_page_preview=True, reply_markup=keyboard) # Page Callback Melong @app.on_callback_query(filters.create(lambda _, __, query: "page_melong#" in query.data)) @ratelimiter -async def melongpage_callback(client, callback_query): +@use_chat_lang() +async def melongpage_callback(client, callback_query, strings): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): - return await callback_query.answer("Not yours..", True) + return await callback_query.answer(strings("unauth"), True) message_id = int(callback_query.data.split("#")[2]) CurrentPage = int(callback_query.data.split("#")[1]) try: kueri = SCRAP_DICT[message_id][1] except KeyError: - return await callback_query.answer("Invalid callback data, please send CMD again..") + return await callback_query.answer(strings("invalid_cb")) try: - terbitres, PageLen, btn = await getDataMelong(callback_query.message, kueri, CurrentPage, callback_query.from_user.id) + terbitres, PageLen, btn = await getDataMelong(callback_query.message, kueri, CurrentPage, callback_query.from_user.id, strings) except TypeError: return keyboard = InlineKeyboard() keyboard.paginate(PageLen, CurrentPage, "page_melong#{number}" + f"#{message_id}#{callback_query.from_user.id}") - keyboard.row(InlineButton("πŸ‘‡ Extract Data ", "Hmmm")) + keyboard.row(InlineButton(strings("ex_data"), user_id=callback_query.from_user.id)) keyboard.row(*btn) - keyboard.row(InlineButton("❌ Close", f"close#{callback_query.from_user.id}")) + keyboard.row(InlineButton(strings("cl_btn"), f"close#{callback_query.from_user.id}")) await editPesan(callback_query.message, terbitres, disable_web_page_preview=True, reply_markup=keyboard) # Lk21 Page Callback @app.on_callback_query(filters.create(lambda _, __, query: "page_lk21#" in query.data)) @ratelimiter -async def lk21page_callback(client, callback_query): +@use_chat_lang() +async def lk21page_callback(client, callback_query, strings): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): - return await callback_query.answer("Not yours..", True) + return await callback_query.answer(strings("unauth"), True) message_id = int(callback_query.data.split("#")[2]) CurrentPage = int(callback_query.data.split("#")[1]) try: kueri = SCRAP_DICT[message_id][1] except KeyError: - return await callback_query.answer("Invalid callback data, please send CMD again..") + return await callback_query.answer(strings("invalid_cb")) try: - lkres, PageLen = await getDatalk21(callback_query.message, kueri, CurrentPage) + lkres, PageLen = await getDatalk21(callback_query.message, kueri, CurrentPage, strings) except TypeError: return keyboard = InlineKeyboard() keyboard.paginate(PageLen, CurrentPage, "page_lk21#{number}" + f"#{message_id}#{callback_query.from_user.id}") - keyboard.row(InlineButton("❌ Close", f"close#{callback_query.from_user.id}")) + keyboard.row(InlineButton(strings("cl_btn"), f"close#{callback_query.from_user.id}")) await editPesan(callback_query.message, lkres, disable_web_page_preview=True, reply_markup=keyboard) # Pahe Page Callback @app.on_callback_query(filters.create(lambda _, __, query: "page_pahe#" in query.data)) @ratelimiter -async def pahepage_callback(client, callback_query): +@use_chat_lang() +async def pahepage_callback(client, callback_query, strings): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): - return await callback_query.answer("Not yours..", True) + return await callback_query.answer(strings("unauth"), True) message_id = int(callback_query.data.split("#")[2]) CurrentPage = int(callback_query.data.split("#")[1]) try: kueri = SCRAP_DICT[message_id][1] except KeyError: - return await callback_query.answer("Invalid callback data, please send CMD again..") + return await callback_query.answer(strings("invalid_cb")) try: - lkres, PageLen = await getDataPahe(callback_query.message, kueri, CurrentPage) + lkres, PageLen = await getDataPahe(callback_query.message, kueri, CurrentPage, strings) except TypeError: return keyboard = InlineKeyboard() keyboard.paginate(PageLen, CurrentPage, "page_pahe#{number}" + f"#{message_id}#{callback_query.from_user.id}") - keyboard.row(InlineButton("❌ Close", f"close#{callback_query.from_user.id}")) + keyboard.row(InlineButton(strings("cl_btn"), f"close#{callback_query.from_user.id}")) await editPesan(callback_query.message, lkres, disable_web_page_preview=True, reply_markup=keyboard) # Gomov Page Callback @app.on_callback_query(filters.create(lambda _, __, query: "page_gomov#" in query.data)) @ratelimiter -async def gomovpage_callback(client, callback_query): +@use_chat_lang() +async def gomovpage_callback(client, callback_query, strings): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): - return await callback_query.answer("Not yours..", True) + return await callback_query.answer(strings("unauth"), True) message_id = int(callback_query.data.split("#")[2]) CurrentPage = int(callback_query.data.split("#")[1]) try: kueri = SCRAP_DICT[message_id][1] except KeyError: - return await callback_query.answer("Invalid callback data, please send CMD again..") + return await callback_query.answer(strings("invalid_cb")) try: - gomovres, PageLen, btn = await getDataGomov(callback_query.message, kueri, CurrentPage, callback_query.from_user.id) + gomovres, PageLen, btn = await getDataGomov(callback_query.message, kueri, CurrentPage, callback_query.from_user.id, strings) except TypeError: return keyboard = InlineKeyboard() keyboard.paginate(PageLen, CurrentPage, "page_gomov#{number}" + f"#{message_id}#{callback_query.from_user.id}") - keyboard.row(InlineButton("πŸ‘‡ Extract Data ", "Hmmm")) + keyboard.row(InlineButton(strings("ex_data"), user_id=callback_query.from_user.id)) keyboard.row(*btn) - keyboard.row(InlineButton("❌ Close", f"close#{callback_query.from_user.id}")) + keyboard.row(InlineButton(strings("cl_btn"), f"close#{callback_query.from_user.id}")) await editPesan(callback_query.message, gomovres, disable_web_page_preview=True, reply_markup=keyboard) @@ -734,24 +753,25 @@ async def gomovpage_callback(client, callback_query): # Kusonime DDL @app.on_callback_query(filters.create(lambda _, __, query: "kusoextract#" in query.data)) @ratelimiter -async def kusonime_scrap(_, callback_query): +@use_chat_lang() +async def kusonime_scrap(_, callback_query, strings): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): - return await callback_query.answer("Not yours..", True) + return await callback_query.answer(strings("unauth"), True) idlink = int(callback_query.data.split("#")[2]) message_id = int(callback_query.data.split("#")[4]) CurrentPage = int(callback_query.data.split("#")[1]) try: link = SCRAP_DICT[message_id][0][CurrentPage - 1][idlink - 1].get("link") except KeyError: - return await callback_query.answer("Invalid callback data, please send CMD again..") + return await callback_query.answer(strings("invalid_cb")) kuso = Kusonime() keyboard = InlineKeyboard() - keyboard.row(InlineButton("↩️ Back", f"page_kuso#{CurrentPage}#{message_id}#{callback_query.from_user.id}"), InlineButton("❌ Close", f"close#{callback_query.from_user.id}")) + keyboard.row(InlineButton(strings("back_btn"), f"page_kuso#{CurrentPage}#{message_id}#{callback_query.from_user.id}"), InlineButton(strings("cl_btn"), f"close#{callback_query.from_user.id}")) try: if init_url := data_kuso.get(link, None): ph = init_url.get("ph_url") - await editPesan(callback_query.message, f"Scrape result from {link}:\n\n{ph}", reply_markup=keyboard, disable_web_page_preview=False) + await editPesan(callback_query.message, strings("res_scrape").format(link=link, kl=ph), reply_markup=keyboard, disable_web_page_preview=False) return tgh = await kuso.telegraph(link, message_id) if tgh["error"]: @@ -761,25 +781,26 @@ async def kusonime_scrap(_, callback_query): await editPesan(callback_query.message, f"ERROR: {err}", reply_markup=keyboard) return data_kuso[link] = {"ph_url": tgh["url"]} - await editPesan(callback_query.message, f"Scrape result from {link}:\n\n{tgh['url']}", reply_markup=keyboard, disable_web_page_preview=False) + await editPesan(callback_query.message, strings("res_scrape").format(link=link, kl=tgh['url']), reply_markup=keyboard, disable_web_page_preview=False) # Savefilm21 DDL @app.on_callback_query(filters.create(lambda _, __, query: "sf21extract#" in query.data)) @ratelimiter -async def savefilm21_scrap(_, callback_query): +@use_chat_lang() +async def savefilm21_scrap(_, callback_query, strings): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): - return await callback_query.answer("Not yours..", True) + return await callback_query.answer(strings("unauth"), True) idlink = int(callback_query.data.split("#")[2]) message_id = int(callback_query.data.split("#")[4]) CurrentPage = int(callback_query.data.split("#")[1]) try: link = SCRAP_DICT[message_id][0][CurrentPage - 1][idlink - 1].get("link") except KeyError: - return await callback_query.answer("Invalid callback data, please send CMD again..") + return await callback_query.answer(strings("invalid_cb")) keyboard = InlineKeyboard() - keyboard.row(InlineButton("↩️ Back", f"page_savefilm#{CurrentPage}#{message_id}#{callback_query.from_user.id}"), InlineButton("❌ Close", f"close#{callback_query.from_user.id}")) + keyboard.row(InlineButton(strings("back_btn"), f"page_savefilm#{CurrentPage}#{message_id}#{callback_query.from_user.id}"), InlineButton(strings("cl_btn"), f"close#{callback_query.from_user.id}")) try: html = await http.get(link, headers=headers) soup = BeautifulSoup(html.text, "lxml") @@ -788,13 +809,14 @@ async def savefilm21_scrap(_, callback_query): except Exception as err: await editPesan(callback_query.message, f"ERROR: {err}", reply_markup=keyboard) return - await editPesan(callback_query.message, f"Scrape result from {link}:\n\n{res}", reply_markup=keyboard) + await editPesan(callback_query.message, strings("res_scrape").format(link=link, kl=res), reply_markup=keyboard) # Scrape Link Download Movieku.CC @app.on_message(filters.command(["movieku_scrap"], COMMAND_HANDLER)) @ratelimiter -async def muviku_scrap(_, message): +@use_chat_lang() +async def muviku_scrap(_, message, strings): try: link = message.text.split(" ", maxsplit=1)[1] html = await http.get(link, headers=headers) @@ -808,11 +830,11 @@ async def muviku_scrap(_, message): # print(f"{kualitas}\n{link data.append({"link": link, "kualitas": kualitas}) if not data: - return await message.reply("Oops, data film tidak ditemukan.") + return await message.reply(strings("no_result")) res = "".join(f"Host: {i['kualitas']}\n{i['link']}\n\n" for i in data) await message.reply(res) except IndexError: - return await message.reply(f"Gunakan command /{message.command[0]} [link] untuk scrap link download") + return await message.reply(strings("invalid_cmd_scrape").format(cmd=message.command[0])) except Exception as e: await message.reply(f"ERROR: {str(e)}") @@ -820,19 +842,20 @@ async def muviku_scrap(_, message): # Scrape DDL Link Melongmovie @app.on_callback_query(filters.create(lambda _, __, query: "melongextract#" in query.data)) @ratelimiter -async def melong_scrap(_, callback_query): +@use_chat_lang() +async def melong_scrap(_, callback_query, strings): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): - return await callback_query.answer("Not yours..", True) + return await callback_query.answer(strings("uauth"), True) idlink = int(callback_query.data.split("#")[2]) message_id = int(callback_query.data.split("#")[4]) CurrentPage = int(callback_query.data.split("#")[1]) try: link = SCRAP_DICT[message_id][0][CurrentPage - 1][idlink - 1].get("link") except KeyError: - return await callback_query.answer("Invalid callback data, please send CMD again..") + return await callback_query.answer(strings("invalid_cb")) keyboard = InlineKeyboard() - keyboard.row(InlineButton("↩️ Back", f"page_melong#{CurrentPage}#{message_id}#{callback_query.from_user.id}"), InlineButton("❌ Close", f"close#{callback_query.from_user.id}")) + keyboard.row(InlineButton(strings("back_btn"), f"page_melong#{CurrentPage}#{message_id}#{callback_query.from_user.id}"), InlineButton(strings("cl_btn"), f"close#{callback_query.from_user.id}")) try: html = await http.get(link, headers=headers) soup = BeautifulSoup(html.text, "lxml") @@ -844,25 +867,26 @@ async def melong_scrap(_, callback_query): except Exception as err: await editPesan(callback_query.message, f"ERROR: {err}", reply_markup=keyboard) return - await editPesan(callback_query.message, f"Scrape result from {link}:\n\n{rep}", reply_markup=keyboard) + await editPesan(callback_query.message, strings("res_scrape").format(link=link, kl=rep), reply_markup=keyboard) # Scrape DDL Link Gomov @app.on_callback_query(filters.create(lambda _, __, query: "gomovextract#" in query.data)) @ratelimiter -async def gomov_dl(_, callback_query): +@use_chat_lang() +async def gomov_dl(_, callback_query, strings): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): - return await callback_query.answer("Not yours..", True) + return await callback_query.answer(strings("unauth"), True) idlink = int(callback_query.data.split("#")[2]) message_id = int(callback_query.data.split("#")[4]) CurrentPage = int(callback_query.data.split("#")[1]) try: link = SCRAP_DICT[message_id][0][CurrentPage - 1][idlink - 1].get("link") except KeyError: - return await callback_query.answer("Invalid callback data, please send CMD again..") + return await callback_query.answer(strings("invalid_cb")) keyboard = InlineKeyboard() - keyboard.row(InlineButton("↩️ Back", f"page_gomov#{CurrentPage}#{message_id}#{callback_query.from_user.id}"), InlineButton("❌ Close", f"close#{callback_query.from_user.id}")) + keyboard.row(InlineButton(strings("back_btn"), f"page_gomov#{CurrentPage}#{message_id}#{callback_query.from_user.id}"), InlineButton(strings("cl_btn"), f"close#{callback_query.from_user.id}")) try: html = await http.get(link, headers=headers) soup = BeautifulSoup(html.text, "lxml") @@ -875,34 +899,35 @@ async def gomov_dl(_, callback_query): except Exception as err: await editPesan(callback_query.message, f"ERROR: {err}", reply_markup=keyboard) return - await editPesan(callback_query.message, f"Scrape result from {link}:\n\n{hasil}", reply_markup=keyboard) + await editPesan(callback_query.message, strings("res_scrape").format(link=link, kl=hasil), reply_markup=keyboard) @app.on_callback_query(filters.create(lambda _, __, query: "lendriveextract#" in query.data)) @ratelimiter -async def lendrive_dl(_, callback_query): +@use_chat_lang() +async def lendrive_dl(_, callback_query, strings): if callback_query.from_user.id != int(callback_query.data.split("#")[3]): - return await callback_query.answer("Not yours..", True) + return await callback_query.answer(strings("unauth"), True) idlink = int(callback_query.data.split("#")[2]) message_id = int(callback_query.data.split("#")[4]) CurrentPage = int(callback_query.data.split("#")[1]) try: link = SCRAP_DICT[message_id][0][CurrentPage - 1][idlink - 1].get("link") except KeyError: - return await callback_query.answer("Invalid callback data, please send CMD again..") + return await callback_query.answer(strings("invalid_cb")) keyboard = InlineKeyboard() - keyboard.row(InlineButton("↩️ Back", f"page_lendrive#{CurrentPage}#{message_id}#{callback_query.from_user.id}"), InlineButton("❌ Close", f"close#{callback_query.from_user.id}")) + keyboard.row(InlineButton(strings("back_btn"), f"page_lendrive#{CurrentPage}#{message_id}#{callback_query.from_user.id}"), InlineButton(strings("cl_btn"), f"close#{callback_query.from_user.id}")) try: hmm = await http.get(link, headers=headers) q = BeautifulSoup(hmm.text, "lxml") j = q.findAll("div", class_="soraurlx") - kl = "#Lendrive Results Download URL:\n\n" + kl = "" for i in j: if not i.find("a"): continue kl += f"{i.find('strong')}:\n" kl += "".join(f"[ {a.text} ]\n" for a in i.findAll("a")) - await editPesan(callback_query.message, f"Scrape result from {link}:\n\n{kl}", reply_markup=keyboard) + await editPesan(callback_query.message, strings("res_scrape").format(link=link, kl=kl), reply_markup=keyboard) except Exception as err: await editPesan(callback_query.message, f"ERROR: {err}", reply_markup=keyboard) diff --git a/misskaty/plugins/ytdl_download_new.py b/misskaty/plugins/ytdl_plugins.py similarity index 78% rename from misskaty/plugins/ytdl_download_new.py rename to misskaty/plugins/ytdl_plugins.py index 6f1e691d..49cd4d0f 100644 --- a/misskaty/plugins/ytdl_download_new.py +++ b/misskaty/plugins/ytdl_plugins.py @@ -11,6 +11,7 @@ from misskaty.core.message_utils import * from misskaty.core.decorator.errors import capture_err from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.helper.http import http +from misskaty.helper.localization import use_chat_lang from misskaty.vars import COMMAND_HANDLER, LOG_CHANNEL LOGGER = getLogger(__name__) @@ -25,23 +26,21 @@ def rand_key(): @app.on_message(filters.command(["ytsearch"], COMMAND_HANDLER) & ~filters.channel) @capture_err @ratelimiter -async def ytsearch(_, message): +@use_chat_lang() +async def ytsearch(_, message, strings): if message.sender_chat: - return await kirimPesan(message, "This feature not supported for channel.") + return await kirimPesan(message, strings("no_channel")) if len(message.command) == 1: - return await kirimPesan(message, "Please input a query..!") + return await kirimPesan(message, strings("no_query")) query = message.text.split(" ", maxsplit=1)[1] search_key = rand_key() YT_DB[search_key] = query search = await main.VideosSearch(query).next() if search["result"] == []: - return await message.reply(f"No result found for `{query}`") + return await message.reply(strings("no_res").format(kweri=query)) i = search["result"][0] - out = f"{i['title']}" - out += f"\nPublished {i['publishedTime']}\n" - out += f"\n❯ Duration: {i['duration']}" - out += f"\n❯ Views: {i['viewCount']['short']}" - out += f"\n❯ Uploader: {i['channel']['name']}\n\n" + out = f"{i['title']}\n" + out = strings("yts_msg").format(pub=i['publishedTime'], dur=i['duration'], vi=i['viewCount']['short'], clink=i['channel']['link'], cname=i['channel']['name']) btn = InlineKeyboardMarkup( [ [ @@ -50,7 +49,7 @@ async def ytsearch(_, message): callback_data=f"ytdl_scroll|{search_key}|1", ) ], - [InlineKeyboardButton("Download", callback_data=f"yt_gen|{i['id']}")], + [InlineKeyboardButton(strings("dl_btn"), callback_data=f"yt_gen|{i['id']}")], ] ) img = await get_ytthumb(i["id"]) @@ -62,17 +61,18 @@ async def ytsearch(_, message): @app.on_message(filters.command(["ytdown"], COMMAND_HANDLER)) @capture_err @ratelimiter -async def ytdownv2(_, message): +@use_chat_lang() +async def ytdownv2(_, message, strings): if not message.from_user: - return + return await kirimPesan(message, strings("no_channel")) if len(message.command) == 1: - return await message.reply("Please input a valid YT-DLP Supported URL") + return await message.reply(strings("invalid_link")) url = message.text.split(" ", maxsplit=1)[1] async with iYTDL(log_group_id=0, cache_path="cache", ffmpeg_location="/usr/bin/mediaextract") as ytdl: try: x = await ytdl.parse(url) if x is None: - return await message.reply("Failed parse URL, check logs..") + return await message.reply(strings("err_parse")) img = await get_ytthumb(x.key) caption = x.caption markup = x.buttons @@ -83,9 +83,10 @@ async def ytdownv2(_, message): @app.on_callback_query(filters.regex(r"^yt_listall")) @ratelimiter -async def ytdl_listall_callback(_, cq: CallbackQuery): +@use_chat_lang() +async def ytdl_listall_callback(_, cq: CallbackQuery, strings): if cq.from_user.id != cq.message.reply_to_message.from_user.id: - return await cq.answer("Not your task", True) + return await cq.answer(strings("unauth"), True) callback = cq.data.split("|") async with iYTDL(log_group_id=0, cache_path="cache", ffmpeg_location="/usr/bin/mediaextract") as ytdl: media, buttons = await ytdl.listview(callback[1]) @@ -94,10 +95,11 @@ async def ytdl_listall_callback(_, cq: CallbackQuery): @app.on_callback_query(filters.regex(r"^yt_extract_info")) @ratelimiter -async def ytdl_extractinfo_callback(_, cq: CallbackQuery): +@use_chat_lang() +async def ytdl_extractinfo_callback(_, cq: CallbackQuery, strings): if cq.from_user.id != cq.message.reply_to_message.from_user.id: - return await cq.answer("Not your task", True) - await cq.answer("Please Wait...") + return await cq.answer(strings("unauth"), True) + await cq.answer(strings("wait")) callback = cq.data.split("|") async with iYTDL(log_group_id=0, cache_path="cache", ffmpeg_location="/usr/bin/mediaextract") as ytdl: if data := await ytdl.extract_info_from_key(callback[1]): @@ -120,9 +122,10 @@ async def ytdl_extractinfo_callback(_, cq: CallbackQuery): @app.on_callback_query(filters.regex(r"^yt_(gen|dl)")) @ratelimiter -async def ytdl_gendl_callback(_, cq: CallbackQuery): +@use_chat_lang() +async def ytdl_gendl_callback(_, cq: CallbackQuery, strings): if cq.from_user.id != cq.message.reply_to_message.from_user.id: - return await cq.answer("Not your task", True) + return await cq.answer(strings("unauth"), True) callback = cq.data.split("|") key = callback[1] if callback[0] == "yt_gen": @@ -170,9 +173,10 @@ async def ytdl_gendl_callback(_, cq: CallbackQuery): @app.on_callback_query(filters.regex(r"^ytdl_scroll")) @ratelimiter -async def ytdl_scroll_callback(_, cq: CallbackQuery): +@use_chat_lang() +async def ytdl_scroll_callback(_, cq: CallbackQuery, strings): if cq.from_user.id != cq.message.reply_to_message.from_user.id: - return await cq.answer("Not your task", True) + return await cq.answer(strings("unauth"), True) callback = cq.data.split("|") search_key = callback[1] page = int(callback[2]) @@ -180,13 +184,10 @@ async def ytdl_scroll_callback(_, cq: CallbackQuery): search = await main.VideosSearch(query).next() i = search["result"][page] out = f"{i['title']}" - out += f"\nPublished {i['publishedTime']}\n" - out += f"\n❯ Duration: {i['duration']}" - out += f"\n❯ Views: {i['viewCount']['short']}" - out += f"\n❯ Uploader: {i['channel']['name']}\n\n" + out = strings("yts_msg").format(pub=i['publishedTime'], dur=i['duration'], vi=i['viewCount']['short'], clink=i['channel']['link'], cname=i['channel']['name']) scroll_btn = [ [ - InlineKeyboardButton("Back", callback_data=f"ytdl_scroll|{search_key}|{page-1}"), + InlineKeyboardButton(strings("back"), callback_data=f"ytdl_scroll|{search_key}|{page-1}"), InlineKeyboardButton( f"{page+1}/{len(search['result'])}", callback_data=f"ytdl_scroll|{search_key}|{page+1}", @@ -195,11 +196,11 @@ async def ytdl_scroll_callback(_, cq: CallbackQuery): ] if page == 0: if len(search["result"]) == 1: - return await cq.answer("That's the end of list", show_alert=True) + return await cq.answer(strings("endlist"), show_alert=True) scroll_btn = [[scroll_btn.pop().pop()]] elif page == (len(search["result"]) - 1): scroll_btn = [[scroll_btn.pop().pop(0)]] - btn = [[InlineKeyboardButton("Download", callback_data=f"yt_gen|{i['id']}")]] + btn = [[InlineKeyboardButton(strings("dl_btn"), callback_data=f"yt_gen|{i['id']}")]] btn = InlineKeyboardMarkup(scroll_btn + btn) await cq.edit_message_media(InputMediaPhoto(await get_ytthumb(i["id"]), caption=out), reply_markup=btn)