MultiLanguage Support [BETA] (#21)

Pushed to public since i dont know when became stable
This commit is contained in:
yasirarism 2023-03-28 13:15:39 +07:00 committed by GitHub
parent 6ea9bf9d98
commit 3a6c0b424e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
72 changed files with 1142 additions and 448 deletions

16
database/locale_db.py Normal file
View file

@ -0,0 +1,16 @@
from pyrogram.enums import ChatType
from typing import Iterable
from database import dbname
localesdb = dbname.locale # DB for localization
group_types: Iterable[ChatType] = (ChatType.GROUP, ChatType.SUPERGROUP)
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:
ul = await localesdb.find_one({"chat_id": chat_id})
return ul["lang"] if ul else {}

0
locales/__init__.py Normal file
View file

68
locales/en-US/admins.json Normal file
View file

@ -0,0 +1,68 @@
{
"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 <code>/help</code> 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.",
"report_no_reply": "Reply To A Message To Report That User.",
"no_delete_perm": "Please give me delete message permission.",
"purge_success": "Successfully deleted {del_total} messages..",
"user_not_found": "I can't find that user.",
"invalid_id_uname": "⚠️ Invalid userid/username",
"kick_self_err": "I can't kick myself, i can leave if you want.",
"ban_self_err": "I can't ban myself, i can leave if you want.",
"report_self_err": "Why are you reporting yourself ?",
"demote_self_err": "I can't demote myself.",
"warn_self_err": "I can't warn myself.",
"mute_self_err": "I can't mute myself.",
"kick_sudo_err": "Wow, you wanna kick my owner?",
"ban_sudo_err": "Wow, you wanna try ban my owner?",
"demote_sudo_err": "Wow, you wanna try demote my owner?",
"warn_sudo_err": "Wow, you wanna try give warning to my owner?",
"mute_sudo_err": "Wow, you wanna try give mute to my owner?",
"kick_admin_err": "Lol, it's crazy if i can kick an admin.",
"ban_admin_err": "Lol, it's crazy if i can banned an admin.",
"mute_admin_err": "Lol, it's crazy if i can mute an admin.",
"warn_admin_err": "Lol, it's crazy if i can warn an admin.",
"kick_msg": "**Kicked User:** {mention} [{id}]\n**Kicked By:** {kicker}\n**Reason:** {reasonmsg}",
"ban_msg": "**Banned User:** {mention} [{id}]\n**Banned By:** {banner}\n",
"unban_msg": "__Banned removed by {mention}__",
"no_ban_permission": "Please give me ban permission to ban user in this group.",
"no_more_99": "You can't use more than 99",
"banned_time": "**Banned For:** {val}\n",
"muted_time": "**Muted For:** {val}\n",
"banned_reason": "**Reason:** {reas}",
"unban_channel_err": "You cannot unban a channel",
"give_unban_user": "Provide a username or reply to a user's message to unban.",
"unban_success": "Successfully unbanned {umention}!",
"give_idban_with_msg_link": "Provide a userid/username along with message link and reason to list-ban",
"give_idunban_with_msg_link": "Provide a userid/username along with message link and reason to list-unban",
"give_reason_list_ban": "You must provide a reason to list-ban",
"Invalid_tg_link": "Invalid message link provided",
"multiple_ban_progress": "`Banning User from multiple groups. This may take some time`",
"multiple_unban_progress": "`Unbanning User from multiple groups. This may take some time`",
"failed_get_uname": "Could not get group usernames",
"listban_msg": "**List-Banned User:** {mention}\n**Banned User ID:** `{uid}`\n**Admin:** {frus}\n**Affected chats:** `{ct}`\n**Reason:** {reas}",
"listunban_msg": "**List-Unbanned User:** {mention}\n**Unbanned User ID:** `{uid}`\n**Admin:** {frus}\n**Affected chats:** `{ct}`\n**Reason:** {reas}",
"promote_self_err": "I can't promote myself.",
"no_promote_perm": "Sadly, I don't permission to promote users.",
"full_promote": "Fully Promoted {umention}!",
"normal_promote": "Promoted {umention}!",
"pin_success": "**Pinned [this]({link}) message.**",
"unpin_success": "**UnPinned [this]({link}) message.**",
"pin_no_perm": "Please give me pin permission to use this command!.",
"report_msg": "Reported {user_mention} to admins!",
"reported_is_admin": "Do you know that the user you are replying is an admin ?",
"user_no_warn": "User {mention} has no warnings.",
"ch_warn_msg": "User {mention} has {warns}/3 warnings.",
"warn_msg": "**Warned User:** {mention}\n**Warned By:** {warner}\n**Reason:** {reas}\n**Warns:** {twarn}/3",
"rmwarn_msg": "Removed warnings of {mention}.",
"unwarn_msg": "Removed warnings by {mention}.",
"rmmute_msg": "__Mute removed by {mention}__",
"unmute_msg": "Unmuted! {umention}",
"reply_to_rm_warn": "Reply to a message to remove a user's warnings.",
"exceed_warn_msg": "Number of warns of {mention} exceeded, BANNED!",
"mute_msg": "**Muted User:** {mention}\n**Muted By:** {muter}\n",
"rm_warn_btn": "🚨 Remove Warn 🚨"
}

View file

@ -0,0 +1,5 @@
{
"no_question": "Please use command <code>/{cmd} [question]</code> to ask your question.",
"find_answers_str": "Wait a moment looking for your answer..",
"answers_too_long": "Question for your answer has exceeded TG text limit, check this link to view.\n\n{answerlink}"
}

3
locales/en-US/fun.json Normal file
View file

@ -0,0 +1,3 @@
{
"result": "🎲 The dice stopped at the number: {number}"
}

View file

@ -0,0 +1,3 @@
{
"back_btn": "« Go back"
}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1,5 @@
{
"language_changed_successfully": "The language has been changed successfully.",
"language_changer_chat": "Here you can change the language used for the bot throughout the chat.\nIf your language is not listed here and you would like to contribute, you can open issue in my github repo.",
"language_changer_private": "Here you can change the language used for the bot in this private chat.\n\nIf you want to change the language of your group, please run the command <code>/setchatlang</code> on it.\nIf your language is not listed here and you would like to contribute, you can open issue in my github repo."
}

4
locales/en-US/main.json Normal file
View file

@ -0,0 +1,4 @@
{
"language_name": "English",
"language_flag": "🇬🇧"
}

View file

@ -0,0 +1,11 @@
{
"processing_text": "`Processing, total time is based on the size of your files...`",
"wait_msg": "`Please wait a moment...`",
"err_link": "It looks like the link you sent is invalid, make sure it's a direct link and can be downloaded.",
"media_invalid": "Please reply to valid media.",
"dl_limit_exceeded": "Sorry, download limited to 2GB to reduce flood. You can convert your files to link.",
"dl_args_text": "Trying to download..",
"mediainfo_help": "Use the command /{cmd} [link], or reply to telegram media with /{cmd}.",
"capt_media": " Your mediainfo results..\n\n**Request By:** {ment}",
"viweb": "💬 Open on Web"
}

6
locales/en-US/ocr.json Normal file
View file

@ -0,0 +1,6 @@
{
"no_photo": "Reply photo with /{cmd} command to scan text from images.",
"read_ocr": "Scanning your images..",
"result_ocr": "Hasil OCR:\n<code>{result}</code>",
"ocr_helper": "/ocr [reply to photo] - Read Text From Image"
}

View file

@ -0,0 +1,13 @@
{
"no_uname": "<code>No Username</code>",
"no_last_name": "<code>No Last Name</code>",
"uname_change_msg": "✨ Changed username from {bef} ➡️ <code>{aft}</code>.\n",
"lastname_change_msg": "✨ Changed last name from {bef} ➡️ <code>{aft}</code>.\n",
"firstname_change_msg": "✨ Changed first name from {bef} ➡️ <code>{aft}</code>.\n",
"set_sangmata_help": "Use <code>/{cmd} on</code>, to enable sangmata. If you want disable, you can use off parameter.",
"sangmata_already_on": "SangMata already enabled in your groups.",
"sangmata_enabled": "Sangmata enabled in your groups.",
"sangmata_already_off": "SangMata already disabled in your groups.",
"sangmata_disabled": "Sangmata disabled in your groups.",
"wrong_param": "Unknown parameter, use only on/off parameter."
}

View file

@ -0,0 +1,19 @@
{
"no_anim_stick": "Animated sticker is not supported!",
"not_sticker": "This is not a sticker!",
"unkang_msg": "Trying to remove from pack..",
"unkang_success": "Sticker has been removed from your pack",
"unkang_error": "Failed remove sticker from your pack.\n\nERR: {e}",
"unkang_help": "Please reply sticker that created by {c} to remove sticker from your pack.",
"anon_warn": "You are anon admin, kang stickers in my pm.",
"kang_msg": "Trying to steal your sticker...",
"stick_no_name": "The sticker has no name.",
"kang_help": "Want me to guess the sticker? Please tag a sticker.",
"exist_pack": "<code>Using existing sticker pack...</code>",
"new_packs": "<b>Creating a new sticker pack...</b>",
"please_start_msg": "It looks like you've never interacted with me in private chat, you need to do that first..",
"click_me": "Click Me",
"pack_full": "Your Sticker Pack is full if your pack is not in v1 Type /kang 1, if it is not in v2 Type /kang 2 and so on.",
"viewpack": "👀 View Your Pack",
"kang_success": "<b>Sticker successfully stolen!</b>\n<b>Emoji:</b> {emot}"
}

View file

@ -0,0 +1 @@
{}

5
locales/en-US/webss.json Normal file
View file

@ -0,0 +1,5 @@
{
"no_url": "Give A Url To Fetch Screenshot.",
"wait_str": "Capturing screenshot...",
"ss_failed_str": "Failed To Take Screenshot. {err}"
}

68
locales/id-ID/admins.json Normal file
View file

@ -0,0 +1,68 @@
{
"no_admin_error": "Anda harus merupakan 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 <code>/help</code>.",
"purge_no_reply": "Balas pesan untuk 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.",
"no_delete_perm": "Tolong beri saya izin untuk menghapus pesan.",
"purge_success": "Berhasil menghapus {del_total} pesan..",
"user_not_found": "Saya tidak dapat menemukan pengguna itu.",
"invalid_id_uname": "⚠️ ID pengguna/nama pengguna salah",
"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.",
"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?",
"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.",
"ban_admin_err": "Hah, sungguh gila jika saya bisa melarang seorang admin.",
"mute_admin_err": "Hah, sungguh gila jika saya bisa membisukan admin.",
"warn_admin_err": "Hah, sungguh gila jika saya bisa memperingatkan seorang admin.",
"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_more_99": "Anda tidak dapat menggunakan lebih dari 99",
"banned_time": "**Dilarang Untuk:** {val}\n",
"muted_time": "**Dimatikan 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.",
"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",
"give_reason_list_ban": "Anda harus memberikan alasan untuk melarang daftar",
"Invalid_tg_link": "Tautan pesan yang diberikan tidak valid",
"multiple_ban_progress": "`Melarang Pengguna dari banyak grup. Ini mungkin membutuhkan waktu`",
"multiple_unban_progress": "`Membatalkan pencekalan Pengguna dari banyak grup. Ini mungkin membutuhkan waktu`",
"failed_get_uname": "Tidak dapat memperoleh nama pengguna grup",
"listban_msg": "**Pengguna yang Dilarang Daftar:** {mention}\n**ID Pengguna yang Dilarang:** `{uid}`\n**Admin:** {frus}\n**Obrolan yang terpengaruh: ** `{ct}`\n**Alasan:** {reas}",
"listunban_msg": "**Pengguna yang Tidak Dilarang Daftar:** {mention}\n**ID Pengguna yang Tidak Dilarang:** `{uid}`\n**Admin:** {frus}\n**Obrolan yang terpengaruh: ** `{ct}`\n**Alasan:** {reas}",
"promote_self_err": "Saya tidak dapat mempromosikan diri saya sendiri.",
"no_promote_perm": "Sayangnya, saya tidak mengizinkan untuk mempromosikan pengguna.",
"full_promote": "Dipromosikan Sepenuhnya {umention}!",
"normal_promote": "Dipromosikan {umention}!",
"pin_success": "**Pesan [ini]({link}) disematkan.**",
"unpin_success": "**Pesan [ini]({link}) yang tidak disematkan.**",
"pin_no_perm": "Tolong beri saya izin pin untuk menggunakan perintah ini!.",
"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.",
"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}.",
"rmmute_msg": "__Bisukan dihapus oleh {mention}__",
"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",
"rm_warn_btn": "🚨 Hapus Peringatan 🚨"
}

View file

@ -0,0 +1,5 @@
{
"no_question": "Harap gunakan perintah <code>/{cmd} [question]</code> untuk mengajukan pertanyaan Anda.",
"find_answers_str": "Tunggu sebentar untuk mencari jawaban Anda..",
"answers_too_long": "Pertanyaan untuk jawaban Anda telah melampaui batas teks TG, periksa tautan ini untuk melihatnya.\n\n{answerlink}"
}

3
locales/id-ID/fun.json Normal file
View file

@ -0,0 +1,3 @@
{
"result": "🎲 Dadu berhenti di angka: {number}"
}

View file

@ -0,0 +1,4 @@
{
"back_btn": "« Kembali",
"no_results": "Tidak ada hasil yang ditemukan."
}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +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 <code>/setchatlang</code>. \nJika bahasa Anda tidak ada di sini dan Anda ingin berkontribusi, kunjungi repo misskaty."
}

4
locales/id-ID/main.json Normal file
View file

@ -0,0 +1,4 @@
{
"language_name": "Indonesia",
"language_flag": "🇮🇩"
}

View file

@ -0,0 +1,11 @@
{
"processing_text": "`Memproses, total waktu didasarkan pada ukuran file Anda...`",
"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_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"
}

6
locales/id-ID/ocr.json Normal file
View file

@ -0,0 +1,6 @@
{
"no_photo": "Balas foto dengan perintah /{cmd} untuk memindai teks dari gambar.",
"read_ocr": "Memindai gambar Anda..",
"result_ocr": "Hasil OCR:\n<code>{result}</code>",
"ocr_helper": "/ocr [balas ke foto] - Baca Teks Dari Gambar"
}

View file

@ -0,0 +1,13 @@
{
"no_uname": "<code>Tanpa Username</code>",
"no_last_name": "<code>Tanpa Nama Belakang</code>",
"uname_change_msg": "✨ Mengubah nama depan dari {bef} ➡️ <code>{aft}</code>.\n",
"lastname_change_msg": "✨ Mengubah nama belakang dari {bef} ➡️ <code>{aft}</code>.\n",
"firstname_change_msg": "✨ Mengubah nama depan dari {bef} ➡️ <code>{aft}</code>.\n",
"set_sangmata_help": "Gunakan <code>/{cmd} on</code>, untuk mengaktifkan sangmata. Jika Anda ingin menonaktifkan, Anda dapat menggunakan parameter off.",
"sangmata_already_on": "SangMata telah diaktifkan di grup Anda.",
"sangmata_enabled": "Sangmata diaktifkan di grup Anda.",
"sangmata_already_off": "SangMata telah dinonaktifkan di grup Anda.",
"sangmata_disabled": "Sangmata dinonaktifkan di grup Anda.",
"wrong_param": "Parameter tidak diketahui, gunakan hanya parameter hidup/mati."
}

View file

@ -0,0 +1,19 @@
{
"no_anim_stick": "Stiker animasi tidak didukung!",
"not_sticker": "Ini bukan stiker!",
"unkang_msg": "Mencoba menghapus dari paket..",
"unkang_success": "Stiker telah dihapus dari paket Anda",
"unkang_error": "Gagal menghapus stiker dari paket Anda.\n\nERR: {e}",
"unkang_help": "Tolong balas stiker yang dibuat oleh {c} untuk menghapus stiker dari paket Anda.",
"anon_warn": "Anda adalah admin anon, stiker kang ada di pm saya.",
"kang_msg": "Mencoba mencuri stiker Anda...",
"stick_no_name": "Stiker tidak memiliki nama.",
"kang_help": "Ingin saya menebak stikernya? Harap tandai stiker.",
"exist_pack": "<code>Menggunakan paket stiker yang ada...</code>",
"new_packs": "<b>Membuat paket stiker baru...</b>",
"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",
"kang_success": "<b>Stiker berhasil dicuri!</b>\n<b>Emoji:</b> {emot}"
}

View file

@ -0,0 +1 @@
{}

5
locales/id-ID/webss.json Normal file
View file

@ -0,0 +1,5 @@
{
"no_url": "Berikan url untuk mengambil tangkapan layar.",
"wait_str": "Mengambil tangkapan layar...",
"ss_failed_str": "Gagal Mengambil Tangkapan Layar. ERROR: {err}"
}

68
locales/id-JW/admins.json Normal file
View file

