__version__ = (1, 0, 28) # ©️ Dan Gazizullin, 2021-2022 # This file is a part of Hikka Userbot # 🌐 https://github.com/hikariatama/Hikka # You can redistribute it and/or modify it under the terms of the GNU AGPLv3 # 🔑 https://www.gnu.org/licenses/agpl-3.0.html # meta pic: https://0x0.st/oRer.webp # meta banner: https://mods.hikariatama.ru/badges/nekospy.jpg # meta developer: @hikarimods # scope: hikka_only # scope: hikka_min 1.6.0 import contextlib import io import logging import time import typing from telethon.tl.types import ( DocumentAttributeFilename, Message, PeerChat, UpdateDeleteChannelMessages, UpdateDeleteMessages, UpdateEditChannelMessage, UpdateEditMessage, ) from telethon.utils import get_display_name from .. import loader, utils logger = logging.getLogger(__name__) @loader.tds class NekoSpy(loader.Module): """Sends you deleted and / or edited messages from selected users""" rei = "👩‍🎤" groups = "👥" pm = "👤" strings = { "name": "NekoSpy", "state": f"{rei} Spy mode is now {{}}", "spybl": f"{rei} Current chat added to blacklist for spying", "spybl_removed": f"{rei} Current chat removed from blacklist for spying", "spybl_clear": f"{rei} Ignore list for spying cleared", "spywl": f"{rei} Current chat added to whitelist for spying", "spywl_removed": f"{rei} Current chat removed from whitelist for spying", "spywl_clear": f"{rei} Include list for spying cleared", "whitelist": f"\n{rei} Tracking only messages from:\n{{}}", "always_track": f"\n{rei} Always tracking messages from:\n{{}}", "blacklist": f"\n{rei} Ignoring messages from:\n{{}}", "chat": f"{groups} Tracking messages in groups\n", "pm": f"{pm} Tracking messages in personal messages\n", "mode_off": f"{pm} Not tracking messages {{}}spymode\n", "deleted_pm": ( '🗑 {} deleted message in' " pm. Content:\n{}" ), "deleted_chat": ( '🗑 Message in chat {} by {} has been deleted. Content:\n{}' ), "edited_pm": ( '🔏 {} edited message' " in pm." " Old content:\n{}" ), "edited_chat": ( '🔏 Message in chat {}' " by {} has been edited. Old content:\n{}' ), "on": "on", "off": "off", "cfg_enable_pm": "Enable spy mode in Personal messages", "cfg_enable_groups": "Enable spy mode in Groups", "cfg_whitelist": "List of chats to include messages from", "cfg_blacklist": "List of chats to exclude messages from", "cfg_always_track": ( "List of chats to always track messages from, no matter what" ), "cfg_log_edits": "Log information about messages being edited", "cfg_ignore_inline": "Ignore inline messages (sent using @via bots)", "cfg_fw_protect": "Interval of messages sending to prevent floodwait", "sd_media": ( "🔥 {} sent you a self-destructing" " media" ), "save_sd": ( "🔥 Saving" " self-destructing media\n" ), "cfg_save_sd": "Save self-destructing media", } strings_ru = { "on": "включен", "off": "выключен", "state": f"{rei} Режим слежения теперь {{}}", "spybl": f"{rei} Текущий чат добавлен в черный список для слежения", "spybl_removed": ( f"{rei} Текущий чат удален из черного списка для слежения" ), "spybl_clear": f"{rei} Черный список для слежения очищен", "spywl": f"{rei} Текущий чат добавлен в белый список для слежения", "spywl_removed": ( f"{rei} Текущий чат удален из белого списка для слежения" ), "spywl_clear": f"{rei} Белый список для слежения очищен", "whitelist": ( f"\n{rei} Слежу только" " за сообщениями от пользователей / групп:\n{}" ), "always_track": ( f"\n{rei} Всегда слежу за сообщениями от пользователей /" " групп:\n{}" ), "blacklist": ( f"\n{rei} Игнорирую сообщений от пользователей / групп:\n{{}}" ), "chat": f"{groups} Слежу за сообщениями в группах\n", "pm": f"{pm} Слежу за сообщениями в личных сообщениях\n", "deleted_pm": ( '🗑 {} удалил сообщение в' " личке. Содержимое:\n{}" ), "deleted_chat": ( '🗑 Сообщение в чате {} от' ' {} было удалено. Содержимое:\n{}' ), "edited_pm": ( '🔏 {} отредактировал сообщение в личке. Старое содержимое:\n{}' ), "edited_chat": ( '🔏 Сообщение в чате {} от' ' {} было отредактировано. Старое содержимое:\n{}' ), "mode_off": f"{pm} Не отслеживаю сообщения {{}}spymode\n", "cfg_enable_pm": "Включить режим шпиона в личных сообщениях", "cfg_enable_groups": "Включить режим шпиона в группах", "cfg_whitelist": "Список чатов, от которых нужно сохранять сообщения", "cfg_blacklist": "Список чатов, от которых нужно игнорировать сообщения", "cfg_always_track": ( "Список чатов, от которых всегда следует отслеживать сообщения," " несмотря ни на что" ), "cfg_log_edits": "Сохранять отредактированные сообщения", "cfg_ignore_inline": "Игнорировать сообщения из инлайн-режима", "cfg_fw_protect": "Защита от флудвейтов при пересылке", "_cls_doc": ( "Сохраняет удаленные и/или отредактированные сообщения от выбранных" " пользователей" ), "sd_media": ( "🔥 {} отправил вам самоуничтожающееся" " медиа" ), "save_sd": ( "🔥 Сохраняю" " самоуничтожающиеся медиа\n" ), "cfg_save_sd": "Сохранять самоуничтожающееся медиа", } strings_it = { "on": "attivato", "off": "disattivato", "state": f"{rei} Modalità di tracciamento ora {{}}", "spybl": ( f"{rei} Il gruppo corrente è stato aggiunto alla lista nera di" " tracciamento" ), "spybl_removed": ( f"{rei} Il gruppo corrente è stato rimosso dalla lista nera di" " tracciamento" ), "spybl_clear": f"{rei} Lista nera di tracciamento ripulita", "spywl": ( f"{rei} Il gruppo corrente è stato aggiunto alla lista bianca di" " tracciamento" ), "spywl_removed": ( f"{rei} Il gruppo corrente è stato rimosso dalla lista bianca di" " tracciamento" ), "spywl_clear": f"{rei} Lista bianca di tracciamento ripulita", "whitelist": ( f"\n{rei} Sto tracciando solo messaggi da utenti / gruppi:\n{{}}" ), "always_track": ( f"\n{rei} Sto tracciando sempre messaggi da utenti / gruppi:\n{{}}" ), "blacklist": f"\n{rei} Ignoro messaggi da utenti / gruppi:\n{{}}", "chat": f"{groups} Sto tracciando i messaggi nei gruppi\n", "pm": f"{pm} Sto tracciando i messaggi nei messaggi privati\n", "deleted_pm": ( '🗑 {} ha cancellato il' " messaggio in privato. Contenuto:\n{}" ), "deleted_pm": ( '🗑 {} ha eliminato un messaggio in privato. Contenuto:\n{}' ), "deleted_chat": ( '🗑 Un messaggio nel gruppo {} da {} è stato eliminato.' " Contenuto:\n{}" ), "edited_pm": ( '🔏 {} ha modificato un' " messaggio in privato. Vecchio contenuto:\n{}" ), "edited_chat": ( '🔏 Un messaggio nel gruppo {} da {} è stato modificato. Vecchio' " contenuto:\n{}" ), "mode_off": ( f"{pm} Non sto tenendo traccia dei messaggi" " {}spymode\n" ), "cfg_enable_pm": "Attiva modalità spia nei messaggi privati", "cfg_enable_groups": "Attiva modalità spia nei gruppi", "cfg_whitelist": "Lista dei gruppi da cui tenere traccia dei messaggi", "cfg_blacklist": "Lista dei gruppi da cui ignorare i messaggi", "cfg_always_track": ( "Lista dei gruppi da cui tenere traccia dei messaggi," " non importa quello che succede" ), "cfg_log_edits": "Salva i messaggi modificati", "cfg_ignore_inline": "Ignora i messaggi in modalità inline", "cfg_fw_protect": "Protezione contro floodwate ai messaggi inoltrati", "_cls_doc": "Salva i messaggi eliminati e/o modificati da utenti selezionati", "sd_media": ( "🔥 {} ti ha inviato un media" " che si autodistrugge" ), "save_sd": ( "🔥 Salvo" " i media che si autodistruggono\n" ), "cfg_save_sd": "Salva i media che si autodistruggono", } strings_de = { "on": "Aktiviert", "off": "Deaktiviert", "state": f"{rei} Der Tracking-Modus ist jetzt {{}}.", "spybl": ( f"{rei} Der aktuelle Chat wurde zur Spionage-Blacklist hinzugefügt." ), "spybl_removed": ( f"{rei} Der aktuelle Chat wurde von der Spionage-Blacklist entfernt." ), "spybl_clear": f"{rei} Die Spionage-Blacklist wurde geleert.", "spywl": ( f"{rei} Der aktuelle Chat wurde zur Spionage-Whitelist hinzugefügt." ), "spywl_removed": ( f"{rei} Der aktuelle Chat wurde von der Spionage-Whitelist entfernt." ), "spywl_clear": f"{rei} Die Spionage-Whitelist wurde geleert.", "whitelist": f"\n{rei} Ich beobachte nur Nachrichten von:\n{{}}", "always_track": f"\n{rei} Ich beobachte immer Nachrichten von:\n{{}}", "blacklist": f"\n{rei} Ich ignoriere Nachrichten von:\n{{}}", "chat": f"{groups} Ich beobachte Nachrichten in Gruppen.\n", "pm": f"{pm} Ich beobachte Nachrichten in privaten Nachrichten.\n", "deleted_pm": ( '🗑 {} hat eine private Nachricht gelöscht. Inhalt:\n{}' ), "deleted_chat": ( '🗑 Die Nachricht im Chat {}' ' von {} wurde gelöscht. Inhalt:\n{}' ), "edited_pm": ( '🔏 {} hat eine private Nachricht bearbeitet. Alte Nachricht:\n{}' ), "edited_chat": ( '🔏 Die Nachricht im Chat {}' ' von {} wurde bearbeitet. Alte Nachricht:\n{}' ), "mode_off": ( f"{pm} Ich beobachte" " Nachrichten nicht mehr. {}spymode\n" ), "cfg_enable_pm": "Aktivieren Sie den Spionage-Modus in privaten Nachrichten", "cfg_enable_groups": "Aktivieren Sie den Spionage-Modus in Gruppen", "cfg_whitelist": ( "Liste der Gruppen, von denen Nachrichten gespeichert werden sollen" ), "cfg_blacklist": ( "Liste der Gruppen, von denen Nachrichten ignoriert werden sollen" ), "cfg_always_track": ( "Liste der Gruppen, von denen immer Nachrichten verfolgt werden sollen," " egal was passiert" ), "cfg_log_edits": "Gespeicherte bearbeitete Nachrichten", "cfg_ignore_inline": "Ignoriere Nachrichten aus Inline-Modus", "cfg_fw_protect": "Schutz vor Floodwässern beim Weiterleiten", "_cls_doc": ( "Speichert gelöschte bearbeitete Nachrichten von ausgewählten Benutzern" ), "sd_media": ( "🔥 {} hat Ihnen ein selbstzerstörendes" " Medium gesendet" ), "save_sd": ( "🔥 Speichere" " selbstzerstörende Medien\n" ), "cfg_save_sd": "Speichern Sie selbstzerstörende Medien", } strings_uz = { "on": "yoqildi", "off": "o'chirildi", "state": f"{rei} Shu paytda spy rejimi {{}}", "spybl": f"{rei} Ushbu chat spay rejimining qora ro'yxatiga qo'shildi", "spybl_removed": ( f"{rei} Ushbu chat spay rejimining qora ro'yxatidan olib tashlandi" ), "spybl_clear": f"{rei} Spay rejimining qora ro'yxati tozalandi", "spywl": f"{rei} Ushbu chat spay rejimining oq ro'yxatiga qo'shildi", "spywl_removed": ( f"{rei} Ushbu chat spay rejimining oq ro'yxatidan olib tashlandi" ), "spywl_clear": f"{rei} Spay rejimining oq ro'yxati tozalandi", "whitelist": f"\n{rei} Faqat kelgan xabarlarni kuzatish\n{{}}", "always_track": f"\n{rei} Har doim kelgan xabarlarni kuzatish\n{{}}", "blacklist": f"\n{rei} kelgan xabarlarni o'chirish\n{{}}", "chat": f"{groups} Gruplardagi xabarlarimni kuzatish\n", "pm": f"{pm} Shaxsiy xabarlarimni kuzatish\n", "deleted_pm": ( '🗑 {} shaxsiy xabarni' " o'chirdi. Xabar:\n{}" ), "deleted_chat": ( '🗑 {} guruhdan {} xabarni o\'chirdi. Xabar:\n{}' ), "edited_pm": ( '🔏 {} shaxsiy xabarni' " tahrirladi. Eski xabar:\n{}" ), "edited_chat": ( '🔏 {} guruhdan {} xabarni tahrirladi. Eski xabar:\n{}' ), "mode_off": ( f"{pm} Xabarlarimni kuzatishni to'xtatdim{{}}spymode\n" ), "cfg_enable_pm": "Shaxsiy xabarlarimni kuzatishni yoqish", "cfg_enable_groups": "Guruh xabarlarimni kuzatishni yoqish", "cfg_whitelist": "Xabarlarni saqlash kerak bo'lgan suhbatlar ro'yxati", "cfg_blacklist": "Xabarlarni o'chirish kerak bo'lgan suhbatlar ro'yxati", "cfg_always_track": ( "Nima bo'lishidan qat'i nazar, har doim xabarlarni kuzatib boradigan" " suhbatlar ro'yxati" ), "cfg_log_edits": "Saqlangan tahrirlangan xabarlarni", "cfg_ignore_inline": "Inline rejimidan kelgan xabarlarni o'chirish", "cfg_fw_protect": "Forwarding floodlardan himoyalash", "_cls_doc": ( "Tanlangan foydalanuvchilardan kelgan va/yoki o'chirilgan yoki tahrirlangan" " xabarlarni saqlaydi" ), "sd_media": ( "🔥 {} sizga o'chiriladigan media" " yubordi" ), "save_sd": ( "🔥 O'z-o'zini yo'q" " qiladigan ommaviy axborot vositalarini saqlash\n" ), "cfg_save_sd": "O'chiriladigan media saqlash", } strings_tr = { "on": "açık", "off": "kapalı", "state": f"{rei} Şu anda gizli mod {{}}", "spybl": f"{rei} Bu sohbet gizli modun siyah listesine eklendi", "spybl_removed": ( f"{rei} Bu sohbet gizli modun siyah listesinden kaldırıldı" ), "spybl_clear": f"{rei} Gizli modun siyah listesi temizlendi", "spywl": f"{rei} Bu sohbet gizli modun beyaz listesine eklendi", "spywl_removed": ( f"{rei} Bu sohbet gizli modun beyaz listesinden kaldırıldı" ), "spywl_clear": f"{rei} Gizli modun beyaz listesi temizlendi", "whitelist": f"\n{rei} Sadece belirtilen gelen mesajları kaydet\n{{}}", "always_track": ( f"\n{rei} Her zaman belirtilen gelen mesajları kaydet\n{{}}" ), "blacklist": f"\n{rei} Belirtilen gelen mesajları sil\n{{}}", "chat": f"{groups} Grup mesajlarımı kaydet\n", "pm": f"{pm} Özel mesajlarımı kaydet\n", "deleted_pm": ( '🗑 {} özel mesajı sildi.' " Mesaj:\n{}" ), "deleted_chat": ( '🗑 {} guruptan {} mesajı sildi. Mesaj:\n{}' ), "edited_pm": ( '🔏 {} özel mesajı' " düzenledi. Eski mesaj:\n{}" ), "edited_chat": ( '🔏 {} guruptan {} mesajı düzenledi. Eski mesaj:\n{}' ), "mode_off": ( f"{pm} Mesajlarımı kaydetmeyi kapattım{{}}spymode\n" ), "cfg_enable_pm": "Özel mesajlarımı kaydetmeyi aç", "cfg_enable_groups": "Grup mesajlarımı kaydetmeyi aç", "cfg_whitelist": "Kaydedilmesi gereken sohbetler listesi", "cfg_blacklist": "Silinmesi gereken sohbetler listesi", "cfg_always_track": ( "Ne olursa olsun, iletileri her zaman izlenecek sohbetler listesi" ), "cfg_log_edits": "Kaydedilen düzenlenmiş mesajları", "cfg_ignore_inline": "Inline modundan gelen mesajları sil", "cfg_fw_protect": "Forwarding floodlarından korun", "_cls_doc": ( "Belirtilen kullanıcıların/sohbetlerin silinmiş, düzenlenmiş veya" " kaydedilen mesajlarını kaydeder" ), "sd_media": ( "🔥 {} sana silinebilir medya gönderdi" ), "save_sd": ( "🔥 Kendi kendini imha" " eden medyayı kaydetme\n" ), "cfg_save_sd": "Silinebilir medyayı kaydet", } strings_es = { "on": "activado", "off": "desactivado", "state": f"{rei} El modo espía está actualmente {{}}", "spybl": ( f"{rei} Este chat ha sido añadido a la lista negra del modo espía" ), "spybl_removed": ( f"{rei} Este chat ha sido eliminado de la lista negra del modo espía" ), "spybl_clear": f"{rei} La lista negra del modo espía ha sido limpiada", "spywl": ( f"{rei} Este chat ha sido añadido a la lista blanca del modo espía" ), "spywl_removed": ( f"{rei} Este chat ha sido" " eliminado de la lista blanca del modo espía" ), "spywl_clear": f"{rei} La lista blanca del modo espía ha sido limpiada", "whitelist": ( f"\n{rei} Guardar solo los mensajes de los especificados\n{{}}" ), "always_track": ( f"\n{rei} Guardar siempre los mensajes de los especificados\n{{}}" ), "blacklist": f"\n{rei} Borrar los mensajes de los especificados\n{{}}", "chat": ( "👥 Guardar mis" " mensajes de grupo\n" ), "pm": f"{pm} Guardar mis mensajes privados\n", "deleted_pm": ( '🗑 {} eliminó un mensaje' " privado. Mensaje:\n{}" ), "deleted_chat": ( '🗑 {} eliminó un mensaje de' ' {} en el grupo. Mensaje:\n{}' ), "edited_pm": ( '🔏 {} editó un mensaje' " privado. Mensaje anterior:\n{}" ), "edited_chat": ( '🔏 {} editó un mensaje de' ' {} en el grupo. Mensaje anterior:\n{}' ), "mode_off": ( f"{pm} He desactivado el modo espía{{}}spymode\n" ), "cfg_enable_pm": "Guardar mensajes privados", "cfg_enable_groups": "Guardar mensajes de grupo", "cfg_whitelist": "Lista de Chats a guardar", "cfg_blacklist": "Lista de Сhats a borrar", "cfg_always_track": ( "Lista de Chats para rastrear siempre los mensajes, pase lo que pase" ), "cfg_log_edits": "Guardar mensajes editados", "cfg_ignore_inline": "Ignorar mensajes de inline", "cfg_fw_protect": "Protegerse de forwarding floods", "_cls_doc": ( "Guarda los mensajes borrados, editados o enviados por un usuario" " especificado" ), "sd_media": ( "🔥 {} te ha enviado un mensaje de" " contenido que se puede borrar" ), "save_sd": ( "🔥 Guardar medios" " autodestructivos\n" ), "cfg_save_sd": "Guardar contenido que se puede borrar", } strings_kk = { "on": "қосылған", "off": "өшірілген", "state": f"{rei} Шпион режимі ағымда {{}}", "spybl": ( f"{rei} Бұл сөйлесу қорытынды шпион режимінің қара тізіміне қосылды" ), "spybl_removed": ( f"{rei} Бұл сөйлесу қорытынды шпион режимінің қара тізімінен алынды" ), "spybl_clear": f"{rei} Шпион режимінің қара тізімін тазалау", "spywl": ( f"{rei} Бұл сөйлесу қорытынды шпион режимінің ақ тізіміне қосылды" ), "spywl_removed": ( f"{rei} Бұл сөйлесу қорытынды шпион режимінің ақ тізімінен алынды" ), "spywl_clear": f"{rei} Шпион режимінің ақ тізімін тазалау", "whitelist": f"\n{rei} Тек хабарламаларды қадағалау:\n{{}}", "always_track": f"\n{rei} Әрқашан хабарламаларды қадағалау:\n{{}}", "blacklist": f"\n{rei} Хабарламаларды елемеу:\n{{}}", "chat": f"{groups} Группадағы жазбаларымды сақтау\n", "pm": f"{pm} Жеке жазбаларымды сақтау\n", "deleted_pm": ( '🗑 {} жеке жазбағын жойды.' " Жазба:\n{}" ), "deleted_chat": ( '🗑 {} {} топындағы' ' жазбағын жойды. Жазба:\n{}' ), "edited_pm": ( '🔏 {} жеке жазбағын' " өзгертті. Алдындағы жазба:\n{}" ), "edited_chat": ( '🔏 {} {} топындағы жазбағын өзгертті. Алдындағы жазба:\n{}' ), "mode_off": f"{pm} Спай режимін өшірдім{{}}spymode\n", "cfg_enable_pm": "Жеке хабарламаларды сақтау", "cfg_enable_groups": "Топтардың хабарламаларын сақтау", "cfg_whitelist": "Сақталатын топтар тізімі", "cfg_blacklist": "Жоюға мүмкіндік беретін топтар тізімі", "cfg_always_track": ( "Еш нәрсеге қарамастан, әрқашан хабарламаларды бақылайтын топтар тізімі" ), "cfg_log_edits": "Өңделген хабарламаларды сақтау", "cfg_ignore_inline": "Inline режимінен келген хабарламаларды жою", "cfg_fw_protect": "Forwarding flood-тен қорғау", "_cls_doc": ( "Көрсетілген пайдаланушы/топтардың жойылған, өңделген немесе сақталған" " хабарламаларын сақтайды" ), "sd_media": ( "🔥 {} сенің жойылған медиа-жазбаңың" " болуы мүмкін" ), "save_sd": ( "🔥 Жойылған" " медиа-жазбаларды сақтау\n" ), "cfg_save_sd": "Жойылған медиа-жазбаларды сақтау", } def __init__(self): self._tl_channel = None self.config = loader.ModuleConfig( loader.ConfigValue( "enable_pm", True, lambda: self.strings("cfg_enable_pm"), validator=loader.validators.Boolean(), ), loader.ConfigValue( "enable_groups", False, lambda: self.strings("cfg_enable_groups"), validator=loader.validators.Boolean(), ), loader.ConfigValue( "whitelist", [], lambda: self.strings("cfg_whitelist"), validator=loader.validators.Series(), ), loader.ConfigValue( "blacklist", [], lambda: self.strings("cfg_blacklist"), validator=loader.validators.Series(), ), loader.ConfigValue( "always_track", [], lambda: self.strings("cfg_always_track"), validator=loader.validators.Series(), ), loader.ConfigValue( "log_edits", True, lambda: self.strings("cfg_log_edits"), validator=loader.validators.Boolean(), ), loader.ConfigValue( "ignore_inline", True, lambda: self.strings("cfg_ignore_inline"), validator=loader.validators.Boolean(), ), loader.ConfigValue( "fw_protect", 3.0, lambda: self.strings("cfg_fw_protect"), validator=loader.validators.Float(minimum=0.0), ), loader.ConfigValue( "save_sd", True, lambda: self.strings("cfg_save_sd"), validator=loader.validators.Boolean(), ), ) self._queue = [] self._cache = {} self._next = 0 self._threshold = 10 self._flood_protect_sample = 60 @loader.loop(interval=0.1, autostart=True) async def sender(self): if not self._queue or self._next > time.time(): return item = self._queue.pop(0) await item self._next = int(time.time()) + self.config["fw_protect"] @staticmethod def _int(value: typing.Union[str, int], /) -> typing.Union[str, int]: return int(value) if str(value).isdigit() else value @property def blacklist(self): return list( map( self._int, self.config["blacklist"] + [777000, self._client.tg_id, self._tl_channel, self.inline.bot_id], ) ) @blacklist.setter def blacklist(self, value: list): self.config["blacklist"] = list( set(value) - {777000, self._client.tg_id, self._tl_channel, self.inline.bot_id} ) @property def whitelist(self): return list(map(self._int, self.config["whitelist"])) @whitelist.setter def whitelist(self, value: list): self.config["whitelist"] = value @property def always_track(self): return list(map(self._int, self.config["always_track"])) async def client_ready(self): channel, _ = await utils.asset_channel( self._client, "hikka-nekospy", "Deleted and edited messages will appear there", silent=True, invite_bot=True, avatar="https://pm1.narvii.com/6733/0e0380ca5cd7595de53f48c0ce541d3e2f2effc4v2_hq.jpg", _folder="hikka", ) self._channel = int(f"-100{channel.id}") self._tl_channel = channel.id @loader.command( ru_doc=( "• Кто я? • Аянами Рей. • А кто ты? • Аянами Рей. • Ты тоже Аянами Рей? •" " Да. Я та, кого знают как Аянами Рей. • Мы все те, кого знают, как Аянами" " Рей. • Как они все могут быть мной? • Просто потому что другие зовут нас" " Аянами Рей. Только и всё. У тебя ненастоящая душа, и тело твоё -" " подделка. Знаешь почему? • Я не подделка и не фальшивка. Я - это я." ), tr_doc=( "• Kimim? • Ayanami Rei. • Kimsin? • Ayanami Rei. • Sen de Ayanami Rei" " misin? • Evet. Beni bilenler Ayanami Rei olarak bilir. • Hepimiz Ayanami" " Rei olarak bilinenleriz. • Hepimiz nasıl Ayanami Rei olabiliriz? • Sadece" " diğerleri bizi Ayanami Rei olarak adlandırıyor. Sadece bu. Ruhun gerçek" " değil ve vücudun bir kopya. Biliyor musun neden? • Ben bir kopya değilim" " ve sahte değilim. Ben benim." ), it_doc=( "• Chi sono io? • Ayanami Rei. • Chi sei tu? • Ayanami Rei. • Tu sei anche" " Ayanami Rei? • Sì. Io sono quella che conoscono come Ayanami Rei. • Tutti" " noi siamo quelli che conoscono come Ayanami Rei. • Come possono tutti" " essere io? • Solo perché gli altri ci chiamano Ayanami Rei. Solo questo." " La tua anima non è vera e il tuo corpo è una copia. Lo sai perché? • Non" " sono una copia e non sono una falsa. Io sono io." ), kk_doc=( "• Мені кім? • Аянами Рей. • Сені кім? • Аянами Рей. • Сені де Аянами Рей?" " • Иә. Мен Аянами Рей деп білінетін кім. • Барлығымыз Аянами Рей деп" " білінетін кім. • Барлар мені қайсы бола алады? • Қатарынан, біздерді" " Аянами Рей деп атайтын. Бірақ, бұл барлық. Сенің дуалың жарамсыз, және" " телегің - бұл қате. Білесін бе? • Мен жарамсыз және қате емеспін. Мен -" " бұл мен." ), de_doc=( "• Wer bin ich? • Ayanami Rei. • Und wer bist du? • Ayanami Rei. • Bist du" " auch Ayanami Rei? • Ja. Ich bin die, die als Ayanami Rei bekannt ist. •" " Wir sind alle diejenigen, die als Ayanami Rei bekannt sind. • Wie können" " alle mich sein? • Einfach nur, weil andere uns als Ayanami Rei nennen." " Das ist alles. Du hast eine falsche Seele und deinen Körper gibt es" " nicht. Weißt du, warum? • Ich bin nicht falsch und nicht falsch. Ich bin" " ich." ), es_doc=( "• ¿Quién soy? • Ayanami Rei. • ¿Y quién eres? • Ayanami Rei. • ¿Tú también" " eres Ayanami Rei? • Sí. Soy la que se conoce como Ayanami Rei. • Todos" " somos lo que se conoce como Ayanami Rei. • ¿Cómo pueden todos ser yo? •" " Simplemente porque otros nos llaman Ayanami Rei. Eso es todo. Tienes un" " alma falsa y tu cuerpo es una falsificación. ¿Sabes por qué? • No soy" " falso ni falso. Soy yo." ), ) async def spymode(self, message: Message): """• Who am I? • Ayanami Rey. • Who are you? • Ayanami Rey. • Are you Ayanami Rey too? • Yes. I'm the one known as Ayanami Rey. • We're all what we know as Ayanami Rey. • How can they all be me? • Just because others call us Ayanami Rey. That's all. You have a fake soul and your body is a fake. You know why? • I'm not fake or fake. I am me.""" await utils.answer( message, self.strings("state").format( self.strings("off" if self.get("state", False) else "on") ), ) self.set("state", not self.get("state", False)) @loader.command( ru_doc="Добавить / удалить чат из списка игнора", de_doc="Chat zur Ignorierliste hinzufügen / entfernen", uz_doc="Chatni qo'shish / olib tashlash", tr_doc="Sohbeti engelleme listesine ekle / kaldır", es_doc="Agregar / eliminar chat de la lista de ignorados", kk_doc="Чатты қосу / жою", it_doc="Aggiungi / rimuovi chat dalla lista di ignorati", ) async def spybl(self, message: Message): """Add / remove chat from blacklist""" chat = utils.get_chat_id(message) if chat in self.blacklist: self.blacklist = list(set(self.blacklist) - {chat}) await utils.answer(message, self.strings("spybl_removed")) else: self.blacklist = list(set(self.blacklist) | {chat}) await utils.answer(message, self.strings("spybl")) @loader.command( ru_doc="Очистить черный список", de_doc="Schwarze Liste leeren", uz_doc="Qora ro'yxatni tozalash", tr_doc="Siyah listeyi temizle", es_doc="Limpiar lista negra", kk_doc="Қара тізімді тазалау", it_doc="Cancella la lista nera", ) async def spyblclear(self, message: Message): """Clear blacklist""" self.blacklist = [] await utils.answer(message, self.strings("spybl_clear")) @loader.command( ru_doc="Добавить / удалить чат из белого списка", de_doc="Chat zur Whitelist hinzufügen / entfernen", uz_doc="Chatni o'qish ro'yxatiga qo'shish / olib tashlash", tr_doc="Sohbeti beyaz listeye ekle / kaldır", es_doc="Agregar / eliminar chat de la lista blanca", kk_doc="Чатты оқыш тізіміне қосу / жою", it_doc="Aggiungi / rimuovi chat dalla whitelist", ) async def spywl(self, message: Message): """Add / remove chat from whitelist""" chat = utils.get_chat_id(message) if chat in self.whitelist: self.whitelist = list(set(self.whitelist) - {chat}) await utils.answer(message, self.strings("spywl_removed")) else: self.whitelist = list(set(self.whitelist) | {chat}) await utils.answer(message, self.strings("spywl")) @loader.command( ru_doc="Очистить белый список", de_doc="Whitelist leeren", uz_doc="O'qish ro'yxatini tozalash", tr_doc="Beyaz listeyi temizle", es_doc="Limpiar lista blanca", kk_doc="Оқыш тізімін тазалау", it_doc="Cancella la whitelist", ) async def spywlclear(self, message: Message): """Clear whitelist""" self.whitelist = [] await utils.answer(message, self.strings("spywl_clear")) async def _get_entities_list(self, entities: list) -> str: return "\n".join( [ "\u0020\u2800\u0020\u2800▫️ {}' .format( utils.get_entity_url(await self._client.get_entity(x, exp=0)), utils.escape_html( get_display_name(await self._client.get_entity(x, exp=0)) ), ) for x in entities ] ) @loader.command( ru_doc="Показать текущую конфигурацию спай-мода", de_doc="Aktuelle Spy-Modus-Konfiguration anzeigen", uz_doc="Spy rejimining hozirgi konfiguratsiyasini ko'rsatish", tr_doc="Spy modu geçerli yapılandırmasını göster", es_doc="Mostrar la configuración actual del modo espía", kk_doc="Спай-режимдің ағымдағы конфигурациясын көрсету", it_doc="Mostra la configurazione attuale della modalità spia", ) async def spyinfo(self, message: Message): """Show current spy mode configuration""" if not self.get("state"): await utils.answer( message, self.strings("mode_off").format(self.get_prefix()) ) return info = "" if self.config["save_sd"]: info += self.strings("save_sd") if self.config["enable_groups"]: info += self.strings("chat") if self.config["enable_pm"]: info += self.strings("pm") if self.whitelist: info += self.strings("whitelist").format( await self._get_entities_list(self.whitelist) ) if self.config["blacklist"]: info += self.strings("blacklist").format( await self._get_entities_list(self.config["blacklist"]) ) if self.always_track: info += self.strings("always_track").format( await self._get_entities_list(self.always_track) ) await utils.answer(message, info) async def _message_deleted(self, msg_obj: Message, caption: str): caption = self.inline.sanitise_text(caption) if not msg_obj.photo and not msg_obj.video and not msg_obj.document: self._queue += [ self.inline.bot.send_message( self._channel, caption, disable_web_page_preview=True, ) ] return if msg_obj.sticker: self._queue += [ self.inline.bot.send_message( self._channel, caption + "\n\n<sticker>", disable_web_page_preview=True, ) ] return file = io.BytesIO(await self._client.download_media(msg_obj, bytes)) args = (self._channel, file) kwargs = {"caption": caption} if msg_obj.photo: file.name = "photo.jpg" self._queue += [self.inline.bot.send_photo(*args, **kwargs)] elif msg_obj.video: file.name = "video.mp4" self._queue += [self.inline.bot.send_video(*args, **kwargs)] elif msg_obj.voice: file.name = "audio.ogg" self._queue += [self.inline.bot.send_voice(*args, **kwargs)] elif msg_obj.document: file.name = next( attr.file_name for attr in msg_obj.document.attributes if isinstance(attr, DocumentAttributeFilename) ) self._queue += [self.inline.bot.send_document(*args, **kwargs)] async def _message_edited(self, caption: str, msg_obj: Message): args = ( self._channel, await self._client.download_media(msg_obj, bytes), ) kwargs = {"caption": self.inline.sanitise_text(caption)} if msg_obj.photo: self._queue += [self.inline.bot.send_photo(*args, **kwargs)] elif msg_obj.video: self._queue += [self.inline.bot.send_video(*args, **kwargs)] elif msg_obj.voice: self._queue += [self.inline.bot.send_voice(*args, **kwargs)] elif msg_obj.document: self._queue += [self.inline.bot.send_document(*args, **kwargs)] else: self._queue += [ self.inline.bot.send_message( self._channel, self.inline.sanitise_text(caption), disable_web_page_preview=True, ) ] @loader.raw_handler(UpdateEditChannelMessage) async def channel_edit_handler(self, update: UpdateEditChannelMessage): if ( not self.get("state", False) or update.message.out or (self.config["ignore_inline"] and update.message.via_bot_id) ): return key = f"{utils.get_chat_id(update.message)}/{update.message.id}" if key in self._cache and ( utils.get_chat_id(update.message) in self.always_track or self._cache[key].sender_id in self.always_track or ( self.config["log_edits"] and self.config["enable_groups"] and utils.get_chat_id(update.message) not in self.blacklist and ( not self.whitelist or utils.get_chat_id(update.message) in self.whitelist ) ) ): msg_obj = self._cache[key] if not msg_obj.sender.bot and update.message.raw_text != msg_obj.raw_text: await self._message_edited( self.strings("edited_chat").format( utils.get_entity_url(msg_obj.chat), utils.escape_html(get_display_name(msg_obj.chat)), utils.get_entity_url(msg_obj.sender), utils.escape_html(get_display_name(msg_obj.sender)), msg_obj.text, message_url=await utils.get_message_link(msg_obj), ), msg_obj, ) self._cache[key] = update.message def _should_capture(self, user_id: int, chat_id: int) -> bool: return ( chat_id not in self.blacklist and user_id not in self.blacklist and ( not self.whitelist or chat_id in self.whitelist or user_id in self.whitelist ) ) @loader.raw_handler(UpdateEditMessage) async def pm_edit_handler(self, update: UpdateEditMessage): if ( not self.get("state", False) or update.message.out or (self.config["ignore_inline"] and update.message.via_bot_id) ): return key = update.message.id msg_obj = self._cache.get(key) if ( key in self._cache and ( self._cache[key].sender_id in self.always_track or (utils.get_chat_id(self._cache[key]) in self.always_track) or ( self.config["log_edits"] and self._should_capture( self._cache[key].sender_id, utils.get_chat_id(self._cache[key]), ) ) and ( ( self.config["enable_pm"] and not isinstance(msg_obj.peer_id, PeerChat) or self.config["enable_groups"] and isinstance(msg_obj.peer_id, PeerChat) ) ) ) and update.message.raw_text != msg_obj.raw_text ): sender = await self._client.get_entity(msg_obj.sender_id, exp=0) if not sender.bot: chat = ( await self._client.get_entity( msg_obj.peer_id.chat_id, exp=0, ) if isinstance(msg_obj.peer_id, PeerChat) else None ) await self._message_edited( ( self.strings("edited_chat").format( utils.get_entity_url(chat), utils.escape_html(get_display_name(chat)), utils.get_entity_url(sender), utils.escape_html(get_display_name(sender)), msg_obj.text, message_url=await utils.get_message_link(msg_obj), ) if isinstance(msg_obj.peer_id, PeerChat) else self.strings("edited_pm").format( utils.get_entity_url(sender), utils.escape_html(get_display_name(sender)), msg_obj.text, message_url=await utils.get_message_link(msg_obj), ) ), msg_obj, ) self._cache[update.message.id] = update.message @loader.raw_handler(UpdateDeleteMessages) async def pm_delete_handler(self, update: UpdateDeleteMessages): if not self.get("state", False): return for message in update.messages: if message not in self._cache: continue msg_obj = self._cache.pop(message) if ( msg_obj.sender_id not in self.always_track and utils.get_chat_id(msg_obj) not in self.always_track and ( not self._should_capture( msg_obj.sender_id, utils.get_chat_id(msg_obj) ) or (self.config["ignore_inline"] and msg_obj.via_bot_id) or ( not self.config["enable_groups"] and isinstance(msg_obj.peer_id, PeerChat) ) or ( not self.config["enable_pm"] and not isinstance(msg_obj.peer_id, PeerChat) ) ) ): continue sender = await self._client.get_entity(msg_obj.sender_id, exp=0) if sender.bot: continue chat = ( await self._client.get_entity(msg_obj.peer_id.chat_id, exp=0) if isinstance(msg_obj.peer_id, PeerChat) else None ) await self._message_deleted( msg_obj, ( self.strings("deleted_chat").format( utils.get_entity_url(chat), utils.escape_html(get_display_name(chat)), utils.get_entity_url(sender), utils.escape_html(get_display_name(sender)), msg_obj.text, message_url=await utils.get_message_link(msg_obj), ) if isinstance(msg_obj.peer_id, PeerChat) else self.strings("deleted_pm").format( utils.get_entity_url(sender), utils.escape_html(get_display_name(sender)), msg_obj.text, message_url=await utils.get_message_link(msg_obj), ) ), ) @loader.raw_handler(UpdateDeleteChannelMessages) async def channel_delete_handler(self, update: UpdateDeleteChannelMessages): if not self.get("state", False): return for message in update.messages: key = f"{update.channel_id}/{message}" if key not in self._cache: continue msg_obj = self._cache.pop(key) if ( msg_obj.sender_id in self.always_track or utils.get_chat_id(msg_obj) in self.always_track or self.config["enable_groups"] and ( self._should_capture( msg_obj.sender_id, utils.get_chat_id(msg_obj), ) and (not self.config["ignore_inline"] or not msg_obj.via_bot_id) and not msg_obj.sender.bot ) ): await self._message_deleted( msg_obj, self.strings("deleted_chat").format( utils.get_entity_url(msg_obj.chat), utils.escape_html(get_display_name(msg_obj.chat)), utils.get_entity_url(msg_obj.sender), utils.escape_html(get_display_name(msg_obj.sender)), msg_obj.text, message_url=await utils.get_message_link(msg_obj), ), ) @loader.watcher("in") async def watcher(self, message: Message): if ( self.config["save_sd"] and getattr(message, "media", False) and getattr(message.media, "ttl_seconds", False) ): media = io.BytesIO(await self.client.download_media(message.media, bytes)) media.name = "sd.jpg" if message.photo else "sd.mp4" sender = await self.client.get_entity(message.sender_id, exp=0) await ( self.inline.bot.send_photo if message.photo else self.inline.bot.send_video )( self._channel, media, caption=self.strings("sd_media").format( utils.get_entity_url(sender), utils.escape_html(get_display_name(sender)), ), ) with contextlib.suppress(AttributeError): self._cache[ ( message.id if message.is_private or isinstance(message.peer_id, PeerChat) else f"{utils.get_chat_id(message)}/{message.id}" ) ] = message