@ -0,0 +1,68 @@
{
"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 <code>/help</code>.",
"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.",
"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.",
"warn_self_err": "Aku ora bisa ngelekake awakku dhewe.",
"mute_self_err": "Aku ora bisa bisu.",
"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?",
"warn_sudo_err": "Wah, sampeyan pengin nyoba menehi peringatan marang pemilikku?",
"mute_sudo_err": "Wah, sampeyan pengin nyoba menehi bisu marang pemilikku?",
"kick_admin_err": "Lol, edan yen aku bisa nyepak admin.",
"ban_admin_err": "Lol, edan yen aku bisa nglarang admin.",
"mute_admin_err": "Lol, edan yen aku bisa bisu admin.",
"warn_admin_err": "Lol, edan yen aku bisa ngelingake admin.",
"kick_msg": "**Panganggo Ditendhang:** {mention} [{id}]\n**Ditendhang dening:** {kicker}\n**Alasan:** {reasonmsg}",
"ban_msg": "**Panganggo sing Dicekal:** {mention} [{id}]\n**Dicekal Dening:** {banner}\n",
"unban_msg": "__Dicekal dibusak kanthi {mention}__",
"no_ban_permission": "Mangga kula nyuwun idin nglarang panganggo ing grup punika.",
"no_more_99": "Sampeyan ora bisa nggunakake luwih saka 99",
"banned_time": "**Dicekal Kanggo:** {val}\n",
"muted_time": "**Diam Kanggo:** {val}\n",
"banned_reason": "**Alesan:** {reas}",
"unban_channel_err": "Sampeyan ora bisa mbatalake saluran",
"give_unban_user": "Nyedhiyani jeneng panganggo utawa mbales pesen panganggo kanggo mbatalake larangan.",
"unban_success": "Kasil mbatalake {umention}!",
"give_idban_with_msg_link": "Nyedhiyakake id panganggo/jeneng panganggo bebarengan karo pranala pesen lan alasan kanggo larangan daftar",
"give_idunban_with_msg_link": "Nyedhiyani id panganggo/jeneng panganggo bebarengan karo pranala pesen lan alasan kanggo daftar-unban",
"give_reason_list_ban": "Sampeyan kudu menehi alesan kanggo nglarang daftar",
"Invalid_tg_link": "Link pesen ora sah diwenehake",
"multiple_ban_progress": "`Nglarang Panganggo saka macem-macem grup. Iki mbutuhake sawetara wektu`",
"multiple_unban_progress": "`Mbusak Larangan Panganggo saka pirang-pirang grup. Iki mbutuhake sawetara wektu`",
"failed_get_uname": "Ora bisa njupuk jeneng panganggo grup",
"listban_msg": "**Panganggo sing Dilarang Dhaptar:** {mention}\n**ID Panganggo sing Dicekal:** `{uid}`\n**Admin:** {frus}\n**Obrolan sing kena pengaruh: ** `{ct}`\n**Alasan:** {reas}",
"listunban_msg": "**Daftar Panganggo sing Ora Dilarang:** {mention}\n**ID Panganggo sing Ora Dilarang:** `{uid}`\n**Admin:** {frus}\n**Obrolan sing kena pengaruh: ** `{ct}`\n**Alasan:** {reas}",
"promote_self_err": "Aku ora bisa promosi dhewe.",
"no_promote_perm": "Sedhih, aku ora ijin kanggo promosi pangguna.",
"full_promote": "{umention} dipromosekake kanthi lengkap!",
"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!.",
"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.",
"ch_warn_msg": "{mention} duwe {warning}/3 bebaya.",
"warn_msg": "**Panganggo sing Dielingake:** {mention}\n**Dielingake Dening:** {warner}\n**Alesan:** {reas}\n**Ngelingake:** {twarn}/ 3",
"rmwarn_msg": "Pènget saka {mention} wis dibusak.",
"unwarn_msg": "Pènget sing dibusak kanthi {mention}.",
"rmmute_msg": "__Bisu dibusak kanthi {mention}__",
"unmute_msg": "Ora bisu! {umention}",
"reply_to_rm_warn": "Bales pesen kanggo mbusak bebaya pangguna.",
"exceed_warn_msg": "Jumlah peringatan babagan {mention} ngluwihi, DIBRANG!",
"mute_msg": "**Panganggo Bisu:** {mention}\n**Dibunyikan Dening:** {muter}\n",
"rm_warn_btn": "🚨 Copot Warn 🚨"
}

View file

@ -0,0 +1,5 @@
{
"no_question": "Tulung gunakake printah <code>/{cmd} [pitakon]</code> kanggo takon.",
"find_answers_str": "Ngenteni sedhela goleki jawabanmu..",
"answers_too_long": "Pitakonan kanggo jawaban sampeyan wis ngluwihi wates teks TG, priksa pranala iki kanggo ndeleng.\n\n{answerlink}"
}

3
locales/id-JW/fun.json Normal file
View file

@ -0,0 +1,3 @@
{
"result": "🎲 Dadu mandheg ing nomer: {number}"
}

View file

@ -0,0 +1,4 @@
{
"back_btn": "« Balik Maneh",
"no_results": "Ora ana asil sing ditemokake."
}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1,5 @@
{
"language_changed_successfully": "Basa wis kasil diganti.",
"language_changer_chat": "Ing kene sampeyan bisa ngganti basa sing digunakake kanggo bot sajrone obrolan.\nYen basa sampeyan ora ana ing kene lan sampeyan pengin nyumbang, sampeyan bisa mbukak masalah ing githubku. .",
"language_changer_private": "Ing kene sampeyan bisa ngganti basa sing digunakake kanggo bot ing obrolan pribadi iki.\n\nYen sampeyan pengin ngganti basa grup sampeyan, bukak printah <code>/setchatlang</code>. \nYen basa sampeyan ora ana ing kene lan sampeyan pengin nyumbang, bukak repo misskaty."
}

4
locales/id-JW/main.json Normal file
View file

@ -0,0 +1,4 @@
{
"language_name": "Jawa",
"language_flag": "💫​"
}

View file

@ -0,0 +1,11 @@
{
"processing_text": "`Pengolahan, wektu total adhedhasar ukuran berkas panjenengan...`",
"wait_msg": "`Mohon tunggu sejenak...`",
"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_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}",
"viweb": "💬 Bukak Web"
}

6
locales/id-JW/ocr.json Normal file
View file

@ -0,0 +1,6 @@
{
"no_photo": "Bales foto nganggo printah /{cmd} kanggo mindhai teks saka gambar.",
"read_ocr": "Mindai gambar sampeyan..",
"result_ocr": "Hasil OCR:\n<kode>{result}</code>",
"ocr_helper": "/ocr [reply to photo] - Waca Teks Saka Gambar"
}

View file

@ -0,0 +1,13 @@
{
"no_uname": "<code>Ora Jeneng Panganggo</code>",
"no_last_name": "<kode>Ora Ana Jeneng mburi</code>",
"uname_change_msg": "✨ Jeneng pangguna diganti saka {bef} ➡️ <code>{aft}</code>.\n",
"lastname_change_msg": "✨ Ganti jeneng mburi saka {bef} ➡️ <code>{aft}</code>.\n",
"firstname_change_msg": "✨ Ganti jeneng ngarep saka {bef} ➡️ <code>{aft}</code>.\n",
"set_sangmata_help": "Gunakake <code>/{cmd} on</code>, kanggo ngaktifake sangmata. Yen sampeyan pengin mateni, sampeyan bisa nggunakake parameter mati.",
"sangmata_already_on": "SangMata wis diaktifake ing grup sampeyan.",
"sangmata_enabled": "Sangmata diaktifake ing grup sampeyan.",
"sangmata_already_off": "SangMata wis dipateni ing grup sampeyan.",
"sangmata_disabled": "Sangmata dipateni ing grup sampeyan.",
"wrong_param": "Parameter sing ora dingerteni, gunakake mung parameter aktif/mati."
}

View file

@ -0,0 +1,19 @@
{
"no_anim_stick": "Stiker animasi ora didhukung!",
"not_sticker": "Iki dudu stiker!",
"unkang_msg": "Nyoba nyopot saka pack..",
"unkang_success": "Stiker wis dibusak saka pack panjenengan",
"unkang_error": "Gagal mbusak stiker saka paket sampeyan.\n\nERR: {e}",
"unkang_help": "Mangga wangsulana stiker sing digawe {c} kanggo mbusak stiker saka paket sampeyan.",
"anon_warn": "Sampeyan anon admin, kang stiker ing pmku.",
"kang_msg": "Nyolong stiker sampeyan...",
"stick_no_name": "Stiker ora ana jeneng.",
"kang_help": "Arep tak tebak stikere? Mangga tag stiker.",
"exist_pack": "<code>Nganggo paket stiker sing ana...</code>",
"new_packs": "<b>Nggawe pak stiker anyar...</b>",
"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",
"kang_success": "<b>Stiker kasil dicolong!</b>\n<b>Emoji:</b> {emot}"
}

View file

@ -0,0 +1 @@
{}

5
locales/id-JW/webss.json Normal file
View file

@ -0,0 +1,5 @@
{
"no_url": "Wenehana url kanggo njupuk screenshot.",
"wait_str": "Lagi njupuk gambar layar...",
"ss_failed_str": "Gagal njupuk gambar. ERROR: {err}"
}

View file

@ -10,11 +10,11 @@ from pyrogram import Client
from misskaty.vars import API_HASH, API_ID, BOT_TOKEN, DATABASE_URI, USER_SESSION, TZ from misskaty.vars import API_HASH, API_ID, BOT_TOKEN, DATABASE_URI, USER_SESSION, TZ
basicConfig(filename="MissKatyLogs.txt", format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=INFO) basicConfig(filename="MissKatyLogs.txt", format="%(asctime)s - %(name)s.%(funcName)s - %(levelname)s - %(message)s", level=INFO)
logger = getLogger() logger = getLogger()
# handler logging dengan batasan 100 baris # handler logging dengan batasan 100 baris
handler = handlers.RotatingFileHandler("MissKatyLogs.txt", maxBytes=1024*1024) handler = handlers.RotatingFileHandler("MissKatyLogs.txt", maxBytes=1024 * 1024)
handler.setLevel(INFO) handler.setLevel(INFO)
logger.addHandler(handler) logger.addHandler(handler)
getLogger("pyrogram").setLevel(ERROR) getLogger("pyrogram").setLevel(ERROR)
@ -41,15 +41,9 @@ user = Client(
pymonclient = MongoClient(DATABASE_URI) pymonclient = MongoClient(DATABASE_URI)
jobstores = { jobstores = {"default": MongoDBJobStore(client=pymonclient, database="MissKatyDB", collection="nightmode")}
'default': MongoDBJobStore(
client=pymonclient,
database="MissKatyDB",
collection='nightmode')}
scheduler = AsyncIOScheduler( scheduler = AsyncIOScheduler(jobstores=jobstores, timezone=TZ)
jobstores=jobstores,
timezone=TZ)
app.start() app.start()
user.start() user.start()

View file

@ -148,7 +148,7 @@ async def start(_, message):
) )
return await message.reply_photo( return await message.reply_photo(
photo="https://telegra.ph/file/90e9a448bc2f8b055b762.jpg", photo="https://telegra.ph/file/90e9a448bc2f8b055b762.jpg",
caption=f"Hi {nama}, Pm Me For More Info About Me.", caption=f"Hi {nama}, PM me to know about all my features. You can change bot language in bot using <code>/setlang</code> command but it's in beta stage.",
reply_markup=keyboard, reply_markup=keyboard,
) )
if not await db.is_user_exist(message.from_user.id): if not await db.is_user_exist(message.from_user.id):
@ -273,7 +273,7 @@ async def help_parser(name, keyboard=None):
keyboard = InlineKeyboardMarkup(paginate_modules(0, HELPABLE, "help")) keyboard = InlineKeyboardMarkup(paginate_modules(0, HELPABLE, "help"))
return ( return (
"""Hello {first_name}, My name is {bot_name}. """Hello {first_name}, My name is {bot_name}.
I'm a bot with some useful features. I'm a bot with some useful features. You can change language bot using <code>/setlang</code> command, but it's in beta stage.
You can choose an option below, by clicking a button. 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. If you want give coffee to my owner you can send /donate command for more info.
@ -302,6 +302,7 @@ You can choose an option below, by clicking a button below.
General command are: General command are:
- /start: Start the bot - /start: Start the bot
- /help: Give this message - /help: Give this message
- /setlang: Change bot language [BETA]
""" """
if mod_match: if mod_match:
module = mod_match[1].replace(" ", "_") module = mod_match[1].replace(" ", "_")

View file

@ -1,10 +1,13 @@
from functools import wraps
from time import time from time import time
from functools import partial, wraps
from typing import Union, Optional
from traceback import format_exc as err from traceback import format_exc as err
from pyrogram import enums from pyrogram import enums, Client
from pyrogram.errors.exceptions.forbidden_403 import ChatWriteForbidden from pyrogram.errors.exceptions.forbidden_403 import ChatWriteForbidden
from pyrogram.types import Message from ...helper.localization import default_language, get_lang, get_locale_string, langdict
from pyrogram.types import Message, CallbackQuery
from misskaty import app from misskaty import app
from misskaty.vars import SUDO from misskaty.vars import SUDO
@ -37,6 +40,43 @@ async def member_permissions(chat_id: int, user_id: int):
return perms 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
admins_in_chat = {} admins_in_chat = {}
@ -107,3 +147,44 @@ def adminsOnly(permission):
return subFunc2 return subFunc2
return subFunc return subFunc
def require_admin(
permissions: Union[list, str] = None,
allow_in_private: bool = False,
complain_missing_perms: bool = True,
):
def decorator(func):
@wraps(func)
async def wrapper(client: Client, message: Union[CallbackQuery, Message], *args, **kwargs):
lang = await get_lang(message)
strings = partial(
get_locale_string,
langdict[lang].get("admins", langdict[default_language]["admins"]),
lang,
"admins",
)
if isinstance(message, CallbackQuery):
sender = partial(message.answer, show_alert=True)
msg = message.message
elif isinstance(message, Message):
sender = message.reply_text
msg = message
else:
raise NotImplementedError(f"require_admin can't process updates with the type '{message.__name__}' yet.")
# We don't actually check private and channel chats.
if msg.chat.type == enums.ChatType.PRIVATE:
if allow_in_private:
return await func(client, message, *args, *kwargs)
return await sender(strings("private_not_allowed"))
if msg.chat.type == enums.ChatType.CHANNEL:
return await func(client, message, *args, *kwargs)
has_perms = await check_perms(message, permissions, complain_missing_perms, strings)
if has_perms:
return await func(client, message, *args, *kwargs)
return wrapper
return decorator

View file

@ -10,6 +10,7 @@ ratelimit = RateLimiter()
warned_users = TTLCache(maxsize=128, ttl=60) warned_users = TTLCache(maxsize=128, ttl=60)
warning_message = "Spam detected! ignoring your all requests for few minutes." warning_message = "Spam detected! ignoring your all requests for few minutes."
def ratelimiter(func: Callable) -> Callable: def ratelimiter(func: Callable) -> Callable:
""" """
Restricts user's from spamming commands or pressing buttons multiple times Restricts user's from spamming commands or pressing buttons multiple times
@ -22,7 +23,6 @@ def ratelimiter(func: Callable) -> Callable:
is_limited = await ratelimit.acquire(userid) is_limited = await ratelimit.acquire(userid)
if is_limited and userid not in warned_users: if is_limited and userid not in warned_users:
if isinstance(update, Message): if isinstance(update, Message):
await update.reply_text(warning_message) await update.reply_text(warning_message)
warned_users[userid] = 1 warned_users[userid] = 1
@ -38,4 +38,4 @@ def ratelimiter(func: Callable) -> Callable:
else: else:
return await func(client, update) return await func(client, update)
return decorator return decorator

View file

@ -1,7 +1,6 @@
from typing import Union from typing import Union
from pyrate_limiter import (BucketFullException, Duration, Limiter, from pyrate_limiter import BucketFullException, Duration, Limiter, MemoryListBucket, RequestRate
MemoryListBucket, RequestRate)
class RateLimiter: class RateLimiter:
@ -12,7 +11,6 @@ class RateLimiter:
""" """
def __init__(self) -> None: def __init__(self) -> None:
# 2 requests per seconds # 2 requests per seconds
self.second_rate = RequestRate(2, Duration.SECOND) self.second_rate = RequestRate(2, Duration.SECOND)
@ -42,4 +40,4 @@ class RateLimiter:
self.limiter.try_acquire(userid) self.limiter.try_acquire(userid)
return False return False
except BucketFullException: except BucketFullException:
return True return True

View file

@ -12,4 +12,4 @@ from .time_gap import *
from .ssgen_helper import * from .ssgen_helper import *
from .tools import * from .tools import *
from .ytdl_helper import * from .ytdl_helper import *
from .subscene_helper import * from .subscene_helper import *

View file

@ -35,9 +35,9 @@ def get_readable_time(seconds: int) -> str:
def get_readable_bitrate(bitrate_kbps): def get_readable_bitrate(bitrate_kbps):
if bitrate_kbps > 10000: if bitrate_kbps > 10000:
bitrate = str(round(bitrate_kbps / 1000, 2)) + ' ' + 'Mb/s' bitrate = str(round(bitrate_kbps / 1000, 2)) + " " + "Mb/s"
else: else:
bitrate = str(round(bitrate_kbps, 2)) + ' ' + 'kb/s' bitrate = str(round(bitrate_kbps, 2)) + " " + "kb/s"
return bitrate return bitrate

View file

@ -0,0 +1,124 @@
import inspect
import json
import os.path
from functools import partial, wraps
from glob import glob
from typing import Dict, List
from pyrogram.enums import ChatType
from pyrogram.types import CallbackQuery, InlineQuery, Message
from database.locale_db import get_db_lang
enabled_locales: List[str] = [
# "en-GB", # English (United Kingdom)
"en-US", # English (United States)
# "pt-BR", # Portuguese (Brazil)
# "es-ES", # Spanish
# "fr-FR", # French
# "de-DE", # German
# "it-IT", # Italian
# "nl-NL", # Dutch
# "ar-SA", # Arabic
# "ckb-IR", # Sorani (Kurdish)
# "fi-FI", # Finnish
# "he-IL", # Hebrew
"id-ID", # Indonesian
"id-JW", # Javanese
# "ja-JP", # Japanese
# "no-NO", # Norwegian
# "pl-PL", # Polish
# "pt-BRe", # Portuguese (Brazil, extended version)
# "pt-BR2", # Portuguese (Brazil, informal version)
# "ro-RO", # Romanian
# "ru-RU", # Russian
# "sv-SE", # Swedish
# "tr-TR", # Turkish
# "uk-UA", # Ukranian
# "zh-CN", # Chinese (Simplified)
# "zh-TW", # Chinese (Traditional)
]
default_language: str = "en-US"
def cache_localizations(files: List[str]) -> Dict[str, Dict[str, Dict[str, str]]]:
ldict = {lang: {} for lang in enabled_locales}
for file in files:
_, lname, pname = file.split(os.path.sep)
pname = pname.split(".")[0]
dic = json.load(open(file, encoding="utf-8"))
dic.update(ldict[lname].get(pname, {}))
ldict[lname][pname] = dic
return ldict
jsons: List[str] = []
for locale in enabled_locales:
jsons += glob(os.path.join("locales", locale, "*.json"))
langdict = cache_localizations(jsons)
def get_locale_string(dic: dict, language: str, default_context: str, key: str, context: str = None) -> str:
if context:
default_context = context
dic = langdict[language].get(context, langdict[default_language][context])
res: str = dic.get(key) or langdict[default_language][default_context].get(key) or key
return res
async def get_lang(message) -> str:
if isinstance(message, CallbackQuery):
chat = message.message.chat
elif isinstance(message, Message):
chat = message.chat
elif isinstance(message, InlineQuery):
chat, chat.type = message.from_user, ChatType.PRIVATE
else:
raise TypeError(f"Update type '{message.__name__}' is not supported.")
lang = await get_db_lang(chat.id, chat.type)
if chat.type == ChatType.PRIVATE:
lang = lang or message.from_user.language_code or default_language
else:
lang = lang or default_language
# User has a language_code without hyphen
if len(lang.split("-")) == 1:
# Try to find a language that starts with the provided language_code
for locale_ in enabled_locales:
if locale_.startswith(lang):
lang = locale_
elif lang.split("-")[1].islower():
lang = lang.split("-")
lang[1] = lang[1].upper()
lang = "-".join(lang)
return lang if lang in enabled_locales else default_language
def use_chat_lang(context: str = None):
if not context:
cwd = os.getcwd()
frame = inspect.stack()[1]
fname = frame.filename
if fname.startswith(cwd):
fname = fname[len(cwd) + 1 :]
context = fname.split(os.path.sep)[2].split(".")[0]
def decorator(func):
@wraps(func)
async def wrapper(client, message):
lang = await get_lang(message)
dic = langdict.get(lang, langdict[default_language])
lfunc = partial(get_locale_string, dic.get(context, {}), lang, context)
return await func(client, message, lfunc)
return wrapper
return decorator

View file

@ -168,37 +168,25 @@ def html_builder(title: str, text: str) -> str:
if "Text #" in line: if "Text #" in line:
if bool(re.search("Text #1$", line)): if bool(re.search("Text #1$", line)):
subtitle_count = len(re.findall("Text #", text)) subtitle_count = len(re.findall("Text #", text))
html_msg += icon.format( html_msg += icon.format(icon_url="https://te.legra.ph/file/9d4a676445544d0f2d6db.png")
icon_url="https://te.legra.ph/file/9d4a676445544d0f2d6db.png" html_msg += subheading.format(content=f"Subtitles ({subtitle_count} subtitle)")
)
html_msg += subheading.format(
content=f"Subtitles ({subtitle_count} subtitle)"
)
html_msg += "<span style='padding: 10px 0vw;' class='subtitle'>" html_msg += "<span style='padding: 10px 0vw;' class='subtitle'>"
elif "General" in line: elif "General" in line:
html_msg += icon.format( html_msg += icon.format(icon_url="https://te.legra.ph/file/638fb0416f2600e7c5aa3.png")
icon_url="https://te.legra.ph/file/638fb0416f2600e7c5aa3.png"
)
html_msg += subheading.format(content="General") html_msg += subheading.format(content="General")
elif "Video" in line: elif "Video" in line:
html_msg += icon.format( html_msg += icon.format(icon_url="https://te.legra.ph/file/fbc30d71cf71c9a54e59d.png")
icon_url="https://te.legra.ph/file/fbc30d71cf71c9a54e59d.png"
)
html_msg += subheading.format(content="Video") html_msg += subheading.format(content="Video")
elif "Audio" in line: elif "Audio" in line:
html_msg += icon.format( html_msg += icon.format(icon_url="https://te.legra.ph/file/a3c431be457fedbae2286.png")
icon_url="https://te.legra.ph/file/a3c431be457fedbae2286.png"
)
html_msg += subheading.format(content=f"{line.strip()}") html_msg += subheading.format(content=f"{line.strip()}")
elif "Menu" in line: elif "Menu" in line:
html_msg += "</span>" html_msg += "</span>"
html_msg += icon.format( html_msg += icon.format(icon_url="https://te.legra.ph/file/3023b0c2bc202ec9d6d0d.png")
icon_url="https://te.legra.ph/file/3023b0c2bc202ec9d6d0d.png"
)
html_msg += subheading.format(content="Chapters") html_msg += subheading.format(content="Chapters")
else: else:
@ -224,4 +212,4 @@ async def mediainfo_paste(text: str, title: str) -> str:
html_content = html_builder(title, text) html_content = html_builder(title, text)
URL = "https://mediainfo-1-y5870653.deta.app/api" URL = "https://mediainfo-1-y5870653.deta.app/api"
response = await http.post(URL, json={"content": html_content}) response = await http.post(URL, json={"content": html_content})
return f"https://mediainfo-1-y5870653.deta.app/{json.loads(response.content)['key']}" return f"https://mediainfo-1-y5870653.deta.app/{json.loads(response.content)['key']}"

View file

@ -1,43 +1,42 @@
import cfscrape import cfscrape
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
async def down_page(url): async def down_page(url):
f = cfscrape.create_scraper() f = cfscrape.create_scraper()
resp = f.get(url).text resp = f.get(url).text
soup = BeautifulSoup(resp, 'lxml') soup = BeautifulSoup(resp, "lxml")
maindiv = soup.body.find('div', class_='subtitle').find('div', class_='top left') maindiv = soup.body.find("div", class_="subtitle").find("div", class_="top left")
title = maindiv.find('div', class_='header').h1.span.text.strip() title = maindiv.find("div", class_="header").h1.span.text.strip()
try: try:
imdb = maindiv.find('div', class_='header').h1.a['href'] imdb = maindiv.find("div", class_="header").h1.a["href"]
except TypeError: except TypeError:
imdb = "" imdb = ""
try: try:
poster = maindiv.find('div', class_='poster').a['href'] poster = maindiv.find("div", class_="poster").a["href"]
except: except:
poster = "" poster = ""
try: try:
author_name = maindiv.find('div', class_='header').ul.find('li', class_='author').a.text.strip() author_name = maindiv.find("div", class_="header").ul.find("li", class_="author").a.text.strip()
author_link = f"https://subscene.com{maindiv.find('div', class_='header').ul.find('li', class_='author').a['href']}" author_link = f"https://subscene.com{maindiv.find('div', class_='header').ul.find('li', class_='author').a['href']}"
except: except:
author_link = "" author_link = ""
author_name = "Anonymous" author_name = "Anonymous"
download_url = f"https://subscene.com{maindiv.find('div', class_='header').ul.find('li', class_='clearfix').find('div', class_='download').a['href']}" download_url = f"https://subscene.com{maindiv.find('div', class_='header').ul.find('li', class_='clearfix').find('div', class_='download').a['href']}"
try: try:
comments = maindiv.find('div', class_='header').ul.find('li', class_='comment-wrapper').find('div', comments = maindiv.find("div", class_="header").ul.find("li", class_="comment-wrapper").find("div", class_="comment").text
class_='comment').text except:
except: comments = ""
comments = "" try:
try: release = maindiv.find("div", class_="header").ul.find("li", class_="release").find_all("div")
release = maindiv.find('div', class_='header').ul.find('li', class_='release').find_all('div') releases = ""
releases = "" for i in range(2):
for i in range(2): r = release[i].text.strip()
r = release[i].text.strip() releases = releases + f"\n{r}"
releases = releases + f"\n{r}" except Exception:
except Exception as e: releases = ""
releases = ""
response = {"title": title, "imdb": imdb, "poster": poster, "author_name": author_name, response = {"title": title, "imdb": imdb, "poster": poster, "author_name": author_name, "author_url": author_link, "download_url": download_url, "comments": comments, "releases": releases}
"author_url": author_link, "download_url": download_url, "comments": comments, "releases": releases} return response
return response

View file

@ -140,6 +140,4 @@ async def search_jw(movie_name: str, locale: str):
return m_t_ return m_t_
SUPPORTED_URL_REGEX = { SUPPORTED_URL_REGEX = {r"(http|ftp|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])": "ddl"}
r"(http|ftp|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])": "ddl"
}

View file

@ -13,12 +13,14 @@ from misskaty.core.decorator.errors import capture_err
from misskaty.core.decorator.permissions import ( from misskaty.core.decorator.permissions import (
admins_in_chat, admins_in_chat,
adminsOnly, adminsOnly,
require_admin,
list_admins, list_admins,
member_permissions, member_permissions,
) )
from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.decorator.ratelimiter import ratelimiter
from misskaty.core.keyboard import ikb from misskaty.core.keyboard import ikb
from misskaty.core.message_utils import kirimPesan from misskaty.core.message_utils import kirimPesan
from misskaty.helper.localization import use_chat_lang
from misskaty.helper.functions import ( from misskaty.helper.functions import (
extract_user, extract_user,
extract_user_and_reason, extract_user_and_reason,
@ -74,9 +76,10 @@ async def admin_cache_func(_, cmu):
# Purge CMD # Purge CMD
@app.on_message(filters.command("purge", COMMAND_HANDLER) & filters.group) @app.on_message(filters.command("purge", COMMAND_HANDLER) & filters.group)
@adminsOnly("can_delete_messages") @require_admin(permissions=["can_delete_messages"], allow_in_private=True)
@ratelimiter @ratelimiter
async def purge(_, message): @use_chat_lang()
async def purge(_, message, strings):
if not message.from_user: if not message.from_user:
return return
try: try:
@ -84,7 +87,7 @@ async def purge(_, message):
await message.delete() await message.delete()
if not repliedmsg: if not repliedmsg:
return await message.reply_text("Reply to a message to purge from.") return await message.reply_text(strings("purge_no_reply"))
cmd = message.command cmd = message.command
if len(cmd) > 1 and cmd[1].isdigit(): if len(cmd) > 1 and cmd[1].isdigit():
@ -122,32 +125,30 @@ async def purge(_, message):
revoke=True, revoke=True,
) )
del_total += len(message_ids) del_total += len(message_ids)
await kirimPesan(message, f"Successfully deleted {del_total} messages..") await kirimPesan(message, strings("purge_success").format(del_total=del_total))
except Exception as err: except Exception as err:
await kirimPesan(message, f"ERR: {err}") await kirimPesan(message, f"ERROR: {err}")
# Kick members # Kick members
@app.on_message(filters.command(["kick", "dkick"], COMMAND_HANDLER) & filters.group) @app.on_message(filters.command(["kick", "dkick"], COMMAND_HANDLER) & filters.group)
@adminsOnly("can_restrict_members") @adminsOnly("can_restrict_members")
@ratelimiter @ratelimiter
async def kickFunc(client, message): @use_chat_lang()
async def kickFunc(client, message, strings):
if not message.from_user: if not message.from_user:
return return
user_id, reason = await extract_user_and_reason(message) user_id, reason = await extract_user_and_reason(message)
if not user_id: if not user_id:
return await kirimPesan(message, "I can't find that user.") return await kirimPesan(message, strings("user_not_found"))
if user_id == client.me.id: if user_id == client.me.id:
return await kirimPesan(message, "I can't kick myself, i can leave if you want.") return await kirimPesan(message, strings("kick_self_err"))
if user_id in SUDO: if user_id in SUDO:
return await kirimPesan(message, "Wow, you wanna kick my owner?") return await kirimPesan(message, strings("kick_sudo_err"))
if user_id in (await list_admins(message.chat.id)): if user_id in (await list_admins(message.chat.id)):
return await kirimPesan(message, "Lol, it's crazy if i can kick an admin.") return await kirimPesan(message, strings("kick_admin_err"))
user = await app.get_users(user_id) user = await app.get_users(user_id)
msg = f""" msg = strings("kick_msg").format(mention=user.mention, id=user.id, kicker=message.from_user.mention if message.from_user else "Anon Admin", reasonmsg=reason or "-")
**Kicked User:** {user.mention} [{user.id}]
**Kicked By:** {message.from_user.mention if message.from_user else 'Anon'}
**Reason:** {reason or '-'}"""
if message.command[0][0] == "d": if message.command[0][0] == "d":
await message.reply_to_message.delete() await message.reply_to_message.delete()
try: try:
@ -156,33 +157,34 @@ async def kickFunc(client, message):
await asyncio.sleep(1) await asyncio.sleep(1)
await message.chat.unban_member(user_id) await message.chat.unban_member(user_id)
except ChatAdminRequired: except ChatAdminRequired:
await kirimPesan(message, "Please give me ban permission to ban user in this group.") await kirimPesan(message, strings("no_ban_permission"))
# Ban/DBan/TBan User # Ban/DBan/TBan User
@app.on_message(filters.command(["ban", "dban", "tban"], COMMAND_HANDLER) & filters.group) @app.on_message(filters.command(["ban", "dban", "tban"], COMMAND_HANDLER) & filters.group)
@adminsOnly("can_restrict_members") @adminsOnly("can_restrict_members")
@ratelimiter @ratelimiter
async def banFunc(client, message): @use_chat_lang()
async def banFunc(client, message, strings):
if not message.from_user: if not message.from_user:
return return
user_id, reason = await extract_user_and_reason(message, sender_chat=True) user_id, reason = await extract_user_and_reason(message, sender_chat=True)
if not user_id: if not user_id:
return await message.reply_text("I can't find that user.") return await message.reply_text(strings("user_not_found"))
if user_id == client.me.id: if user_id == client.me.id:
return await message.reply_text("I can't ban myself, i can leave if you want.") return await message.reply_text(strings("ban_self_err"))
if user_id in SUDO: if user_id in SUDO:
return await message.reply_text("You Wanna Ban The Elevated One?, RECONSIDER!") return await message.reply_text(strings("ban_sudo_err"))
if user_id in (await list_admins(message.chat.id)): if user_id in (await list_admins(message.chat.id)):
return await message.reply_text("I can't ban an admin, You know the rules, so do i.") return await message.reply_text(strings("ban_admin_err"))
try: try:
mention = (await app.get_users(user_id)).mention mention = (await app.get_users(user_id)).mention
except IndexError: except IndexError:
mention = message.reply_to_message.sender_chat.title if message.reply_to_message else "Anon" mention = message.reply_to_message.sender_chat.title if message.reply_to_message else "Anon"
msg = f"**Banned User:** {mention}\n" f"**Banned By:** {message.from_user.mention if message.from_user else 'Anon'}\n" msg = strings("ban_msg").format(mention=mention, id=user_id, banner=message.from_user.mention if message.from_user else "Anon")
if message.command[0][0] == "d": if message.command[0][0] == "d":
await message.reply_to_message.delete() await message.reply_to_message.delete()
if message.command[0] == "tban": if message.command[0] == "tban":
@ -190,20 +192,20 @@ async def banFunc(client, message):
time_value = split[0] time_value = split[0]
temp_reason = split[1] if len(split) > 1 else "" temp_reason = split[1] if len(split) > 1 else ""
temp_ban = await time_converter(message, time_value) temp_ban = await time_converter(message, time_value)
msg += f"**Banned For:** {time_value}\n" msg += strings("banner_time").format(val=time_value)
if temp_reason: if temp_reason:
msg += f"**Reason:** {temp_reason}" msg += strings("banned_reason").format(reas=temp_reason)
try: try:
if len(time_value[:-1]) < 3: if len(time_value[:-1]) < 3:
await message.chat.ban_member(user_id, until_date=temp_ban) await message.chat.ban_member(user_id, until_date=temp_ban)
await message.reply_text(msg) await message.reply_text(msg)
else: else:
await message.reply_text("You can't use more than 99") await message.reply_text(strings("no_more_99"))
except AttributeError: except AttributeError:
pass pass
return return
if reason: if reason:
msg += f"**Reason:** {reason}" msg += strings("banned_reason").format(reas=reason)
keyboard = ikb({"🚨 Unban 🚨": f"unban_{user_id}"}) keyboard = ikb({"🚨 Unban 🚨": f"unban_{user_id}"})
try: try:
await message.chat.ban_member(user_id) await message.chat.ban_member(user_id)
@ -216,7 +218,8 @@ async def banFunc(client, message):
@app.on_message(filters.command("unban", COMMAND_HANDLER) & filters.group) @app.on_message(filters.command("unban", COMMAND_HANDLER) & filters.group)
@adminsOnly("can_restrict_members") @adminsOnly("can_restrict_members")
@ratelimiter @ratelimiter
async def unban_func(_, message): @use_chat_lang()
async def unban_func(_, message, strings):
if not message.from_user: if not message.from_user:
return return
# we don't need reasons for unban, also, we # we don't need reasons for unban, also, we
@ -226,49 +229,50 @@ async def unban_func(_, message):
reply = message.reply_to_message reply = message.reply_to_message
if reply and reply.sender_chat and reply.sender_chat != message.chat.id: if reply and reply.sender_chat and reply.sender_chat != message.chat.id:
return await message.reply_text("You cannot unban a channel") return await message.reply_text(strings("unban_channel_err"))
if len(message.command) == 2: if len(message.command) == 2:
user = message.text.split(None, 1)[1] user = message.text.split(None, 1)[1]
elif len(message.command) == 1 and reply: elif len(message.command) == 1 and reply:
user = message.reply_to_message.from_user.id user = message.reply_to_message.from_user.id
else: else:
return await message.reply_text("Provide a username or reply to a user's message to unban.") return await message.reply_text(strings("give_unban_user"))
await message.chat.unban_member(user) await message.chat.unban_member(user)
umention = (await app.get_users(user)).mention umention = (await app.get_users(user)).mention
await message.reply_text(f"Unbanned! {umention}") await message.reply_text(strings("unban_success").format(umention=umention))
# Ban users listed in a message # Ban users listed in a message
@app.on_message(filters.user(SUDO) & filters.command("listban", COMMAND_HANDLER) & filters.group) @app.on_message(filters.user(SUDO) & filters.command("listban", COMMAND_HANDLER) & filters.group)
@ratelimiter @ratelimiter
async def list_ban_(c, message): @use_chat_lang()
async def list_ban_(c, message, strings):
if not message.from_user: if not message.from_user:
return return
userid, msglink_reason = await extract_user_and_reason(message) userid, msglink_reason = await extract_user_and_reason(message)
if not userid or not msglink_reason: if not userid or not msglink_reason:
return await message.reply_text("Provide a userid/username along with message link and reason to list-ban") return await message.reply_text(strings("give_idban_with_msg_link"))
if len(msglink_reason.split(" ")) == 1: # message link included with the reason if len(msglink_reason.split(" ")) == 1: # message link included with the reason
return await message.reply_text("You must provide a reason to list-ban") return await message.reply_text(strings("give_reason_list_ban"))
# seperate messge link from reason # seperate messge link from reason
lreason = msglink_reason.split() lreason = msglink_reason.split()
messagelink, reason = lreason[0], " ".join(lreason[1:]) messagelink, reason = lreason[0], " ".join(lreason[1:])
if not re.search(r"(https?://)?t(elegram)?\.me/\w+/\d+", messagelink): # validate link if not re.search(r"(https?://)?t(elegram)?\.me/\w+/\d+", messagelink): # validate link
return await message.reply_text("Invalid message link provided") return await message.reply_text(strings("invalid_tg_link"))
if userid == c.me.id: if userid == c.me.id:
return await message.reply_text("I can't ban myself.") return await message.reply_text(strings("ban_self_err"))
if userid in SUDO: if userid in SUDO:
return await message.reply_text("You Wanna Ban The Elevated One?, RECONSIDER!") return await message.reply_text(strings("ban_sudo_err"))
splitted = messagelink.split("/") splitted = messagelink.split("/")
uname, mid = splitted[-2], int(splitted[-1]) uname, mid = splitted[-2], int(splitted[-1])
m = await message.reply_text("`Banning User from multiple groups. This may take some time`") m = await message.reply_text(strings("multiple_ban_progress"))
try: try:
msgtext = (await app.get_messages(uname, mid)).text msgtext = (await app.get_messages(uname, mid)).text
gusernames = re.findall(r"@\w+", msgtext) gusernames = re.findall(r"@\w+", msgtext)
except: except:
return await m.edit_text("Could not get group usernames") return await m.edit_text(strings("failed_get_uname"))
count = 0 count = 0
for username in gusernames: for username in gusernames:
try: try:
@ -281,40 +285,32 @@ async def list_ban_(c, message):
count += 1 count += 1
mention = (await app.get_users(userid)).mention mention = (await app.get_users(userid)).mention
msg = f""" msg = strings("listban_msg").format(mention=mention, uid=userid, frus=message.from_user.mention, ct=count, reas=reason)
**List-Banned User:** {mention}
**Banned User ID:** `{userid}`
**Admin:** {message.from_user.mention}
**Affected chats:** `{count}`
**Reason:** {reason}
"""
await m.edit_text(msg) await m.edit_text(msg)
# Unban users listed in a message # Unban users listed in a message
@app.on_message(filters.user(SUDO) & filters.command("listunban", COMMAND_HANDLER) & filters.group) @app.on_message(filters.user(SUDO) & filters.command("listunban", COMMAND_HANDLER) & filters.group)
@ratelimiter @ratelimiter
async def list_unban_(c, message): @use_chat_lang()
async def list_unban_(c, message, strings):
if not message.from_user: if not message.from_user:
return return
userid, msglink = await extract_user_and_reason(message) userid, msglink = await extract_user_and_reason(message)
if not userid or not msglink: if not userid or not msglink:
return await message.reply_text("Provide a userid/username along with message link to list-unban") return await message.reply_text(strings("give_idunban_with_msg_link"))
if not re.search(r"(https?://)?t(elegram)?\.me/\w+/\d+", msglink): # validate link if not re.search(r"(https?://)?t(elegram)?\.me/\w+/\d+", msglink): # validate link
return await message.reply_text("Invalid message link provided") return await message.reply_text(strings("invalid_tg_link"))
splitted = msglink.split("/") splitted = msglink.split("/")
uname, mid = splitted[-2], int(splitted[-1]) uname, mid = splitted[-2], int(splitted[-1])
m = await message.reply_text( m = await message.reply_text(strings("multiple_unban_progress"))
"`Unbanning User from multiple groups. \
This may take some time`"
)
try: try:
msgtext = (await app.get_messages(uname, mid)).text msgtext = (await app.get_messages(uname, mid)).text
gusernames = re.findall(r"@\w+", msgtext) gusernames = re.findall(r"@\w+", msgtext)
except: except:
return await m.edit_text("Could not get the group usernames") return await m.edit_text(strings("failed_get_uname"))
count = 0 count = 0
for username in gusernames: for username in gusernames:
try: try:
@ -326,12 +322,7 @@ async def list_unban_(c, message):
continue continue
count += 1 count += 1
mention = (await app.get_users(userid)).mention mention = (await app.get_users(userid)).mention
msg = f""" msg = strings("listunban_msg").format(mention=mention, uid=userid, frus=message.from_user.mention, ct=count)
**List-Unbanned User:** {mention}
**Unbanned User ID:** `{userid}`
**Admin:** {message.from_user.mention}
**Affected chats:** `{count}`
"""
await m.edit_text(msg) await m.edit_text(msg)
@ -339,37 +330,39 @@ async def list_unban_(c, message):
@app.on_message(filters.command("del", COMMAND_HANDLER) & filters.group) @app.on_message(filters.command("del", COMMAND_HANDLER) & filters.group)
@adminsOnly("can_delete_messages") @adminsOnly("can_delete_messages")
@ratelimiter @ratelimiter
async def deleteFunc(_, message): @use_chat_lang()
async def deleteFunc(_, message, strings):
if not message.from_user: if not message.from_user:
return return
if not message.reply_to_message: if not message.reply_to_message:
return await message.reply_text("Reply To A Message To Delete It") return await message.reply_text(strings("delete_no_reply"))
try: try:
await message.reply_to_message.delete() await message.reply_to_message.delete()
await message.delete() await message.delete()
except: except:
await message.reply("Please give me delete message permission.") await message.reply(strings("no_delete_perm"))
# Promote Members # Promote Members
@app.on_message(filters.command(["promote", "fullpromote"], COMMAND_HANDLER) & filters.group) @app.on_message(filters.command(["promote", "fullpromote"], COMMAND_HANDLER) & filters.group)
@adminsOnly("can_promote_members") @adminsOnly("can_promote_members")
@ratelimiter @ratelimiter
async def promoteFunc(client, message): @use_chat_lang()
async def promoteFunc(client, message, strings):
if not message.from_user: if not message.from_user:
return return
try: try:
user_id = await extract_user(message) user_id = await extract_user(message)
umention = (await app.get_users(user_id)).mention umention = (await app.get_users(user_id)).mention
except: except:
return await message.reply("⚠️ Invalid userid/username") return await message.reply(strings("invalid_id_uname"))
if not user_id: if not user_id:
return await message.reply_text("I can't find that user.") return await message.reply_text(strings("user_not_found"))
bot = await app.get_chat_member(message.chat.id, client.me.id) bot = await app.get_chat_member(message.chat.id, client.me.id)
if user_id == client.me.id: if user_id == client.me.id:
return await message.reply_text("I can't promote myself.") return await message.reply_text(strings("promote_self_err"))
if not bot.privileges.can_promote_members: if not bot.privileges.can_promote_members:
return await message.reply_text("I don't have enough permissions") return await message.reply_text(strings("no_promote_perm"))
if message.command[0][0] == "f": if message.command[0][0] == "f":
await message.chat.promote_member( await message.chat.promote_member(
user_id, user_id,
@ -381,10 +374,10 @@ async def promoteFunc(client, message):
can_pin_messages=bot.can_pin_messages, can_pin_messages=bot.can_pin_messages,
can_promote_members=bot.can_promote_members, can_promote_members=bot.can_promote_members,
can_manage_chat=bot.can_manage_chat, can_manage_chat=bot.can_manage_chat,
can_manage_voice_chats=bot.can_manage_voice_chats can_manage_voice_chats=bot.can_manage_voice_chats,
) ),
) )
return await message.reply_text(f"Fully Promoted! {umention}") return await message.reply_text(strings("full_promote").format(umention=umention))
await message.chat.promote_member( await message.chat.promote_member(
user_id, user_id,
@ -396,29 +389,28 @@ async def promoteFunc(client, message):
can_pin_messages=False, can_pin_messages=False,
can_promote_members=False, can_promote_members=False,
can_manage_chat=bot.can_manage_chat, can_manage_chat=bot.can_manage_chat,
can_manage_voice_chats=bot.can_manage_voice_chats can_manage_voice_chats=bot.can_manage_voice_chats,
) ),
) )
await message.reply_text(f"Promoted! {umention}") await message.reply_text(strings("normal_promote").format(umention=umention))
# Demote Member # Demote Member
@app.on_message(filters.command("demote", COMMAND_HANDLER) & filters.group) @app.on_message(filters.command("demote", COMMAND_HANDLER) & filters.group)
@adminsOnly("can_restrict_members") @adminsOnly("can_restrict_members")
@ratelimiter @ratelimiter
async def demote(client, message): @use_chat_lang()
async def demote(client, message, strings):
if not message.from_user: if not message.from_user:
return return
user_id = await extract_user(message) user_id = await extract_user(message)
if not user_id: if not user_id:
return await message.reply_text("I can't find that user.") return await message.reply_text(strings("user_not_found"))
if user_id == client.me.id: if user_id == client.me.id:
return await message.reply_text("I can't demote myself.") return await message.reply_text(strings("demote_self_err"))
if user_id in SUDO: if user_id in SUDO:
return await message.reply_text("You wanna demote the elevated one?") return await message.reply_text(strings("demote_sudo_err"))
await message.chat.promote_member( await message.chat.promote_member(user_id=user_id)
user_id=user_id
)
umention = (await app.get_users(user_id)).mention umention = (await app.get_users(user_id)).mention
await message.reply_text(f"Demoted! {umention}") await message.reply_text(f"Demoted! {umention}")
@ -427,27 +419,28 @@ async def demote(client, message):
@app.on_message(filters.command(["pin", "unpin"], COMMAND_HANDLER) & filters.group) @app.on_message(filters.command(["pin", "unpin"], COMMAND_HANDLER) & filters.group)
@adminsOnly("can_pin_messages") @adminsOnly("can_pin_messages")
@ratelimiter @ratelimiter
async def pin(_, message): @use_chat_lang()
async def pin(_, message, strings):
if not message.from_user: if not message.from_user:
return return
if not message.reply_to_message: if not message.reply_to_message:
return await message.reply_text("Reply to a message to pin/unpin it.") return await message.reply_text(strings("pin_no_reply"))
r = message.reply_to_message r = message.reply_to_message
try: try:
if message.command[0][0] == "u": if message.command[0][0] == "u":
await r.unpin() await r.unpin()
return await message.reply_text( return await message.reply_text(
f"**Unpinned [this]({r.link}) message.**", strings("unpin_success").format(link=r.link),
disable_web_page_preview=True, disable_web_page_preview=True,
) )
await r.pin(disable_notification=True) await r.pin(disable_notification=True)
await message.reply( await message.reply(
f"**Pinned [this]({r.link}) message.**", strings("pin_success").format(link=r.link),
disable_web_page_preview=True, disable_web_page_preview=True,
) )
except ChatAdminRequired: except ChatAdminRequired:
await message.reply( await message.reply(
"Please give me admin access to use this command.", strings("pin_no_perm"),
disable_web_page_preview=True, disable_web_page_preview=True,
) )
@ -456,7 +449,8 @@ async def pin(_, message):
@app.on_message(filters.command(["mute", "tmute"], COMMAND_HANDLER) & filters.group) @app.on_message(filters.command(["mute", "tmute"], COMMAND_HANDLER) & filters.group)
@adminsOnly("can_restrict_members") @adminsOnly("can_restrict_members")
@ratelimiter @ratelimiter
async def mute(client, message): @use_chat_lang()
async def mute(client, message, strings):
if not message.from_user: if not message.from_user:
return return
try: try:
@ -464,24 +458,24 @@ async def mute(client, message):
except Exception as err: except Exception as err:
return await message.reply(f"ERROR: {err}") return await message.reply(f"ERROR: {err}")
if not user_id: if not user_id:
return await message.reply_text("I can't find that user.") return await message.reply_text(strings("user_not_found"))
if user_id == client.me.id: if user_id == client.me.id:
return await message.reply_text("I can't mute myself.") return await message.reply_text(strings("mute_self_err"))
if user_id in SUDO: if user_id in SUDO:
return await message.reply_text("You wanna mute the elevated one?, RECONSIDER!") return await message.reply_text(strings("mute_sudo_err"))
if user_id in (await list_admins(message.chat.id)): if user_id in (await list_admins(message.chat.id)):
return await message.reply_text("I can't mute an admin, You know the rules, so do i.") return await message.reply_text(strings("mute_admin_err"))
mention = (await app.get_users(user_id)).mention mention = (await app.get_users(user_id)).mention
keyboard = ikb({"🚨 Unmute 🚨": f"unmute_{user_id}"}) keyboard = ikb({"🚨 Unmute 🚨": f"unmute_{user_id}"})
msg = f"**Muted User:** {mention}\n" f"**Muted By:** {message.from_user.mention if message.from_user else 'Anon'}\n" msg = strings("muted_msg").format(mention=mention, muter=message.from_user.mention if message.from_user else "Anon")
if message.command[0] == "tmute": if message.command[0] == "tmute":
split = reason.split(None, 1) split = reason.split(None, 1)
time_value = split[0] time_value = split[0]
temp_reason = split[1] if len(split) > 1 else "" temp_reason = split[1] if len(split) > 1 else ""
temp_mute = await time_converter(message, time_value) temp_mute = await time_converter(message, time_value)
msg += f"**Muted For:** {time_value}\n" msg += strings("muted_time").format(val=time_value)
if temp_reason: if temp_reason:
msg += f"**Reason:** {temp_reason}" msg += strings("banned_reason").format(reas=temp_reason)
try: try:
if len(time_value[:-1]) < 3: if len(time_value[:-1]) < 3:
await message.chat.restrict_member( await message.chat.restrict_member(
@ -491,12 +485,12 @@ async def mute(client, message):
) )
await message.reply_text(msg, reply_markup=keyboard) await message.reply_text(msg, reply_markup=keyboard)
else: else:
await message.reply_text("You can't use more than 99") await message.reply_text(strings("no_more_99"))
except AttributeError: except AttributeError:
pass pass
return return
if reason: if reason:
msg += f"**Reason:** {reason}" msg += strings("banned_reason").format(reas=reason)
await message.chat.restrict_member(user_id, permissions=ChatPermissions()) await message.chat.restrict_member(user_id, permissions=ChatPermissions())
await message.reply_text(msg, reply_markup=keyboard) await message.reply_text(msg, reply_markup=keyboard)
@ -505,67 +499,66 @@ async def mute(client, message):
@app.on_message(filters.command("unmute", COMMAND_HANDLER) & filters.group) @app.on_message(filters.command("unmute", COMMAND_HANDLER) & filters.group)
@adminsOnly("can_restrict_members") @adminsOnly("can_restrict_members")
@ratelimiter @ratelimiter
async def unmute(_, message): @use_chat_lang()
async def unmute(_, message, strings):
if not message.from_user: if not message.from_user:
return return
user_id = await extract_user(message) user_id = await extract_user(message)
if not user_id: if not user_id:
return await message.reply_text("I can't find that user.") return await message.reply_text(strings("user_not_found"))
await message.chat.unban_member(user_id) await message.chat.unban_member(user_id)
umention = (await app.get_users(user_id)).mention (await app.get_users(user_id)).mention
await message.reply_text(f"Unmuted! {umention}") await message.reply_text(strings("unmute_msg"))
@app.on_message(filters.command(["warn", "dwarn"], COMMAND_HANDLER) & filters.group) @app.on_message(filters.command(["warn", "dwarn"], COMMAND_HANDLER) & filters.group)
@adminsOnly("can_restrict_members") @adminsOnly("can_restrict_members")
@ratelimiter @ratelimiter
async def warn_user(client, message): @use_chat_lang()
async def warn_user(client, message, strings):
if not message.from_user: if not message.from_user:
return return
user_id, reason = await extract_user_and_reason(message) user_id, reason = await extract_user_and_reason(message)
chat_id = message.chat.id chat_id = message.chat.id
if not user_id: if not user_id:
return await message.reply_text("I can't find that user.") return await message.reply_text(strings("user_not_found"))
if user_id == client.me.id: if user_id == client.me.id:
return await message.reply_text("I can't warn myself, i can leave if you want.") return await message.reply_text(strings("warn_self_err"))
if user_id in SUDO: if user_id in SUDO:
return await message.reply_text("You Wanna Warn The Elevated One?, RECONSIDER!") return await message.reply_text(strings("warn_sudo_err"))
if user_id in (await list_admins(chat_id)): if user_id in (await list_admins(chat_id)):
return await message.reply_text("I can't warn an admin, You know the rules, so do i.") return await message.reply_text(strings("warn_admin_err"))
user, warns = await asyncio.gather( user, warns = await asyncio.gather(
app.get_users(user_id), app.get_users(user_id),
get_warn(chat_id, await int_to_alpha(user_id)), get_warn(chat_id, await int_to_alpha(user_id)),
) )
mention = user.mention mention = user.mention
keyboard = ikb({"🚨 Remove Warn 🚨": f"unwarn_{user_id}"}) keyboard = ikb({strings("rmwarn_btn"): f"unwarn_{user_id}"})
warns = warns["warns"] if warns else 0 warns = warns["warns"] if warns else 0
if message.command[0][0] == "d": if message.command[0][0] == "d":
await message.reply_to_message.delete() await message.reply_to_message.delete()
if warns >= 2: if warns >= 2:
await message.chat.ban_member(user_id) await message.chat.ban_member(user_id)
await message.reply_text(f"Number of warns of {mention} exceeded, BANNED!") await message.reply_text(strings("exceed_warn_msg").format(mention=mention))
await remove_warns(chat_id, await int_to_alpha(user_id)) await remove_warns(chat_id, await int_to_alpha(user_id))
else: else:
warn = {"warns": warns + 1} warn = {"warns": warns + 1}
msg = f""" msg = strings("warn_msg").format(mention=mention, warner=message.from_user.mention if message.from_user else "Anon", reas=reason or "No Reason Provided.", twarn=warns + 1)
**Warned User:** {mention}
**Warned By:** {message.from_user.mention if message.from_user else 'Anon'}
**Reason:** {reason or 'No Reason Provided.'}
**Warns:** {warns + 1}/3"""
await message.reply_text(msg, reply_markup=keyboard) await message.reply_text(msg, reply_markup=keyboard)
await add_warn(chat_id, await int_to_alpha(user_id), warn) await add_warn(chat_id, await int_to_alpha(user_id), warn)
@app.on_callback_query(filters.regex("unwarn_")) @app.on_callback_query(filters.regex("unwarn_"))
@ratelimiter @ratelimiter
async def remove_warning(_, cq): @use_chat_lang()
async def remove_warning(_, cq, strings):
from_user = cq.from_user from_user = cq.from_user
chat_id = cq.message.chat.id chat_id = cq.message.chat.id
permissions = await member_permissions(chat_id, from_user.id) permissions = await member_permissions(chat_id, from_user.id)
permission = "can_restrict_members" permission = "can_restrict_members"
if permission not in permissions: if permission not in permissions:
return await cq.answer( return await cq.answer(
"You don't have enough permissions to perform this action.\n" + f"Permission needed: {permission}", strings("no_permission_error").format(permissions=permission),
show_alert=True, show_alert=True,
) )
user_id = cq.data.split("_")[1] user_id = cq.data.split("_")[1]
@ -573,52 +566,53 @@ async def remove_warning(_, cq):
if warns: if warns:
warns = warns["warns"] warns = warns["warns"]
if not warns or warns == 0: if not warns or warns == 0:
return await cq.answer("User has no warnings.") return await cq.answer(strings("user_no_warn").format(mention=cq.message.reply_to_message.from_user.id))
warn = {"warns": warns - 1} warn = {"warns": warns - 1}
await add_warn(chat_id, await int_to_alpha(user_id), warn) await add_warn(chat_id, await int_to_alpha(user_id), warn)
text = cq.message.text.markdown text = cq.message.text.markdown
text = f"~~{text}~~\n\n" text = f"~~{text}~~\n\n"
text += f"__Warn removed by {from_user.mention}__" text += strings("unwarn_msg").format(mention=from_user.mention)
await cq.message.edit(text) await cq.message.edit(text)
@app.on_callback_query(filters.regex("unmute_")) @app.on_callback_query(filters.regex("unmute_"))
@ratelimiter @ratelimiter
async def unmute_user(_, cq): @use_chat_lang()
async def unmute_user(_, cq, strings):
from_user = cq.from_user from_user = cq.from_user
chat_id = cq.message.chat.id chat_id = cq.message.chat.id
permissions = await member_permissions(chat_id, from_user.id) permissions = await member_permissions(chat_id, from_user.id)
permission = "can_restrict_members" permission = "can_restrict_members"
if permission not in permissions: if permission not in permissions:
return await cq.answer( return await cq.answer(
"You don't have enough permissions to perform this action.\n" + f"Permission needed: {permission}", strings("no_permission_error").format(permissions=permission),
show_alert=True, show_alert=True,
) )
user_id = cq.data.split("_")[1] user_id = cq.data.split("_")[1]
text = cq.message.text.markdown text = cq.message.text.markdown
text = f"~~{text}~~\n\n" text = f"~~{text}~~\n\n"
text += f"__Mute removed by {from_user.mention}__" text += strings("rmmute_msg").format(mention=from_user.mention)
await cq.message.chat.unban_member(user_id) await cq.message.chat.unban_member(user_id)
await cq.message.edit(text) await cq.message.edit(text)
@app.on_callback_query(filters.regex("unban_")) @app.on_callback_query(filters.regex("unban_"))
@ratelimiter @ratelimiter
async def unban_user(_, cq): @use_chat_lang()
async def unban_user(_, cq, strings):
from_user = cq.from_user from_user = cq.from_user
chat_id = cq.message.chat.id chat_id = cq.message.chat.id
permissions = await member_permissions(chat_id, from_user.id) permissions = await member_permissions(chat_id, from_user.id)
permission = "can_restrict_members" permission = "can_restrict_members"
if permission not in permissions: if permission not in permissions:
return await cq.answer( return await cq.answer(
"You don't have enough permissions to perform this action.\n" + f"Permission needed: {permission}", strings("no_permission_error").format(permissions=permission),
show_alert=True, show_alert=True,
) )
user_id = cq.data.split("_")[1] user_id = cq.data.split("_")[1]
(await app.get_users(user_id)).mention
text = cq.message.text.markdown text = cq.message.text.markdown
text = f"~~{text}~~\n\n" text = f"~~{text}~~\n\n"
text += f"__Banned removed by {from_user.mention}__" text += strings("unban_msg").format(mention=from_user.mention)
await cq.message.chat.unban_member(user_id) await cq.message.chat.unban_member(user_id)
await cq.message.edit(text) await cq.message.edit(text)
@ -627,11 +621,12 @@ async def unban_user(_, cq):
@app.on_message(filters.command("rmwarn", COMMAND_HANDLER) & filters.group) @app.on_message(filters.command("rmwarn", COMMAND_HANDLER) & filters.group)
@adminsOnly("can_restrict_members") @adminsOnly("can_restrict_members")
@ratelimiter @ratelimiter
async def remove_warnings(_, message): @use_chat_lang()
async def remove_warnings(_, message, strings):
if not message.from_user: if not message.from_user:
return return
if not message.reply_to_message: if not message.reply_to_message:
return await message.reply_text("Reply to a message to remove a user's warnings.") return await message.reply_text(strings("reply_to_rm_warn"))
user_id = message.reply_to_message.from_user.id user_id = message.reply_to_message.from_user.id
mention = message.reply_to_message.from_user.mention mention = message.reply_to_message.from_user.mention
chat_id = message.chat.id chat_id = message.chat.id
@ -639,53 +634,55 @@ async def remove_warnings(_, message):
if warns: if warns:
warns = warns["warns"] warns = warns["warns"]
if warns == 0 or not warns: if warns == 0 or not warns:
await message.reply_text(f"{mention} have no warnings.") await message.reply_text(strings("user_no_warn").format(mention=mention))
else: else:
await remove_warns(chat_id, await int_to_alpha(user_id)) await remove_warns(chat_id, await int_to_alpha(user_id))
await message.reply_text(f"Removed warnings of {mention}.") await message.reply_text(strings("rmwarn_msg").format(mention=mention))
# Warns # Warns
@app.on_message(filters.command("warns", COMMAND_HANDLER) & filters.group) @app.on_message(filters.command("warns", COMMAND_HANDLER) & filters.group)
@capture_err @capture_err
@ratelimiter @ratelimiter
async def check_warns(_, message): @use_chat_lang()
async def check_warns(_, message, strings):
if not message.from_user: if not message.from_user:
return return
user_id = await extract_user(message) user_id = await extract_user(message)
if not user_id: if not user_id:
return await message.reply_text("I can't find that user.") return await message.reply_text(strings("user_not_found"))
warns = await get_warn(message.chat.id, await int_to_alpha(user_id)) warns = await get_warn(message.chat.id, await int_to_alpha(user_id))
mention = (await app.get_users(user_id)).mention mention = (await app.get_users(user_id)).mention
if warns: if warns:
warns = warns["warns"] warns = warns["warns"]
else: else:
return await message.reply_text(f"{mention} has no warnings.") return await message.reply_text(strings("user_no_warn").format(mention=mention))
return await message.reply_text(f"{mention} has {warns}/3 warnings.") return await message.reply_text(strings("ch_warn_msg").format(mention=mention, warns=warns))
# Report User in Group # Report User in Group
@app.on_message((filters.command("report", COMMAND_HANDLER) | filters.command(["admins", "admin"], prefixes="@")) & filters.group) @app.on_message((filters.command("report", COMMAND_HANDLER) | filters.command(["admins", "admin"], prefixes="@")) & filters.group)
@capture_err @capture_err
@ratelimiter @ratelimiter
async def report_user(_, message): @use_chat_lang()
async def report_user(_, message, strings):
if not message.reply_to_message: if not message.reply_to_message:
return await message.reply_text("Reply to a message to report that user.") return await message.reply_text(strings("report_no_reply"))
reply = message.reply_to_message reply = message.reply_to_message
reply_id = reply.from_user.id if reply.from_user else reply.sender_chat.id reply_id = reply.from_user.id if reply.from_user else reply.sender_chat.id
user_id = message.from_user.id if message.from_user else message.sender_chat.id user_id = message.from_user.id if message.from_user else message.sender_chat.id
if reply_id == user_id: if reply_id == user_id:
return await message.reply_text("Why are you reporting yourself ?") return await message.reply_text(strings("report_self_err"))
list_of_admins = await list_admins(message.chat.id) list_of_admins = await list_admins(message.chat.id)
linked_chat = (await app.get_chat(message.chat.id)).linked_chat linked_chat = (await app.get_chat(message.chat.id)).linked_chat
if linked_chat is None: if linked_chat is None:
if reply_id in list_of_admins or reply_id == message.chat.id: if reply_id in list_of_admins or reply_id == message.chat.id:
return await message.reply_text("Do you know that the user you are replying is an admin ?") return await message.reply_text(strings("reported_is_admin"))
elif reply_id in list_of_admins or reply_id == message.chat.id or reply_id == linked_chat.id: elif reply_id in list_of_admins or reply_id == message.chat.id or reply_id == linked_chat.id:
return await message.reply_text("Do you know that the user you are replying is an admin ?") return await message.reply_text(strings("reported_is_admin"))
user_mention = reply.from_user.mention if reply.from_user else reply.sender_chat.title user_mention = reply.from_user.mention if reply.from_user else reply.sender_chat.title
text = f"Reported {user_mention} to admins!" text = strings("report_msg").format(user_mention=user_mention)
admin_data = [m async for m in app.get_chat_members(message.chat.id, filter=enums.ChatMembersFilter.ADMINISTRATORS)] admin_data = [m async for m in app.get_chat_members(message.chat.id, filter=enums.ChatMembersFilter.ADMINISTRATORS)]
for admin in admin_data: for admin in admin_data:
if admin.user.is_bot or admin.user.is_deleted: if admin.user.is_bot or admin.user.is_deleted:

View file

@ -120,4 +120,4 @@ async def bypass(_, message):
data = wetransfer_bypass(url) data = wetransfer_bypass(url)
await editPesan(msg, f"{data}\n\n{mention}") await editPesan(msg, f"{data}\n\n{mention}")
else: else:
await kirimPesan(message, "Unsupported url..") await kirimPesan(message, "Unsupported url..")

View file

@ -1,7 +1,8 @@
from pyrogram import filters from pyrogram import filters
from pyrogram.errors import MessageNotModified, MessageTooLong from pyrogram.errors import MessageTooLong
from misskaty import app from misskaty import app
from misskaty.helper.localization import use_chat_lang
from misskaty.helper import http, post_to_telegraph from misskaty.helper import http, post_to_telegraph
from misskaty.core.message_utils import * from misskaty.core.message_utils import *
from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.decorator.ratelimiter import ratelimiter
@ -10,9 +11,10 @@ from misskaty.vars import COMMAND_HANDLER, OPENAI_API
@app.on_message(filters.command("ask", COMMAND_HANDLER)) @app.on_message(filters.command("ask", COMMAND_HANDLER))
@ratelimiter @ratelimiter
async def chatbot(c, m): @use_chat_lang()
async def chatbot(c, m, strings):
if len(m.command) == 1: if len(m.command) == 1:
return await kirimPesan(m, f"Please use command <code>/{m.command[0]} [question]</code> to ask your question.") return await kirimPesan(m, strings("no_question").format(cmd=m.command[0]), quote=True)
pertanyaan = m.text.split(" ", maxsplit=1)[1] pertanyaan = m.text.split(" ", maxsplit=1)[1]
headers = { headers = {
"Content-Type": "application/json", "Content-Type": "application/json",
@ -28,7 +30,7 @@ async def chatbot(c, m):
}, },
], ],
} }
msg = await kirimPesan(m, "Wait a moment looking for your answer..") msg = await kirimPesan(m, strings("find_answers_str"), quote=True)
try: try:
response = (await http.post("https://api.openai.com/v1/chat/completions", headers=headers, json=json_data)).json() response = (await http.post("https://api.openai.com/v1/chat/completions", headers=headers, json=json_data)).json()
if err := response.get("error"): if err := response.get("error"):
@ -37,6 +39,6 @@ async def chatbot(c, m):
await editPesan(msg, answer) await editPesan(msg, answer)
except MessageTooLong: except MessageTooLong:
answerlink = await post_to_telegraph(False, "MissKaty ChatBot ", answer) answerlink = await post_to_telegraph(False, "MissKaty ChatBot ", answer)
await editPesan(msg, f"Question for your answer has exceeded TG text limit, check this link to view.\n\n{answerlink}", disable_web_page_preview=True) await editPesan(msg, strings("answers_too_long").format(answerlink=answerlink), disable_web_page_preview=True)
except Exception as err: except Exception as err:
await editPesan(msg, f"Oppss. ERROR: {str(err)}") await editPesan(msg, f"ERROR: {str(err)}")

View file

@ -17,11 +17,9 @@ from pyrogram import enums, filters
from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
from misskaty import app, user, botStartTime, BOT_NAME from misskaty import app, user, botStartTime, BOT_NAME
from misskaty.helper import http
from misskaty.helper.human_read import get_readable_file_size, get_readable_time from misskaty.helper.human_read import get_readable_file_size, get_readable_time
from misskaty.core.message_utils import editPesan, hapusPesan, kirimPesan from misskaty.core.message_utils import editPesan, hapusPesan, kirimPesan
from misskaty.vars import COMMAND_HANDLER, SUDO from misskaty.vars import COMMAND_HANDLER, SUDO
from utils import LOGGER
__MODULE__ = "DevCommand" __MODULE__ = "DevCommand"
__HELP__ = """ __HELP__ = """
@ -67,8 +65,8 @@ async def log_file(bot, message):
@app.on_message(filters.command(["donate"], COMMAND_HANDLER)) @app.on_message(filters.command(["donate"], COMMAND_HANDLER))
async def donate(_, message): async def donate(_, message):
await message.reply_photo( await message.reply_photo(
"AgACAgQAAxkBAAECsVNjbMvjxbN4gRafvNBH-Kv-Zqml8wACzq4xG95tbVPDeZ_UusonbAAIAQADAgADeQAHHgQ", "https://telegra.ph/file/2acf7698f300ef3d9138f.jpg",
caption=f"Hai {message.from_user.mention}, jika kamu merasa bot ini berguna bisa melakukan donasi dengan scan kode QRIS diatas untuk kebutuhan server dan lainnya. Terimakasih..", caption=f"Hai {message.from_user.mention}, jika kamu merasa bot ini berguna bisa melakukan donasi dengan scan kode QRIS diatas yaa. Terimakasih..",
) )
@ -158,37 +156,37 @@ async def evaluation_cmd_t(_, m):
try: try:
await aexec(cmd, _, m) await aexec(cmd, _, m)
except NameError as e: except NameError as e:
trace_output = "❌ MISSING VARIABEL:\n" trace_output = "❌ MISSING VARIABEL:\n"
trace_output += f"{e}" trace_output += f"{e}"
exc = trace_output exc = trace_output
except AttributeError as e: except AttributeError as e:
trace_output = "❌ MISSING ATTRIBUTE:\n" trace_output = "❌ MISSING ATTRIBUTE:\n"
trace_output += f"{e}" trace_output += f"{e}"
exc = trace_output exc = trace_output
except SyntaxError as e: except SyntaxError:
trace = traceback.format_exc() trace = traceback.format_exc()
splitted = str(trace).split("\n") splitted = str(trace).split("\n")
end_split = len(splitted) end_split = len(splitted)
row_1 = splitted[end_split - 4] row_1 = splitted[end_split - 4]
row_2 = splitted[end_split - 3] row_2 = splitted[end_split - 3]
row_3 = splitted[end_split - 2] row_3 = splitted[end_split - 2]
compiles = row_1 + "\n" + row_2 + "\n" + row_3 compiles = row_1 + "\n" + row_2 + "\n" + row_3
trace_output = "⚙️ SYNTAX ERROR:\n" trace_output = "⚙️ SYNTAX ERROR:\n"
trace_output += f"{compiles}" trace_output += f"{compiles}"
exc = trace_output exc = trace_output
except ValueError as e: except ValueError as e:
trace_output = "🧮 VALUE ERROR:\n" trace_output = "🧮 VALUE ERROR:\n"
trace_output += f"{e}" trace_output += f"{e}"
exc = trace_output exc = trace_output
except Exception as e: except Exception as e:
#trace = traceback.format_exc() # trace = traceback.format_exc()
""" Periksa apakah error regexnya tertangkap""" """Periksa apakah error regexnya tertangkap"""
match = re.search(r"Telegram says: .+", str(e)) match = re.search(r"Telegram says: .+", str(e))
trace_output = "⚠️ COMMON ERROR:\n" trace_output = "⚠️ COMMON ERROR:\n"
trace_output += f"{e}" trace_output += f"{e}"
if match: if match:
trace_output = f"👀 {match[0]}" trace_output = f"👀 {match[0]}"
exc = trace_output exc = trace_output
stdout = redirected_output.getvalue() stdout = redirected_output.getvalue()
stderr = redirected_error.getvalue() stderr = redirected_error.getvalue()
@ -241,7 +239,7 @@ async def update_restart(_, message):
except Exception as e: except Exception as e:
return await message.reply_text(str(e)) return await message.reply_text(str(e))
msg = await message.reply_text("<b>Updated with default branch, restarting now.</b>") msg = await message.reply_text("<b>Updated with default branch, restarting now.</b>")
with open('restart.pickle', 'wb') as status: with open("restart.pickle", "wb") as status:
pickle.dump([message.chat.id, msg.id], status) pickle.dump([message.chat.id, msg.id], status)
os.execvp(sys.executable, [sys.executable, "-m", "misskaty"]) os.execvp(sys.executable, [sys.executable, "-m", "misskaty"])

View file

@ -162,11 +162,7 @@ async def fbdl(client, message):
obj = SmartDL(url, progress_bar=False) obj = SmartDL(url, progress_bar=False)
obj.start() obj.start()
path = obj.get_dest() path = obj.get_dest()
await message.reply_video( await message.reply_video(path, caption=f"<code>{os.path.basename(path)}</code>\n\nUploaded for {message.from_user.mention} [<code>{message.from_user.id}</code>]", thumb="assets/thumb.jpg")
path,
caption=f"<code>{os.path.basename(path)}</code>\n\nUploaded for {message.from_user.mention} [<code>{message.from_user.id}</code>]",
thumb="assets/thumb.jpg"
)
await msg.delete() await msg.delete()
try: try:
os.remove(path) os.remove(path)

View file

@ -6,6 +6,7 @@ from PIL import Image, ImageDraw, ImageFont
from pyrogram import filters from pyrogram import filters
from misskaty import app from misskaty import app
from misskaty.helper.localization import use_chat_lang
from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.decorator.ratelimiter import ratelimiter
from misskaty.core.decorator.errors import capture_err from misskaty.core.decorator.errors import capture_err
from misskaty.vars import COMMAND_HANDLER from misskaty.vars import COMMAND_HANDLER
@ -157,3 +158,10 @@ async def memify(client, message):
await message.reply("Gunakan command <b>/mmf <text></b> dengan reply ke sticker, pisahkan dengan ; untuk membuat posisi text dibawah.") await message.reply("Gunakan command <b>/mmf <text></b> dengan reply ke sticker, pisahkan dengan ; untuk membuat posisi text dibawah.")
else: else:
await message.reply("Gunakan command <b>/mmf <text></b> dengan reply ke sticker, pisahkan dengan ; untuk membuat posisi text dibawah.") await message.reply("Gunakan command <b>/mmf <text></b> 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):
dices = await c.send_dice(m.chat.id, reply_to_message_id=m.id)
await dices.reply_text(strings("result").format(number=dices.dice.value), quote=True)

View file

@ -8,7 +8,6 @@
import datetime import datetime
import os import os
import time import time
import traceback
from asyncio import gather, sleep from asyncio import gather, sleep
from logging import getLogger from logging import getLogger

View file

@ -23,7 +23,7 @@ from misskaty import BOT_USERNAME, app
from misskaty.core.message_utils import * from misskaty.core.message_utils import *
from misskaty.core.decorator.errors import capture_err from misskaty.core.decorator.errors import capture_err
from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.decorator.ratelimiter import ratelimiter
from misskaty.helper import http, get_random_string, search_jw, GENRES_EMOJI, post_to_telegraph from misskaty.helper import http, get_random_string, search_jw, GENRES_EMOJI
from misskaty.vars import COMMAND_HANDLER, LOG_CHANNEL from misskaty.vars import COMMAND_HANDLER, LOG_CHANNEL
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)

View file

@ -0,0 +1,102 @@
from functools import partial
from typing import Union
from pyrogram import Client, filters
from pyrogram.enums import ChatType
from pyrogram.types import (
CallbackQuery,
InlineKeyboardButton,
InlineKeyboardMarkup,
Message,
)
from misskaty.vars import COMMAND_HANDLER
from misskaty import app
from database.locale_db import set_db_lang
from ..core.decorator.permissions import require_admin
from ..helper.localization import (
default_language,
get_locale_string,
langdict,
use_chat_lang,
)
def gen_langs_kb():
langs = list(langdict)
kb = []
while langs:
lang = langdict[langs[0]]["main"]
a = [
InlineKeyboardButton(
f"{lang['language_flag']} {lang['language_name']}",
callback_data=f"set_lang {langs[0]}",
)
]
langs.pop(0)
if langs:
lang = langdict[langs[0]]["main"]
a.append(
InlineKeyboardButton(
f"{lang['language_flag']} {lang['language_name']}",
callback_data=f"set_lang {langs[0]}",
)
)
langs.pop(0)
kb.append(a)
return kb
@app.on_callback_query(filters.regex("^chlang$"))
@app.on_message(filters.command(["setchatlang", "setlang"], COMMAND_HANDLER))
@require_admin(allow_in_private=True)
@use_chat_lang()
async def chlang(c: Client, m: Union[CallbackQuery, Message], strings):
keyboard = InlineKeyboardMarkup(
inline_keyboard=[
*gen_langs_kb(),
[InlineKeyboardButton(strings("back_btn", context="general"), callback_data="start_back")],
]
)
if isinstance(m, CallbackQuery):
msg = m.message
sender = msg.edit_text
else:
msg = m
sender = msg.reply_text
res = strings("language_changer_private") if msg.chat.type == ChatType.PRIVATE else strings("language_changer_chat")
await sender(res, reply_markup=keyboard)
@app.on_callback_query(filters.regex("^set_lang "))
@require_admin(allow_in_private=True)
@use_chat_lang()
async def set_chat_lang(c: Client, m: CallbackQuery, strings):
lang = m.data.split()[1]
await set_db_lang(m.message.chat.id, m.message.chat.type, lang)
strings = partial(
get_locale_string,
langdict[lang].get("lang_setting", langdict[default_language]["lang_setting"]),
lang,
"lang_setting",
)
if m.message.chat.type == ChatType.PRIVATE:
keyboard = InlineKeyboardMarkup(
inline_keyboard=[
[
InlineKeyboardButton(
strings("back_btn", context="general"),
callback_data="start_back",
)
]
]
)
else:
keyboard = None
await m.message.edit_text(strings("language_changed_successfully"), reply_markup=keyboard)

View file

@ -16,29 +16,31 @@ from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
from misskaty import app from misskaty import app
from misskaty.core.message_utils import * from misskaty.core.message_utils import *
from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.decorator.ratelimiter import ratelimiter
from misskaty.helper import http, progress_for_pyrogram, runcmd, post_to_telegraph from misskaty.helper import progress_for_pyrogram, runcmd, post_to_telegraph
from misskaty.helper.mediainfo_paste import mediainfo_paste from misskaty.helper.mediainfo_paste import mediainfo_paste
from misskaty.helper.localization import use_chat_lang
from misskaty.vars import COMMAND_HANDLER from misskaty.vars import COMMAND_HANDLER
from utils import get_file_id from utils import get_file_id
@app.on_message(filters.command(["mediainfo"], COMMAND_HANDLER)) @app.on_message(filters.command(["mediainfo"], COMMAND_HANDLER))
@ratelimiter @ratelimiter
async def mediainfo(client, message): @use_chat_lang()
async def mediainfo(client, message, strings):
if not message.from_user: if not message.from_user:
return return
if message.reply_to_message and message.reply_to_message.media: if message.reply_to_message and message.reply_to_message.media:
process = await kirimPesan(message, "`Processing, total time is based size of your files...`", quote=True) process = await kirimPesan(message, strings("processing_text"), quote=True)
file_info = get_file_id(message.reply_to_message) file_info = get_file_id(message.reply_to_message)
if file_info is None: if file_info is None:
return await editPesan(process, "Please reply to valid media.") return await editPesan(process, strings("media_invalid"))
if (message.reply_to_message.video and message.reply_to_message.video.file_size > 2097152000) or (message.reply_to_message.document and message.reply_to_message.document.file_size > 2097152000): if (message.reply_to_message.video and message.reply_to_message.video.file_size > 2097152000) or (message.reply_to_message.document and message.reply_to_message.document.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("dl_limit_exceeded"))
c_time = time.time() c_time = time.time()
dl = await message.reply_to_message.download( dl = await message.reply_to_message.download(
file_name="/downloads/", file_name="/downloads/",
progress=progress_for_pyrogram, progress=progress_for_pyrogram,
progress_args=("Trying to download..", process, c_time), progress_args=(strings("dl_args_text"), process, c_time),
) )
file_path = path.join("/downloads/", path.basename(dl)) file_path = path.join("/downloads/", path.basename(dl))
output_ = await runcmd(f'mediainfo "{file_path}"') output_ = await runcmd(f'mediainfo "{file_path}"')
@ -51,21 +53,21 @@ JSON
DETAILS DETAILS
{out or 'Not Supported'} {out or 'Not Supported'}
""" """
text_ = file_info.message_type file_info.message_type
try: try:
link = await mediainfo_paste(out, "MissKaty Mediainfo") link = await mediainfo_paste(out, "MissKaty Mediainfo")
markup = InlineKeyboardMarkup([[InlineKeyboardButton(text="💬 View in Web", url=link)]]) markup = InlineKeyboardMarkup([[InlineKeyboardButton(text=strings("vweb"), url=link)]])
except: except:
try: try:
link = await post_to_telegraph(False, "MissKaty MediaInfo", body_text) link = await post_to_telegraph(False, "MissKaty MediaInfo", body_text)
markup = InlineKeyboardMarkup([[InlineKeyboardButton(text="💬 View in Web", url=link)]]) markup = InlineKeyboardMarkup([[InlineKeyboardButton(text=strings("vweb"), url=link)]])
except: except:
markup = None markup = None
with io.BytesIO(str.encode(body_text)) as out_file: with io.BytesIO(str.encode(body_text)) as out_file:
out_file.name = "MissKaty_Mediainfo.txt" out_file.name = "MissKaty_Mediainfo.txt"
await message.reply_document( await message.reply_document(
out_file, out_file,
caption=f" <b>MEDIA INFO</b>\n\n**Request by:** {message.from_user.mention}", caption=strings("capt_media").format(ment=message.from_user.mention),
thumb="assets/thumb.jpg", thumb="assets/thumb.jpg",
reply_markup=markup, reply_markup=markup,
) )
@ -77,11 +79,11 @@ DETAILS
else: else:
try: try:
link = message.text.split(" ", maxsplit=1)[1] link = message.text.split(" ", maxsplit=1)[1]
process = await kirimPesan(message, "`Mohon tunggu sejenak...`") process = await kirimPesan(message, strings("wait_msg"))
try: try:
output = subprocess.check_output(["mediainfo", f"{link}"]).decode("utf-8") output = subprocess.check_output(["mediainfo", f"{link}"]).decode("utf-8")
except Exception: except Exception:
return await editPesan(process, "Sepertinya link yang kamu kirim tidak valid, pastikan direct link dan bisa di download.") return await editPesan(process, strings("err_link"))
body_text = f""" body_text = f"""
MissKatyBot MediaInfo MissKatyBot MediaInfo
{output} {output}
@ -89,21 +91,21 @@ DETAILS
# link = await post_to_telegraph(False, title, body_text) # link = await post_to_telegraph(False, title, body_text)
try: try:
link = await mediainfo_paste(out, "MissKaty Mediainfo") link = await mediainfo_paste(out, "MissKaty Mediainfo")
markup = InlineKeyboardMarkup([[InlineKeyboardButton(text="💬 View in Web", url=link)]]) markup = InlineKeyboardMarkup([[InlineKeyboardButton(text=strings("vweb"), url=link)]])
except: except:
try: try:
link = await post_to_telegraph(False, "MissKaty MediaInfo", body_text) link = await post_to_telegraph(False, "MissKaty MediaInfo", body_text)
markup = InlineKeyboardMarkup([[InlineKeyboardButton(text="💬 View in Web", url=link)]]) markup = InlineKeyboardMarkup([[InlineKeyboardButton(text=strings("vweb"), url=link)]])
except: except:
markup = None markup = None
with io.BytesIO(str.encode(output)) as out_file: with io.BytesIO(str.encode(output)) as out_file:
out_file.name = "MissKaty_Mediainfo.txt" out_file.name = "MissKaty_Mediainfo.txt"
await message.reply_document( await message.reply_document(
out_file, out_file,
caption=f"Hasil mediainfo anda..\n\n**Request by:** {message.from_user.mention}", caption=strings("capt_media").format(ment=message.from_user.mention),
thumb="assets/thumb.jpg", thumb="assets/thumb.jpg",
reply_markup=markup, reply_markup=markup,
) )
await process.delete() await process.delete()
except IndexError: except IndexError:
return await kirimPesan(message, "Gunakan command /mediainfo [link], atau reply telegram media dengan /mediainfo.") return await kirimPesan(message, strings("mediainfo_help").format(help=message.command[0]))

View file

@ -8,11 +8,9 @@
import json import json
import os import os
import time
import asyncio import asyncio
import traceback import traceback
from PIL import Image from PIL import Image
from datetime import datetime
from logging import getLogger from logging import getLogger
from urllib.parse import quote from urllib.parse import quote
@ -63,11 +61,11 @@ async def readqr(c, m):
if not m.reply_to_message.photo: if not m.reply_to_message.photo:
return await m.reply("Please reply photo that contain valid QR Code.") return await m.reply("Please reply photo that contain valid QR Code.")
foto = await m.reply_to_message.download() foto = await m.reply_to_message.download()
myfile = {'file': (foto, open(foto, 'rb'),'application/octet-stream')} myfile = {"file": (foto, open(foto, "rb"), "application/octet-stream")}
url = 'http://api.qrserver.com/v1/read-qr-code/' url = "http://api.qrserver.com/v1/read-qr-code/"
r = await http.post(url, files=myfile) r = await http.post(url, files=myfile)
os.remove(foto) os.remove(foto)
if res := r.json()[0]['symbol'][0]['data'] is None: if res := r.json()[0]["symbol"][0]["data"] is None:
return await kirimPesan(m, res) return await kirimPesan(m, res)
await kirimPesan(m, f"<b>QR Code Reader by @{c.me.username}:</b> <code>{r.json()[0]['symbol'][0]['data']}</code>", quote=True) await kirimPesan(m, f"<b>QR Code Reader by @{c.me.username}:</b> <code>{r.json()[0]['symbol'][0]['data']}</code>", quote=True)

View file

@ -4,8 +4,7 @@ from datetime import datetime, timedelta
import pytz import pytz
from apscheduler.jobstores.base import ConflictingIdError from apscheduler.jobstores.base import ConflictingIdError
from pyrogram import filters, __version__ from pyrogram import filters, __version__
from pyrogram.errors import (ChannelInvalid, ChannelPrivate, ChatAdminRequired, from pyrogram.errors import ChannelInvalid, ChannelPrivate, ChatAdminRequired, ChatNotModified
ChatNotModified)
from pyrogram.types import ChatPermissions, InlineKeyboardButton, InlineKeyboardMarkup from pyrogram.types import ChatPermissions, InlineKeyboardButton, InlineKeyboardMarkup
from misskaty import BOT_NAME, BOT_USERNAME, app, scheduler from misskaty import BOT_NAME, BOT_USERNAME, app, scheduler
@ -30,6 +29,7 @@ __HELP__ = """<b>Enable or disable nightmode (locks the chat at specified interv
TIME_ZONE = pytz.timezone(TZ) TIME_ZONE = pytz.timezone(TZ)
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton(text="❤️", callback_data="nightmd")]]) reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton(text="❤️", callback_data="nightmd")]])
# Check calculate how long it will take to Ramadhan # Check calculate how long it will take to Ramadhan
def puasa(): def puasa():
now = datetime.now(pytz.timezone("Asia/Jakarta")) now = datetime.now(pytz.timezone("Asia/Jakarta"))
@ -43,6 +43,7 @@ def puasa():
y = datetime(2022, 4, 2, 0, 0, 0) y = datetime(2022, 4, 2, 0, 0, 0)
return y - x return y - x
def tglsekarang(): def tglsekarang():
now = datetime.now(pytz.timezone("Asia/Jakarta")) now = datetime.now(pytz.timezone("Asia/Jakarta"))
days = ["Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Minggu"] days = ["Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Minggu"]
@ -66,84 +67,60 @@ def tglsekarang():
jam = now.strftime("%H:%M") jam = now.strftime("%H:%M")
return f"{days[now.weekday()]}, {tgl} {month[now.month]} {tahun}" return f"{days[now.weekday()]}, {tgl} {month[now.month]} {tahun}"
def extract_time(time_val: str): def extract_time(time_val: str):
if any(time_val.endswith(unit) for unit in ('m', 'h')): if any(time_val.endswith(unit) for unit in ("m", "h")):
unit = time_val[-1] unit = time_val[-1]
time_num = time_val[:-1] time_num = time_val[:-1]
if not time_num.isdigit(): if not time_num.isdigit():
return "" return ""
if unit == 'm': if unit == "m":
time = int(time_num) * 60 time = int(time_num) * 60
elif unit == 'h': elif unit == "h":
time = int(time_num) * 60 * 60 time = int(time_num) * 60 * 60
else: else:
return "" return ""
return time return time
return "" return ""
async def un_mute_chat(chat_id: int, perm: ChatPermissions): async def un_mute_chat(chat_id: int, perm: ChatPermissions):
try: try:
await app.set_chat_permissions(chat_id, perm) await app.set_chat_permissions(chat_id, perm)
except ChatAdminRequired: except ChatAdminRequired:
await app.send_message( 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}`")
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}`")
except (ChannelInvalid, ChannelPrivate): except (ChannelInvalid, ChannelPrivate):
scheduler.remove_job(f"enable_nightmode_{chat_id}") scheduler.remove_job(f"enable_nightmode_{chat_id}")
scheduler.remove_job(f"disable_nightmode_{chat_id}") scheduler.remove_job(f"disable_nightmode_{chat_id}")
await app.send_message( 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.")
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.")
except ChatNotModified: except ChatNotModified:
pass pass
except Exception as e: except Exception as e:
await app.send_message( await app.send_message(LOG_CHANNEL, f"#NIGHTMODE_FAIL\nFailed to turn off nightmode at `{chat_id}`\n" f"ERROR: `{e}`")
LOG_CHANNEL,
f"#NIGHTMODE_FAIL\nFailed to turn off nightmode at `{chat_id}`\n"
f"ERROR: `{e}`")
else: else:
job = scheduler.get_job(f"enable_nightmode_{chat_id}") job = scheduler.get_job(f"enable_nightmode_{chat_id}")
close_at = job.next_run_time close_at = job.next_run_time
await app.send_message( 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)
chat_id,
f"#NIGHTMODE_HANDLER\n📆 {tglsekarang()}\n\n☀️ Group is Opening.\nWill be closed at {close_at}",
reply_markup=reply_markup
)
async def mute_chat(chat_id: int): async def mute_chat(chat_id: int):
try: try:
await app.set_chat_permissions(chat_id, ChatPermissions()) await app.set_chat_permissions(chat_id, ChatPermissions())
except ChatAdminRequired: except ChatAdminRequired:
await app.send_message( 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}`")
LOG_CHANNEL,
f"#NIGHTMODE_FAIL\nFailed to enable nightmode at `{chat_id}`,"
f"since {BOT_NAME} is not an admin in chat `{chat_id}`")
except (ChannelInvalid, ChannelPrivate): except (ChannelInvalid, ChannelPrivate):
scheduler.remove_job(f"enable_nightmode_{chat_id}") scheduler.remove_job(f"enable_nightmode_{chat_id}")
scheduler.remove_job(f"disable_nightmode_{chat_id}") scheduler.remove_job(f"disable_nightmode_{chat_id}")
await app.send_message( 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.")
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.")
except ChatNotModified: except ChatNotModified:
pass pass
except Exception as e: except Exception as e:
await app.send_message( await app.send_message(LOG_CHANNEL, f"#NIGHTMODE_FAIL\nFailed to enable nightmode at `{chat_id}`\n" f"ERROR: `{e}`")
LOG_CHANNEL,
f"#NIGHTMODE_FAIL\nFailed to enable nightmode at `{chat_id}`\n"
f"ERROR: `{e}`")
else: else:
job = scheduler.get_job(f"disable_nightmode_{chat_id}") job = scheduler.get_job(f"disable_nightmode_{chat_id}")
open_at = job.next_run_time open_at = job.next_run_time
await app.send_message( 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)
chat_id,
f"#NIGHTMODE_HANDLER\n📆 {tglsekarang()}\n\n🌗 Group is closing.\nWill be opened at {open_at}",
reply_markup=reply_markup
)
@app.on_message(filters.command("nightmode", COMMAND_HANDLER) & filters.group) @app.on_message(filters.command("nightmode", COMMAND_HANDLER) & filters.group)
@adminsOnly("can_change_info") @adminsOnly("can_change_info")
@ -157,7 +134,7 @@ async def nightmode_handler(c, msg):
scheduler.remove_job(job_id=f"disable_nightmode_{chat_id}") scheduler.remove_job(job_id=f"disable_nightmode_{chat_id}")
if not bool(scheduler.get_jobs()) and bool(scheduler.state): if not bool(scheduler.get_jobs()) and bool(scheduler.state):
scheduler.shutdown() scheduler.shutdown()
return await kirimPesan(msg, 'Nightmode disabled.') return await kirimPesan(msg, "Nightmode disabled.")
return await kirimPesan(msg, "Nightmode isn't enabled in this chat.") return await kirimPesan(msg, "Nightmode isn't enabled in this chat.")
starttime = re.findall(r"-s=(\d+:\d+)", msg.text) starttime = re.findall(r"-s=(\d+:\d+)", msg.text)
@ -165,10 +142,7 @@ async def nightmode_handler(c, msg):
now = datetime.now(TIME_ZONE) now = datetime.now(TIME_ZONE)
try: try:
start_timestamp = TIME_ZONE.localize( start_timestamp = TIME_ZONE.localize(datetime.strptime((now.strftime("%m:%d:%Y - ") + start), "%m:%d:%Y - %H:%M"))
datetime.strptime(
(now.strftime('%m:%d:%Y - ') + start),
'%m:%d:%Y - %H:%M'))
except ValueError: except ValueError:
return await kirimPesan(msg, "Invalid time format. Use HH:MM format.") return await kirimPesan(msg, "Invalid time format. Use HH:MM format.")
lockdur = re.findall(r"-e=(\w+)", msg.text) lockdur = re.findall(r"-e=(\w+)", msg.text)
@ -176,53 +150,25 @@ async def nightmode_handler(c, msg):
lock_dur = extract_time(lockdur.lower()) lock_dur = extract_time(lockdur.lower())
if not lock_dur: if not lock_dur:
return await kirimPesan( return await kirimPesan(msg, "Invalid time duration. Use proper format." "\nExample: 6h (for 6 hours), 10m for 10 minutes.")
msg,
'Invalid time duration. Use proper format.'
'\nExample: 6h (for 6 hours), 10m for 10 minutes.')
if start_timestamp < now: if start_timestamp < now:
start_timestamp = start_timestamp + timedelta(days=1) start_timestamp = start_timestamp + timedelta(days=1)
end_time_stamp = start_timestamp + timedelta(seconds=int(lock_dur)) end_time_stamp = start_timestamp + timedelta(seconds=int(lock_dur))
try: try:
# schedule to enable nightmode # schedule to enable nightmode
scheduler.add_job( scheduler.add_job(mute_chat, "interval", [chat_id], id=f"enable_nightmode_{chat_id}", days=1, next_run_time=start_timestamp, max_instances=50, misfire_grace_time=None)
mute_chat,
'interval',
[chat_id],
id=f"enable_nightmode_{chat_id}",
days=1,
next_run_time=start_timestamp,
max_instances=50,
misfire_grace_time=None)
# schedule to disable nightmode # schedule to disable nightmode
scheduler.add_job( 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)
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: except ConflictingIdError:
return await kirimPesan( return await kirimPesan(msg, "Already a schedule is running in this chat. Disable it using `-d` flag.")
msg, 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.")
'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.')
if not bool(scheduler.state): if not bool(scheduler.state):
scheduler.start() scheduler.start()
@app.on_callback_query(filters.regex(r"^nightmd$")) @app.on_callback_query(filters.regex(r"^nightmd$"))
@ratelimiter @ratelimiter
async def callbackanightmd(c, q): async def callbackanightmd(c, q):
await q.answer( 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)
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
)

View file

@ -5,6 +5,7 @@
* @projectName MissKatyPyro * @projectName MissKatyPyro
* Copyright @YasirPedia All rights reserved * Copyright @YasirPedia All rights reserved
""" """
import os import os
from pyrogram import filters from pyrogram import filters
@ -14,6 +15,7 @@ from misskaty import app
from misskaty.core.message_utils import * from misskaty.core.message_utils import *
from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.decorator.ratelimiter import ratelimiter
from misskaty.core.decorator.errors import capture_err from misskaty.core.decorator.errors import capture_err
from misskaty.helper.localization import use_chat_lang
from misskaty.helper.http import http from misskaty.helper.http import http
from misskaty.vars import COMMAND_HANDLER from misskaty.vars import COMMAND_HANDLER
@ -24,11 +26,12 @@ __HELP__ = "/ocr [reply to photo] - Read Text From Image"
@app.on_message(filters.command(["ocr"], COMMAND_HANDLER)) @app.on_message(filters.command(["ocr"], COMMAND_HANDLER))
@capture_err @capture_err
@ratelimiter @ratelimiter
async def ocr(_, m): @use_chat_lang()
async def ocr(_, m, strings):
reply = m.reply_to_message reply = m.reply_to_message
if not reply or not reply.photo and not reply.sticker: if not reply or not reply.photo and not reply.sticker:
return await kirimPesan(m, f"Reply photo with /{m.command[0]} command") return await kirimPesan(m, strings("no_photo").format(cmd=m.command[0]), quote=True)
msg = await kirimPesan(m, "Reading image...") msg = await kirimPesan(m, strings("read_ocr"), quote=True)
try: try:
file_path = await reply.download() file_path = await reply.download()
if reply.sticker: if reply.sticker:
@ -41,7 +44,7 @@ async def ocr(_, m):
follow_redirects=True, follow_redirects=True,
) )
).json() ).json()
await editPesan(msg, f"Hasil OCR:\n<code>{req['text']}</code>") await editPesan(msg, strings("result_ocr").format(result=req["text"]))
os.remove(file_path) os.remove(file_path)
except Exception as e: except Exception as e:
await editPesan(msg, str(e)) await editPesan(msg, str(e))

View file

@ -5,6 +5,7 @@ from misskaty import app
from misskaty.core.decorator.permissions import adminsOnly from misskaty.core.decorator.permissions import adminsOnly
from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.decorator.ratelimiter import ratelimiter
from misskaty.core.message_utils import kirimPesan from misskaty.core.message_utils import kirimPesan
from misskaty.helper.localization import use_chat_lang
from misskaty.vars import COMMAND_HANDLER from misskaty.vars import COMMAND_HANDLER
__MODULE__ = "SangMata" __MODULE__ = "SangMata"
@ -19,28 +20,28 @@ This feature inspired from SangMata Bot. I'm created simple detection to check u
filters.group & ~filters.bot & ~filters.via_bot, filters.group & ~filters.bot & ~filters.via_bot,
group=3, group=3,
) )
async def cek_mataa(_, m): @use_chat_lang()
async def cek_mataa(_, m, strings):
if m.sender_chat or not await is_sangmata_on(m.chat.id): if m.sender_chat or not await is_sangmata_on(m.chat.id):
return return
if not await cek_userdata(m.from_user.id): if not await cek_userdata(m.from_user.id):
return await add_userdata(m.from_user.id, m.from_user.username, m.from_user.first_name, m.from_user.last_name) return await add_userdata(m.from_user.id, m.from_user.username, m.from_user.first_name, m.from_user.last_name)
username, first_name, last_name = await get_userdata(m.from_user.id) usernamebefore, first_name, lastname_before = await get_userdata(m.from_user.id)
msg = "" msg = ""
if username != m.from_user.username or first_name != m.from_user.first_name or last_name != m.from_user.last_name: if usernamebefore != m.from_user.username or first_name != m.from_user.first_name or lastname_before != m.from_user.last_name:
msg += "👀 <b>Mata MissKaty</b>\n\n" msg += f"👀 <b>Mata MissKaty</b>\n\n🌞 User: {m.from_user.mention} [<code>{m.from_user.id}</code>]\n"
if username != m.from_user.username: if usernamebefore != m.from_user.username:
username = "No Username" if not username else username usernamebefore = f"@{usernamebefore}" if usernamebefore else strings("no_uname")
msg += f"{m.from_user.mention} [<code>{m.from_user.id}</code>] changed username.\n" usernameafter = f"@{m.from_user.username}" if m.from_user.username else strings("no_uname")
msg += f"From {username} ➡️ @{m.from_user.username}.\n" msg += strings("uname_change_msg").format(bef=usernamebefore, aft=usernameafter)
await add_userdata(m.from_user.id, m.from_user.username, m.from_user.first_name, m.from_user.last_name) await add_userdata(m.from_user.id, m.from_user.username, m.from_user.first_name, m.from_user.last_name)
if first_name != m.from_user.first_name: if first_name != m.from_user.first_name:
msg += f"{m.from_user.mention} [<code>{m.from_user.id}</code>] changed first_name.\n" msg += strings("firstname_change_msg").format(bef=first_name, aft=m.from_user.first_name)
msg += f"From {first_name} ➡️ {m.from_user.first_name}.\n"
await add_userdata(m.from_user.id, m.from_user.username, m.from_user.first_name, m.from_user.last_name) await add_userdata(m.from_user.id, m.from_user.username, m.from_user.first_name, m.from_user.last_name)
if last_name != m.from_user.last_name: if lastname_before != m.from_user.last_name:
last_name = "No Lastname" if not username else username lastname_before = lastname_before or strings("no_last_name")
msg += f"{m.from_user.mention} [<code>{m.from_user.id}</code>] changed last_name.\n" lastname_after = m.from_user.last_name or strings("no_last_name")
msg += f"From {last_name} ➡️ {m.from_user.last_name}." msg += strings("lastname_change_msg").format(bef=lastname_before, aft=lastname_after)
await add_userdata(m.from_user.id, m.from_user.username, m.from_user.first_name, m.from_user.last_name) await add_userdata(m.from_user.id, m.from_user.username, m.from_user.first_name, m.from_user.last_name)
if msg != "": if msg != "":
await kirimPesan(m, msg, quote=True) await kirimPesan(m, msg, quote=True)
@ -49,22 +50,23 @@ async def cek_mataa(_, m):
@app.on_message(filters.group & filters.command("sangmata_set", COMMAND_HANDLER) & ~filters.bot & ~filters.via_bot) @app.on_message(filters.group & filters.command("sangmata_set", COMMAND_HANDLER) & ~filters.bot & ~filters.via_bot)
@adminsOnly("can_change_info") @adminsOnly("can_change_info")
@ratelimiter @ratelimiter
async def set_mataa(_, m): @use_chat_lang()
async def set_mataa(_, m, strings):
if len(m.command) == 1: if len(m.command) == 1:
return await kirimPesan(m, f"Use <code>/{m.command[0]} on</code>, to enable sangmata. If you want disable, you can use off parameter.") return await kirimPesan(m, strings("set_sangmata_help").format(cmd=m.command[0]))
if m.command[1] == "on": if m.command[1] == "on":
cekset = await is_sangmata_on(m.chat.id) cekset = await is_sangmata_on(m.chat.id)
if cekset: if cekset:
await kirimPesan(m, "SangMata already enabled in your groups.") await kirimPesan(m, strings("sangmata_already_on"))
else: else:
await sangmata_on(m.chat.id) await sangmata_on(m.chat.id)
await kirimPesan(m, "Sangmata enabled in your groups.") await kirimPesan(m, strings("sangmata_enabled"))
elif m.command[1] == "off": elif m.command[1] == "off":
cekset = await is_sangmata_on(m.chat.id) cekset = await is_sangmata_on(m.chat.id)
if not cekset: if not cekset:
await kirimPesan(m, "SangMata already disabled in your groups.") await kirimPesan(m, strings("sangmata_already_off"))
else: else:
await sangmata_off(m.chat.id) await sangmata_off(m.chat.id)
await kirimPesan(m, "Sangmata has been disabled in your groups.") await kirimPesan(m, strings("sangmata_disabled"))
else: else:
await kirimPesan(m, "Unknown parameter, use only on/off parameter.") await kirimPesan(m, strings("wrong_param"))

View file

@ -16,6 +16,7 @@ from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
from misskaty import BOT_USERNAME, app from misskaty import BOT_USERNAME, app
from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.decorator.ratelimiter import ratelimiter
from misskaty.helper.http import http from misskaty.helper.http import http
from misskaty.helper.localization import use_chat_lang
from misskaty.vars import COMMAND_HANDLER, LOG_CHANNEL from misskaty.vars import COMMAND_HANDLER, LOG_CHANNEL
__MODULE__ = "Stickers" __MODULE__ = "Stickers"
@ -43,10 +44,11 @@ SUPPORTED_TYPES = ["jpeg", "png", "webp"]
@app.on_message(filters.command(["getsticker"], COMMAND_HANDLER)) @app.on_message(filters.command(["getsticker"], COMMAND_HANDLER))
@ratelimiter @ratelimiter
async def getsticker_(c, m): @use_chat_lang()
async def getsticker_(c, m, strings):
if sticker := m.reply_to_message.sticker: if sticker := m.reply_to_message.sticker:
if sticker.is_animated: if sticker.is_animated:
await m.reply_text("Animated sticker is not supported!") await m.reply_text(strings("no_anim_stick"))
else: else:
with tempfile.TemporaryDirectory() as tempdir: with tempfile.TemporaryDirectory() as tempdir:
path = os.path.join(tempdir, "getsticker") path = os.path.join(tempdir, "getsticker")
@ -56,11 +58,11 @@ async def getsticker_(c, m):
) )
await m.reply_to_message.reply_document( await m.reply_to_message.reply_document(
document=sticker_file, document=sticker_file,
caption=(f"<b>Emoji:</b> {sticker.emoji}\n" f"<b>Sticker ID:</b> <code>{sticker.file_id}</code>\n\n" f"<b>Send by:</b> @{BOT_USERNAME}"), caption=f"<b>Emoji:</b> {sticker.emoji}\n" f"<b>Sticker ID:</b> <code>{sticker.file_id}</code>\n\n" f"<b>Send by:</b> @{BOT_USERNAME}",
) )
shutil.rmtree(tempdir, ignore_errors=True) shutil.rmtree(tempdir, ignore_errors=True)
else: else:
await m.reply_text("This is not a sticker!") await m.reply_text(strings("not_sticker"))
@app.on_message(filters.command("stickerid", COMMAND_HANDLER) & filters.reply) @app.on_message(filters.command("stickerid", COMMAND_HANDLER) & filters.reply)
@ -72,9 +74,10 @@ async def getstickerid(c, m):
@app.on_message(filters.command("unkang", COMMAND_HANDLER) & filters.reply) @app.on_message(filters.command("unkang", COMMAND_HANDLER) & filters.reply)
@ratelimiter @ratelimiter
async def getstickerid(c, m): @use_chat_lang()
async def getstickerid(c, m, strings):
if m.reply_to_message.sticker: if m.reply_to_message.sticker:
pp = await m.reply_text("Trying to remove from pack..") pp = await m.reply_text(strings("unkang_msg"))
try: try:
decoded = FileId.decode(m.reply_to_message.sticker.file_id) decoded = FileId.decode(m.reply_to_message.sticker.file_id)
sticker = InputDocument( sticker = InputDocument(
@ -83,19 +86,20 @@ async def getstickerid(c, m):
file_reference=decoded.file_reference, file_reference=decoded.file_reference,
) )
await app.invoke(RemoveStickerFromSet(sticker=sticker)) await app.invoke(RemoveStickerFromSet(sticker=sticker))
await pp.edit("Sticker has been removed from your pack") await pp.edit(strings("unkang_success"))
except Exception as e: except Exception as e:
await pp.edit(f"Failed remove sticker from your pack.\n\nERR: {e}") await pp.edit(strings("unkang_error").format(e=e))
else: else:
await m.reply_text(f"Please reply sticker that created by {c.me.username} to remove sticker from your pack.") await m.reply_text(strings("unkang_help").format(c=c.me.username))
@app.on_message(filters.command(["curi", "kang"], COMMAND_HANDLER)) @app.on_message(filters.command(["curi", "kang"], COMMAND_HANDLER))
@ratelimiter @ratelimiter
async def kang_sticker(c, m): @use_chat_lang()
async def kang_sticker(c, m, strings):
if not m.from_user: if not m.from_user:
return await m.reply_text("You are anon admin, kang stickers in my pm.") return await m.reply_text(strings("anon_warn"))
prog_msg = await m.reply_text("Trying to steal your sticker...") prog_msg = await m.reply_text(strings("kang_msg"))
sticker_emoji = "🤔" sticker_emoji = "🤔"
packnum = 0 packnum = 0
packname_found = False packname_found = False
@ -131,7 +135,7 @@ async def kang_sticker(c, m):
animated = True animated = True
elif reply.sticker: elif reply.sticker:
if not reply.sticker.file_name: if not reply.sticker.file_name:
return await prog_msg.edit_text("The sticker has no name.") return await prog_msg.edit_text(strings("stick_no_name"))
if reply.sticker.emoji: if reply.sticker.emoji:
sticker_emoji = reply.sticker.emoji sticker_emoji = reply.sticker.emoji
animated = reply.sticker.is_animated animated = reply.sticker.is_animated
@ -186,7 +190,7 @@ async def kang_sticker(c, m):
sticker_emoji = "".join(set(EMOJI_PATTERN.findall("".join(m.command[2:])))) or sticker_emoji sticker_emoji = "".join(set(EMOJI_PATTERN.findall("".join(m.command[2:])))) or sticker_emoji
resize = True resize = True
else: else:
return await prog_msg.edit_text("Want me to guess the sticker? Please tag a sticker.") return await prog_msg.edit_text(strings("kang_help"))
try: try:
if resize: if resize:
filename = resize_image(filename) filename = resize_image(filename)
@ -226,7 +230,7 @@ async def kang_sticker(c, m):
msg_ = media.updates[-1].message msg_ = media.updates[-1].message
stkr_file = msg_.media.document stkr_file = msg_.media.document
if packname_found: if packname_found:
await prog_msg.edit_text("<code>Using existing sticker pack...</code>") await prog_msg.edit_text(strings("exist_pack"))
await c.invoke( await c.invoke(
AddStickerToSet( AddStickerToSet(
stickerset=InputStickerSetShortName(short_name=packname), stickerset=InputStickerSetShortName(short_name=packname),
@ -241,7 +245,7 @@ async def kang_sticker(c, m):
) )
) )
else: else:
await prog_msg.edit_text("<b>Creating a new sticker pack...</b>") await prog_msg.edit_text(strings("new_packs"))
stkr_title = f"{m.from_user.first_name}'s" stkr_title = f"{m.from_user.first_name}'s"
if animated: if animated:
stkr_title += "AnimPack" stkr_title += "AnimPack"
@ -271,12 +275,12 @@ async def kang_sticker(c, m):
) )
except PeerIdInvalid: except PeerIdInvalid:
return await prog_msg.edit_text( return await prog_msg.edit_text(
"It looks like you've never interacted with me in private chat, you need to do that first..", strings("please_start_msg"),
reply_markup=InlineKeyboardMarkup( reply_markup=InlineKeyboardMarkup(
[ [
[ [
InlineKeyboardButton( InlineKeyboardButton(
"Click Me", strings("click_me"),
url=f"https://t.me/{c.me.username}?start", url=f"https://t.me/{c.me.username}?start",
) )
] ]
@ -285,7 +289,7 @@ async def kang_sticker(c, m):
) )
except BadRequest: except BadRequest:
return await prog_msg.edit_text("Your Sticker Pack is full if your pack is not in v1 Type /kang 1, if it is not in v2 Type /kang 2 and so on.") return await prog_msg.edit_text(strings("pack_full"))
except Exception as all_e: except Exception as all_e:
await prog_msg.edit_text(f"{all_e.__class__.__name__} : {all_e}") await prog_msg.edit_text(f"{all_e.__class__.__name__} : {all_e}")
else: else:
@ -293,14 +297,14 @@ async def kang_sticker(c, m):
[ [
[ [
InlineKeyboardButton( InlineKeyboardButton(
text="👀 View Your Pack", text=strings("viewpack"),
url=f"https://t.me/addstickers/{packname}", url=f"https://t.me/addstickers/{packname}",
) )
] ]
] ]
) )
await prog_msg.edit_text( await prog_msg.edit_text(
f"<b>Sticker successfully stolen!</b>\n<b>Emoji:</b> {sticker_emoji}", strings("kang_success").format(emot=sticker_emoji),
reply_markup=markup, reply_markup=markup,
) )
# Cleanup # Cleanup

View file

@ -9,7 +9,6 @@ from pyrogram import filters
from misskaty import app from misskaty import app
from misskaty.core.decorator.ratelimiter import ratelimiter from misskaty.core.decorator.ratelimiter import ratelimiter
from misskaty.core.message_utils import * from misskaty.core.message_utils import *
from misskaty.helper import http
from misskaty.vars import COMMAND_HANDLER from misskaty.vars import COMMAND_HANDLER
from .web_scraper import split_arr from .web_scraper import split_arr
@ -18,21 +17,22 @@ LOGGER = logging.getLogger(__name__)
SUB_TITLE_DICT = {} SUB_TITLE_DICT = {}
SUB_DL_DICT = {} SUB_DL_DICT = {}
# Get list title based on query # Get list title based on query
async def getTitleSub(msg, kueri, CurrentPage, user): async def getTitleSub(msg, kueri, CurrentPage, user):
if not SUB_TITLE_DICT.get(msg.id): if not SUB_TITLE_DICT.get(msg.id):
sdata = [] sdata = []
scraper = cfscrape.create_scraper() scraper = cfscrape.create_scraper()
param = {"query": kueri} param = {"query": kueri}
r = scraper.post("https://subscene.com/subtitles/searchbytitle", data=param).text r = scraper.post("https://subscene.com/subtitles/searchbytitle", data=param).text
soup = BeautifulSoup(r,"lxml") soup = BeautifulSoup(r, "lxml")
lists = soup.find("div", {"class": "search-result"}) lists = soup.find("div", {"class": "search-result"})
entry = lists.find_all("div", {"class":"title"}) entry = lists.find_all("div", {"class": "title"})
# if "Tidak Ditemukan" in entry[0].text: # if "Tidak Ditemukan" in entry[0].text:
# await editPesan(msg, f"Sorry, could not find any result for: {kueri}") # await editPesan(msg, f"Sorry, could not find any result for: {kueri}")
# return None, 0, None # return None, 0, None
for sub in entry: for sub in entry:
title = sub.find('a').text title = sub.find("a").text
link = f"https://subscene.com{sub.find('a').get('href')}" link = f"https://subscene.com{sub.find('a').get('href')}"
sdata.append({"title": title, "link": link}) sdata.append({"title": title, "link": link})
SUB_TITLE_DICT[msg.id] = [split_arr(sdata, 10), kueri] SUB_TITLE_DICT[msg.id] = [split_arr(sdata, 10), kueri]
@ -54,14 +54,15 @@ async def getTitleSub(msg, kueri, CurrentPage, user):
await editPesan(msg, "Sorry could not find any matching results!") await editPesan(msg, "Sorry could not find any matching results!")
return None, 0, None return None, 0, None
# Get list all subtitles from title # Get list all subtitles from title
async def getListSub(msg, link, CurrentPage, user): async def getListSub(msg, link, CurrentPage, user):
if not SUB_DL_DICT.get(msg.id): if not SUB_DL_DICT.get(msg.id):
sdata = [] sdata = []
scraper = cfscrape.create_scraper() scraper = cfscrape.create_scraper()
kuki = {'LanguageFilter': "13,44,50"} # Only filter language English, Malay, Indonesian kuki = {"LanguageFilter": "13,44,50"} # Only filter language English, Malay, Indonesian
r = scraper.get(link, cookies=kuki).text r = scraper.get(link, cookies=kuki).text
soup = BeautifulSoup(r,"lxml") soup = BeautifulSoup(r, "lxml")
for i in soup.findAll(class_="a1"): for i in soup.findAll(class_="a1"):
lang = i.find("a").findAll("span")[0].text.strip() lang = i.find("a").findAll("span")[0].text.strip()
title = i.find("a").findAll("span")[1].text.strip() title = i.find("a").findAll("span")[1].text.strip()
@ -92,6 +93,7 @@ async def getListSub(msg, link, CurrentPage, user):
await editPesan(msg, "Sorry could not find any matching results!") await editPesan(msg, "Sorry could not find any matching results!")
return None, 0, None return None, 0, None
# Subscene CMD # Subscene CMD
@app.on_message(filters.command(["subscene"], COMMAND_HANDLER)) @app.on_message(filters.command(["subscene"], COMMAND_HANDLER))
@ratelimiter @ratelimiter
@ -113,6 +115,7 @@ async def subsceneCMD(client, message):
keyboard.row(InlineButton("❌ Close", f"close#{message.from_user.id}")) keyboard.row(InlineButton("❌ Close", f"close#{message.from_user.id}"))
await editPesan(pesan, subres, disable_web_page_preview=True, reply_markup=keyboard) await editPesan(pesan, subres, disable_web_page_preview=True, reply_markup=keyboard)
# Callback list title # Callback list title
@app.on_callback_query(filters.create(lambda _, __, query: "subscenepage#" in query.data)) @app.on_callback_query(filters.create(lambda _, __, query: "subscenepage#" in query.data))
@ratelimiter @ratelimiter
@ -142,6 +145,7 @@ async def subpage_callback(client, callback_query):
keyboard.row(InlineButton("❌ Close", f"close#{callback_query.from_user.id}")) keyboard.row(InlineButton("❌ Close", f"close#{callback_query.from_user.id}"))
await editPesan(callback_query.message, subres, disable_web_page_preview=True, reply_markup=keyboard) await editPesan(callback_query.message, subres, disable_web_page_preview=True, reply_markup=keyboard)
# Callback list title # Callback list title
@app.on_callback_query(filters.create(lambda _, __, query: "sublist#" in query.data)) @app.on_callback_query(filters.create(lambda _, __, query: "sublist#" in query.data))
@ratelimiter @ratelimiter
@ -172,6 +176,7 @@ async def subdlpage_callback(client, callback_query):
keyboard.row(InlineButton("❌ Close", f"close#{callback_query.from_user.id}")) keyboard.row(InlineButton("❌ Close", f"close#{callback_query.from_user.id}"))
await editPesan(callback_query.message, subres, disable_web_page_preview=True, reply_markup=keyboard) await editPesan(callback_query.message, subres, disable_web_page_preview=True, reply_markup=keyboard)
# Callback dl subtitle # Callback dl subtitle
@app.on_callback_query(filters.create(lambda _, __, query: "extractsubs#" in query.data)) @app.on_callback_query(filters.create(lambda _, __, query: "extractsubs#" in query.data))
@ratelimiter @ratelimiter
@ -191,6 +196,6 @@ async def dlsub_callback(client, callback_query):
scraper = cfscrape.create_scraper() scraper = cfscrape.create_scraper()
res = await down_page(link) res = await down_page(link)
dl = scraper.get(res.get("download_url")) dl = scraper.get(res.get("download_url"))
f = open(f"{title}.zip", mode='wb').write(dl.content) f = open(f"{title}.zip", mode="wb").write(dl.content)
await callback_query.message.reply_document(f"{title}.zip", caption=f"Title: {res.get('title')}\nIMDb: {res['imdb']}\nAuthor: {res['author_name']}\nRelease Info: ") await callback_query.message.reply_document(f"{title}.zip", caption=f"Title: {res.get('title')}\nIMDb: {res['imdb']}\nAuthor: {res['author_name']}\nRelease Info: ")
os.remove(f"{title}.zip") os.remove(f"{title}.zip")

View file

@ -49,10 +49,7 @@ def split_arr(arr, size: 5):
# Terbit21 GetData # Terbit21 GetData
async def getDataTerbit21(msg, kueri, CurrentPage): async def getDataTerbit21(msg, kueri, CurrentPage):
if not SCRAP_DICT.get(msg.id): if not SCRAP_DICT.get(msg.id):
if not kueri: 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()
terbitjson = (await http.get("https://yasirapi.eu.org/terbit21")).json()
else:
terbitjson = (await http.get(f"https://yasirapi.eu.org/terbit21?q={kueri}")).json()
if not terbitjson.get("result"): if not terbitjson.get("result"):
await editPesan(msg, "Sorry, could not find any results!") await editPesan(msg, "Sorry, could not find any results!")
return None, None return None, None
@ -68,8 +65,7 @@ async def getDataTerbit21(msg, kueri, CurrentPage):
for c, i in enumerate(SCRAP_DICT[msg.id][0][index], start=1): for c, i in enumerate(SCRAP_DICT[msg.id][0][index], start=1):
TerbitRes += f"<b>{c}. <a href='{i['link']}'>{i['judul']}</a></b>\n<b>Category:</b> <code>{i['kategori']}</code>\n" TerbitRes += f"<b>{c}. <a href='{i['link']}'>{i['judul']}</a></b>\n<b>Category:</b> <code>{i['kategori']}</code>\n"
TerbitRes += "\n" if re.search(r"Complete|Ongoing", i["kategori"]) else f"💠 <b><a href='{i['dl']}'>Download</a></b>\n\n" TerbitRes += "\n" if re.search(r"Complete|Ongoing", i["kategori"]) else f"💠 <b><a href='{i['dl']}'>Download</a></b>\n\n"
IGNORE_CHAR = "[]" TerbitRes = "".join(i for i in TerbitRes if i not in "[]")
TerbitRes = "".join(i for i in TerbitRes if not i in IGNORE_CHAR)
return TerbitRes, PageLen return TerbitRes, PageLen
except (IndexError, KeyError): except (IndexError, KeyError):
await editPesan(msg, "Sorry, could not find any results!") await editPesan(msg, "Sorry, could not find any results!")
@ -79,10 +75,7 @@ async def getDataTerbit21(msg, kueri, CurrentPage):
# LK21 GetData # LK21 GetData
async def getDatalk21(msg, kueri, CurrentPage): async def getDatalk21(msg, kueri, CurrentPage):
if not SCRAP_DICT.get(msg.id): if not SCRAP_DICT.get(msg.id):
if not kueri: 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()
lk21json = (await http.get("https://yasirapi.eu.org/lk21")).json()
else:
lk21json = (await http.get(f"https://yasirapi.eu.org/lk21?q={kueri}")).json()
if not lk21json.get("result"): if not lk21json.get("result"):
await editPesan(msg, "Sorry could not find any matching results!") await editPesan(msg, "Sorry could not find any matching results!")
return None, None return None, None
@ -98,8 +91,7 @@ async def getDatalk21(msg, kueri, CurrentPage):
for c, i in enumerate(SCRAP_DICT[msg.id][0][index], start=1): for c, i in enumerate(SCRAP_DICT[msg.id][0][index], start=1):
lkResult += f"<b>{c}. <a href='{i['link']}'>{i['judul']}</a></b>\n<b>Category:</b> <code>{i['kategori']}</code>\n" lkResult += f"<b>{c}. <a href='{i['link']}'>{i['judul']}</a></b>\n<b>Category:</b> <code>{i['kategori']}</code>\n"
lkResult += "\n" if re.search(r"Complete|Ongoing", i["kategori"]) else f"💠 <b><a href='{i['dl']}'>Download</a></b>\n\n" lkResult += "\n" if re.search(r"Complete|Ongoing", i["kategori"]) else f"💠 <b><a href='{i['dl']}'>Download</a></b>\n\n"
IGNORE_CHAR = "[]" lkResult = "".join(i for i in lkResult if i not in "[]")
lkResult = "".join(i for i in lkResult if not i in IGNORE_CHAR)
return lkResult, PageLen return lkResult, PageLen
except (IndexError, KeyError): except (IndexError, KeyError):
await editPesan(msg, "Sorry could not find any matching results!") await editPesan(msg, "Sorry could not find any matching results!")
@ -198,7 +190,7 @@ async def getDataMovieku(msg, kueri, CurrentPage):
async def getDataSavefilm21(msg, kueri, CurrentPage, user): async def getDataSavefilm21(msg, kueri, CurrentPage, user):
if not SCRAP_DICT.get(msg.id): if not SCRAP_DICT.get(msg.id):
sfdata = [] sfdata = []
data = await http.get(f"https://193.43.104.235/?s={kueri}", headers=headers) data = await http.get(f"https://savefilm21.pro/?s={kueri}", headers=headers)
text = BeautifulSoup(data, "lxml") text = BeautifulSoup(data, "lxml")
entry = text.find_all(class_="entry-header") entry = text.find_all(class_="entry-header")
if "Tidak Ditemukan" in entry[0].text: if "Tidak Ditemukan" in entry[0].text:

View file

@ -1,4 +1,3 @@
import os
from asyncio import gather from asyncio import gather
from pyrogram import filters from pyrogram import filters
@ -7,7 +6,7 @@ from misskaty import app
from misskaty.core.message_utils import * from misskaty.core.message_utils import *
from misskaty.core.decorator.errors import capture_err from misskaty.core.decorator.errors import capture_err
from misskaty.core.decorator.ratelimiter import ratelimiter 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 from misskaty.vars import COMMAND_HANDLER
__MODULE__ = "WebSS" __MODULE__ = "WebSS"
@ -19,15 +18,16 @@ __HELP__ = """
@app.on_message(filters.command(["webss"], COMMAND_HANDLER)) @app.on_message(filters.command(["webss"], COMMAND_HANDLER))
@capture_err @capture_err
@ratelimiter @ratelimiter
async def take_ss(_, m): @use_chat_lang()
async def take_ss(_, m, strings):
if len(m.command) == 1: if len(m.command) == 1:
return await kirimPesan(m, "Give A Url To Fetch Screenshot.") return await kirimPesan(m, strings("no_url"))
url = m.command[1] if m.command[1].startswith("http") else f"https://{m.command[1]}" url = m.command[1] if m.command[1].startswith("http") else f"https://{m.command[1]}"
filename = f"webSS_{m.from_user.id}.png" filename = f"webSS_{m.from_user.id}.png"
msg = await m.reply("Capturing screenshot...") msg = await m.reply(strings("wait_str"))
try: try:
url = f"https://webss.yasirapi.eu.org/api?url={url}&width=1280&height=720" url = f"https://webss.yasirapi.eu.org/api?url={url}&width=1280&height=720"
await gather(*[m.reply_document(url, file_name=filename), m.reply_photo(url)]) await gather(*[m.reply_document(url, file_name=filename), m.reply_photo(url)])
await hapusPesan(msg) await hapusPesan(msg)
except Exception as e: except Exception as e:
await editPesan(msg, f"Failed To Take Screenshot. {str(e)}") await editPesan(msg, strings("ss_failed_str").format(err=str(e)))

View file

@ -23,12 +23,14 @@ except:
load_dotenv("config.env", override=True) load_dotenv("config.env", override=True)
def getConfig(name: str): def getConfig(name: str):
try: try:
return environ[name] return environ[name]
except: except:
return "" return ""
# Required ENV # Required ENV
try: try:
BOT_TOKEN = getConfig("BOT_TOKEN") BOT_TOKEN = getConfig("BOT_TOKEN")
@ -42,7 +44,7 @@ try:
except Exception as e: except Exception as e:
LOGGER.error(f"One or more env variables missing! Exiting now.\n{e}") LOGGER.error(f"One or more env variables missing! Exiting now.\n{e}")
sys.exit(1) sys.exit(1)
TZ = environ.get("TZ", "Asia/Jakarta") TZ = environ.get("TZ", "Asia/Jakarta")
COMMAND_HANDLER = environ.get("COMMAND_HANDLER", "! /").split() COMMAND_HANDLER = environ.get("COMMAND_HANDLER", "! /").split()
SUDO = list( SUDO = list(

View file

@ -1,4 +1,4 @@
from subprocess import run as srun from subprocess import run as srun
import logging, os, requests import logging, os, requests
from dotenv import load_dotenv from dotenv import load_dotenv
@ -24,26 +24,31 @@ load_dotenv("config.env", override=True)
UPSTREAM_REPO_URL = os.environ.get("UPSTREAM_REPO_URL", "") UPSTREAM_REPO_URL = os.environ.get("UPSTREAM_REPO_URL", "")
if len(UPSTREAM_REPO_URL) == 0: if len(UPSTREAM_REPO_URL) == 0:
UPSTREAM_REPO_URL = None UPSTREAM_REPO_URL = None
UPSTREAM_REPO_BRANCH = os.environ.get("UPSTREAM_REPO_BRANCH", "") UPSTREAM_REPO_BRANCH = os.environ.get("UPSTREAM_REPO_BRANCH", "")
if len(UPSTREAM_REPO_BRANCH) == 0: if len(UPSTREAM_REPO_BRANCH) == 0:
UPSTREAM_REPO_BRANCH = "master" UPSTREAM_REPO_BRANCH = "master"
if UPSTREAM_REPO_URL is not None: if UPSTREAM_REPO_URL is not None:
if os.path.exists('.git'): if os.path.exists(".git"):
srun(["rm", "-rf", ".git"]) srun(["rm", "-rf", ".git"])
update = srun([f"git init -q \ update = srun(
[
f"git init -q \
&& git config --global user.email mail@yasir.eu.org \ && git config --global user.email mail@yasir.eu.org \
&& git config --global user.name yasirarism \ && git config --global user.name yasirarism \
&& git add . \ && git add . \
&& git commit -sm update -q \ && git commit -sm update -q \
&& git remote add origin {UPSTREAM_REPO_URL} \ && git remote add origin {UPSTREAM_REPO_URL} \
&& git fetch origin -q \ && git fetch origin -q \
&& git reset --hard origin/{UPSTREAM_REPO_BRANCH} -q"], shell=True) && git reset --hard origin/{UPSTREAM_REPO_BRANCH} -q"
],
shell=True,
)
if update.returncode == 0: if update.returncode == 0:
LOGGER.error('Successfully updated with latest commit from UPSTREAM_REPO') LOGGER.error("Successfully updated with latest commit from UPSTREAM_REPO")
else: else:
LOGGER.error('Something went wrong while updating, check UPSTREAM_REPO if valid or not!') LOGGER.error("Something went wrong while updating, check UPSTREAM_REPO if valid or not!")