├── README.md ├── null.py ├── hearts.py ├── fl.py ├── print.py ├── leave.py ├── saved.py ├── calc.py ├── scrs.py ├── заёбушка.py ├── .github └── workflows │ └── python-publish.yml ├── MTF.py ├── SquareBlur.py ├── colorBit.py ├── 0x.py ├── pung.py ├── заёбушка2.0.py ├── words.py ├── modulator.py ├── what.py ├── webshot.py ├── pypng.py ├── filename.py ├── valute.py ├── TgsKiller.py ├── LoremIpsum.py ├── MirrorFlipV2.py ├── ttdl.py ├── Lines50.py ├── tagall.py ├── jpeg.py ├── BlackLines.py ├── delme.py ├── biography.py ├── MacAshoT.py ├── rysianskiy.py ├── OneMessage.py ├── codefy.py ├── mediaspam.py ├── ph.py ├── ticker.py ├── StickTools.py ├── cheval.py ├── MicroQuotes.py ├── YTsearch.py ├── MirrorFlip.py ├── _base64.py ├── stext.py ├── YandexRS.py ├── dotify.py ├── distortion_no_api.py ├── gg.gg.py ├── urldl.py ├── Hasher.py ├── QRtools.py ├── Glitcher.py ├── datamosh.py ├── Switcher.py ├── VideoDistortion.py ├── Swiper.py ├── MegaMozg.py ├── purge.py ├── hyi.py ├── Circles.py ├── soaper.py ├── im2bin.py ├── family.py ├── zip.py ├── DNA.py ├── gird.py ├── spinner.py ├── notexec.py ├── pic2pack.py ├── kicklast.py ├── help.py ├── python.py ├── pydraft.py ├── test.py ├── notes.py ├── SuperDemotivator.py ├── PillowTools.py ├── SuperDemotivator.V2.py ├── kzdQuotes.py └── admin_tools.py /README.md: -------------------------------------------------------------------------------- 1 | # Govno modules 2 | Сборник моих [модулей](https://t.me/SomeScripts) 3 | 4 | [я](https://t.me/KeyZenD) 5 | -------------------------------------------------------------------------------- /null.py: -------------------------------------------------------------------------------- 1 | from .. import loader 2 | class nullMod(loader.Module): 3 | strings = {"name": "null"} 4 | async def nullcmd(self, message): 5 | await message.edit("null") -------------------------------------------------------------------------------- /hearts.py: -------------------------------------------------------------------------------- 1 | from .. import loader 2 | from asyncio import sleep 3 | @loader.tds 4 | class HeartsMod(loader.Module): 5 | strings = {"name": "Heart's"} 6 | @loader.owner 7 | async def heartscmd(self, message): 8 | for _ in range(10): 9 | for heart in ['❤', '️🧡', '💛', '💚', '💙', '💜']: 10 | await message.edit(heart) 11 | await sleep(0.3) -------------------------------------------------------------------------------- /fl.py: -------------------------------------------------------------------------------- 1 | from asyncio import sleep 2 | from userbot.events import register 3 | 4 | 5 | @register(outgoing=True, pattern='^.fl ?(.*)') 6 | async def fakeload(e): 7 | inp = e.pattern_match.group(1) 8 | load = [" ","▏","▎","▍","▌","▋","▊","▉"] 9 | bar = "" 10 | count = 0 11 | await e.edit("`[Инициализация]`") 12 | sleep(3) 13 | for i in range(13): 14 | for division in load: 15 | space = " " * (12 - i) 16 | await e.edit(f"`{bar}{division}{space}[{count}%]`") 17 | count += 1 18 | sleep(0.3) 19 | if count == 101: 20 | break 21 | bar += "█" 22 | sleep(2) 23 | done = "Загрузка завершена!" 24 | if inp: 25 | done = inp 26 | await e.edit(f"`{done}`") 27 | -------------------------------------------------------------------------------- /print.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | from asyncio import sleep 3 | @loader.tds 4 | class PrintMod(loader.Module): 5 | """Аналог модуля typewriter""" 6 | strings = {"name": "print"} 7 | @loader.owner 8 | async def printcmd(self, message): 9 | """.print """ 10 | text = utils.get_args_raw(message) 11 | if not text: 12 | reply = await message.get_reply_message() 13 | if not reply or not reply.message: 14 | await message.edit("Текста нет!") 15 | return 16 | text = reply.message 17 | out = "" 18 | for ch in text: 19 | out += ch 20 | if ch not in [" ", "\n"]: 21 | await message.edit(out+"\u2060") 22 | await sleep(0.3) 23 | -------------------------------------------------------------------------------- /leave.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | from asyncio import sleep 3 | from telethon.tl.functions.channels import LeaveChannelRequest 4 | @loader.tds 5 | class LeaveMod(loader.Module): 6 | strings = {"name": "Just leave"} 7 | @loader.sudo 8 | async def leavecmd(self, message): 9 | """.leave""" 10 | if not message.chat: 11 | await message.edit("Дурка блять") 12 | return 13 | text = utils.get_args_raw(message) 14 | if not text: 15 | text = "До связи." 16 | if text.lower() == "del": 17 | await message.delete() 18 | else: 19 | await message.edit(f"{text}") 20 | await sleep(1) 21 | await message.client(LeaveChannelRequest(message.chat_id)) 22 | 23 | -------------------------------------------------------------------------------- /saved.py: -------------------------------------------------------------------------------- 1 | import io 2 | from .. import loader, utils 3 | 4 | @loader.tds 5 | class SavedMod(loader.Module): 6 | """Соxранятель в избранное""" 7 | strings = {"name": "SavedMessages", "to":"me"} 8 | @loader.unrestricted 9 | async def savedcmd(self, message): 10 | """.saved реплай на медиа""" 11 | await message.delete() 12 | reply = await message.get_reply_message() 13 | name = utils.get_args_raw(message) 14 | if not reply or not reply.file: 15 | return 16 | media = reply.media 17 | if media.ttl_seconds or name: 18 | file = await reply.download_media(bytes) 19 | file = io.BytesIO(file) 20 | file.name = name or str(reply.sender_id) + reply.file.ext 21 | file.seek(0) 22 | await message.client.send_file(self.strings["to"], file) 23 | else: 24 | await reply.forward_to(self.strings["to"]) 25 | -------------------------------------------------------------------------------- /calc.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | class КукуляторMod(loader.Module): 3 | """Кукулирует вырожения""" 4 | strings = {'name': 'Кукулятор'} 5 | 6 | async def calccmd(self, message): 7 | """.calc <выражение или реплай на то, что нужно посчитать> 8 | Кстати: 9 | ** - возвести в степень 10 | / - деление 11 | % - деление по модулю""" 12 | question = utils.get_args_raw(message) 13 | reply = await message.get_reply_message() 14 | if not question: 15 | if not reply: 16 | await utils.answer(message, "2+2=5") 17 | return 18 | else: 19 | question = reply.raw_text 20 | try: 21 | answer = eval(question) 22 | answer = f"{question}={answer}" 23 | except Exception as e: 24 | answer = f"{question}={e}" 25 | await utils.answer(message, answer) 26 | 27 | -------------------------------------------------------------------------------- /scrs.py: -------------------------------------------------------------------------------- 1 | 2 | from .. import loader, utils 3 | from telethon import events, errors, functions, types 4 | 5 | def register(cb): 6 | cb(ScrSpamMod()) 7 | 8 | 9 | class ScrSpamMod(loader.Module): 10 | """Screenshot Spammer by @KeyZenD""" 11 | 12 | strings = {'name': 'ScrSpam'} 13 | 14 | def __init__(self): 15 | self.name = self.strings['name'] 16 | self._me = None 17 | self._ratelimit = [] 18 | 19 | async def client_ready(self, client, db): 20 | self._db = db 21 | self._client = client 22 | self.me = await client.get_me() 23 | 24 | async def scrscmd(self, message): 25 | """.scrs """ 26 | a = 1 27 | r = utils.get_args(message) 28 | if r and r[0].isdigit(): 29 | a = int(r[0]) 30 | await message.edit("Screenshoting...") 31 | for _ in range(a): 32 | await message.client(functions.messages.SendScreenshotNotificationRequest(peer=message.to_id, reply_to_msg_id=message.id)) 33 | await message.delete() 34 | 35 | -------------------------------------------------------------------------------- /заёбушка.py: -------------------------------------------------------------------------------- 1 | from asyncio import sleep 2 | from .. import loader, utils 3 | 4 | def register(cb): 5 | cb(ЗаёбушкаMod()) 6 | 7 | class ЗаёбушкаMod(loader.Module): 8 | """Заебет любого""" 9 | strings = {'name': 'Заёбушка'} 10 | 11 | async def заебуcmd(self, message): 12 | """.заебу <колличество> <реплай на того, кого заебать>""" 13 | reply = await message.get_reply_message() 14 | if not reply: 15 | await message.edit("А кого заёбывать-то?") 16 | return 17 | id = reply.sender_id 18 | args = utils.get_args(message) 19 | count = 50 20 | if args: 21 | if args[0].isdigit(): 22 | if int(args[0]) < 0: 23 | count = 50 24 | else: 25 | count = int(args[0]) 26 | txt = 'Заёбушка :3'.format(id) 27 | await message.delete() 28 | for _ in range(count): 29 | await sleep(0.3) 30 | msg = await message.client.send_message(message.to_id, txt) 31 | await sleep(0.3) 32 | await msg.delete() 33 | -------------------------------------------------------------------------------- /.github/workflows/python-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflows will upload a Python Package using Twine when a release is created 2 | # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries 3 | 4 | name: Upload Python Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | deploy: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Set up Python 18 | uses: actions/setup-python@v2 19 | with: 20 | python-version: '3.x' 21 | - name: Install dependencies 22 | run: | 23 | python -m pip install --upgrade pip 24 | pip install setuptools wheel twine 25 | - name: Build and publish 26 | env: 27 | TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} 28 | TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} 29 | run: | 30 | python setup.py sdist bdist_wheel 31 | twine upload dist/* 32 | -------------------------------------------------------------------------------- /MTF.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | import io 3 | 4 | @loader.tds 5 | class MTFMod(loader.Module): 6 | """send Message as file""" 7 | strings = {'name': 'MessageToFile'} 8 | 9 | async def mtfcmd(self, message): 10 | """.mtf """ 11 | reply = await message.get_reply_message() 12 | if not reply or not reply.message: 13 | await message.edit("Reply to text!") 14 | return 15 | text = bytes(reply.raw_text, "utf8") 16 | fname = utils.get_args_raw(message) or str(message.id+reply.id)+".txt" 17 | file = io.BytesIO(text) 18 | file.name = fname 19 | file.seek(0) 20 | await reply.reply(file=file) 21 | await message.delete() 22 | 23 | async def ftmcmd(self, message): 24 | """.ftm """ 25 | reply = await message.get_reply_message() 26 | if not reply or not reply.file: 27 | await message.edit("Reply to file!") 28 | return 29 | text = await reply.download_media(bytes) 30 | text = str(text, "utf8") 31 | if utils.get_args(message): 32 | text = f"{text}" 33 | await utils.answer(message, utils.escape_html(text)) -------------------------------------------------------------------------------- /SquareBlur.py: -------------------------------------------------------------------------------- 1 | from PIL import Image, ImageFilter 2 | import io 3 | from .. import loader, utils 4 | @loader.tds 5 | class SquareBlurMod(loader.Module): 6 | """Make image 1:1 ratio""" 7 | strings = {"name": "SquareBlur"} 8 | 9 | @loader.unrestricted 10 | async def squareblurcmd(self, message): 11 | """make image 1:1 ratio""" 12 | reply = await message.get_reply_message() 13 | if not reply or not reply.file or not reply.file.mime_type.split("/")[0].lower() == "image": 14 | await message.edit("Reply to image!") 15 | return 16 | im = io.BytesIO() 17 | await reply.download_media(im) 18 | im = Image.open(im) 19 | w, h = im.size 20 | if w == h: 21 | await message.edit("Ты за меня придурка не держи!") 22 | return 23 | _min, _max = min(w, h), max(w, h) 24 | bg = im.crop(((w-_min)//2, (h-_min)//2, (w+_min)//2, (h+_min)//2)) 25 | bg = bg.filter(ImageFilter.GaussianBlur(5)) 26 | bg = bg.resize((_max, _max)) 27 | bg.paste(im, ((_max-w)//2, (_max-h)//2)) 28 | img = io.BytesIO() 29 | img.name = "im.png" 30 | bg.save(img) 31 | img.seek(0) 32 | await reply.reply(file=img) 33 | await message.delete() 34 | -------------------------------------------------------------------------------- /colorBit.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | from PIL import Image 3 | from io import BytesIO as io 4 | 5 | class colorBitMod(loader.Module): 6 | strings = {"name": "colorBit"} 7 | async def cbitcmd(self, message): 8 | """.cbit <число от 0 до 255""" 9 | reply = await message.get_reply_message() 10 | if not reply or not reply.file or not "image" in reply.file.mime_type: 11 | return await message.edit("Reply to image!") 12 | x = utils.get_args_raw(message) 13 | x = int(x) if x.isdigit() else 8 14 | if x <= 0 or x >= 256: 15 | x = 8 16 | x = 256//x 17 | im = Image.open(io(await reply.download_media(bytes))) 18 | w, h = im.size 19 | mode = im.mode 20 | out = [] 21 | await message.edit("Processing...") 22 | for bit in list(im.tobytes()): 23 | bit = list(range(0, 256+x, x))[bit//x] 24 | out.append(bit) 25 | image = Image.frombytes(mode, (w, h), bytes(out)) 26 | output = io() 27 | image.save(output, "PNG") 28 | output.seek(0) 29 | await message.delete() 30 | await reply.reply(file=output) -------------------------------------------------------------------------------- /0x.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils # pylint: disable=relative-beyond-top-level 2 | from requests import post 3 | import io 4 | 5 | 6 | @loader.tds 7 | class x0Mod(loader.Module): 8 | """Uploader""" 9 | strings = { 10 | "name": "x0 Uploader" 11 | } 12 | 13 | async def client_ready(self, client, db): 14 | self.client = client 15 | 16 | 17 | @loader.sudo 18 | async def x0cmd(self, message): 19 | await message.edit("Uploading...") 20 | reply = await message.get_reply_message() 21 | if not reply: 22 | await message.edit("Reply to message!") 23 | return 24 | media = reply.media 25 | if not media: 26 | file = io.BytesIO(bytes(reply.raw_text, "utf-8")) 27 | file.name = "txt.txt" 28 | else: 29 | file = io.BytesIO(await self.client.download_file(media)) 30 | file.name = reply.file.name if reply.file.name else reply.file.id+reply.file.ext 31 | try: 32 | x0at = post('https://x0.at', files={'file': file}) 33 | except ConnectionError as e: 34 | await message.edit(ste(e)) 35 | return 36 | url = x0at.text 37 | output = f'URL: {url}' 38 | await message.edit(output) 39 | 40 | -------------------------------------------------------------------------------- /pung.py: -------------------------------------------------------------------------------- 1 | from telethon import events 2 | from telethon.errors.rpcerrorlist import YouBlockedUserError 3 | from .. import loader, utils 4 | from datetime import datetime 5 | 6 | 7 | def register(cb): 8 | cb(PingerMod()) 9 | 10 | 11 | class PingerMod(loader.Module): 12 | """более точный пинг""" 13 | 14 | strings = {'name': 'PingerХуингер'} 15 | 16 | def __init__(self): 17 | self.name = self.strings['name'] 18 | self._me = None 19 | self._ratelimit = [] 20 | 21 | async def client_ready(self, client, db): 22 | self._db = db 23 | self._client = client 24 | self.me = await client.get_me() 25 | 26 | async def pingcmd(self, message): 27 | """пингует""" 28 | a = 5 29 | r = utils.get_args(message) 30 | if r and r[0].isdigit(): 31 | a = int(r[0]) 32 | ping_msg = [] 33 | ping_data = [] 34 | for _ in range(a): 35 | start = datetime.now() 36 | msg = await message.client.send_message("me", "ping") 37 | end = datetime.now() 38 | duration = (end - start).microseconds / 1000 39 | ping_data.append(duration) 40 | ping_msg.append(msg) 41 | ping = sum(ping_data) / len(ping_data) 42 | await message.edit(f"[ok] {str(ping)[0:5]}ms") 43 | for i in ping_msg: 44 | await i.delete() -------------------------------------------------------------------------------- /заёбушка2.0.py: -------------------------------------------------------------------------------- 1 | from asyncio import sleep 2 | from .. import loader, utils 3 | 4 | def register(cb): 5 | cb(ЗаёбушкаMod()) 6 | 7 | class ЗаёбушкаMod(loader.Module): 8 | """Заебет любого""" 9 | strings = {'name': 'Заёбушка'} 10 | def __init__(self): 11 | self.name = self.strings['name'] 12 | self._me = None 13 | self._ratelimit = [] 14 | 15 | async def заебуcmd(self, message): 16 | """.заебу <колличество> <реплай на того, кого заебать>""" 17 | reply = await message.get_reply_message() 18 | if not reply: 19 | await message.edit("А кого заёбывать-то?") 20 | return 21 | id = reply.sender_id 22 | args = utils.get_args(message) 23 | count = 50 24 | if args: 25 | if args[0].isdigit(): 26 | if int(args[0]) < 0: 27 | count = 50 28 | else: 29 | count = int(args[0]) 30 | txt = '{}' 31 | await message.edit(txt.format(id, "Я тебя заебу!")) 32 | for _ in range(count): 33 | await sleep(0.3) 34 | msg = await message.client.send_message(message.to_id, txt.format(id, "Заёбушка:3"), reply_to=message) 35 | if not msg.is_reply: 36 | await msg.edit("Остановлено!") 37 | break 38 | await sleep(0.3) 39 | await msg.delete() 40 | 41 | -------------------------------------------------------------------------------- /words.py: -------------------------------------------------------------------------------- 1 | from .. import loader 2 | import io 3 | 4 | class WordsMod(loader.Module): 5 | strings = {"name": "Words Counter"} 6 | 7 | async def wordscmd(self, message): 8 | reply = await message.get_reply_message() 9 | object = reply.sender_id if reply else message.sender_id 10 | chat = message.to_id 11 | 12 | await message.edit("Сбор статистики...") 13 | 14 | _words = {} 15 | 16 | async for msg in message.client.iter_messages(chat, from_user=object): 17 | if msg and msg.raw_text: 18 | words = set("".join(map(lambda x: x if (x in [" "] or x.isalpha()) else " ", msg.raw_text)).lower().split()) 19 | for word in words: 20 | count = msg.raw_text.lower().count(word) 21 | _words[word] = _words.get(word, 0) + count 22 | all = list(_words.items()) 23 | all.sort(key=lambda i: i[1]) 24 | response = "" 25 | for word in all[::-1]: 26 | response += f"{word[0]}: {word[1]}\n" 27 | file = io.BytesIO(bytes(response, "utf-8")) 28 | file.name = f"ID:{object}.txt" 29 | await message.reply(file=file) 30 | await message.delete() 31 | -------------------------------------------------------------------------------- /modulator.py: -------------------------------------------------------------------------------- 1 | R=int 2 | Q=float 3 | E=len 4 | # requires: pydub numpy 5 | from .. import loader as A,utils 6 | import os 7 | from pydub import AudioSegment as M 8 | import numpy as G,io 9 | class BMod(A.Module): 10 | 'Modulate pitch of voice';strings={'name':'Modulator'} 11 | async def modulatecmd(W,message): 12 | A=message;B=await A.get_reply_message() 13 | if not B or not B.file and'audio'in B.file.mime_type:return await A.edit('Reply to audio!') 14 | N=io.BytesIO(await B.download_media(bytes));N.seek(0);X=[];H=M.empty();I=M.from_file(N);I=[A for A in I];C=utils.get_args(A);J=0.9,1.1,0.01;O=3 15 | if E(C)==3: 16 | try:J=(Q(A)for A in C) 17 | except:pass 18 | if E(C)==4: 19 | try:J=(Q(A)for A in C[0:3]);O=R(C[3]) 20 | except:pass 21 | P=G.repeat(G.arange(*J),O);S=G.sin(P);D=list(map(lambda x:x[0]*x[-1],zip(P,S)));K=1;await A.edit('Modulating...') 22 | for (T,L) in enumerate(I): 23 | U=D[T%E(D)];K+=1 24 | if K>E(D):K=0;D=D[::-1] 25 | V=R(L.frame_rate*U);H+=L._spawn(L.raw_data,overrides={'frame_rate':V}) 26 | F=io.BytesIO();F.name='modulator_by_keyzend.ogg';H.export(F,format='ogg',bitrate='64k',codec='libopus');F.seek(0);await A.client.send_file(A.to_id,F,reply_to=B.id,voice_note=True,duration=E(H)/1000);await A.delete() 27 | -------------------------------------------------------------------------------- /what.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | from PIL import Image, ImageDraw 3 | from random import randint 4 | from io import BytesIO 5 | 6 | 7 | @loader.tds 8 | class WhatMod(loader.Module): 9 | """wow, what is it there?""" 10 | strings = {"name": "What?"} 11 | 12 | async def whatcmd(self, message): 13 | """Draw circle in random place""" 14 | args = utils.get_args_raw(message) 15 | scale = int(args) if args and args.isdigit() else 50 16 | scale = 10 if scale < 0 else scale 17 | scale = 100 if scale > 100 else scale 18 | reply = await message.get_reply_message() 19 | if not reply or not reply.file.mime_type.split("/")[0].lower() == "image": 20 | await message.edit("Reply to img!") 21 | return 22 | await message.edit("What is it?") 23 | im = BytesIO() 24 | await reply.download_media(im) 25 | im = Image.open(im) 26 | w, h = im.size 27 | f = (min(w,h)//100)*scale 28 | draw = ImageDraw.Draw(im) 29 | x, y = randint(0, w-f), randint(0, h-f) 30 | draw.ellipse((x, y, x+randint(f//2, f), y+randint(f//2, f)), fill=None, outline="red", width=randint(3, 10)) 31 | out = BytesIO() 32 | out.name = "what.png" 33 | im.save(out) 34 | out.seek(0) 35 | await message.delete() 36 | return await reply.reply(file=out) 37 | 38 | -------------------------------------------------------------------------------- /webshot.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | import logging 3 | from requests import get 4 | import io 5 | 6 | 7 | logger = logging.getLogger(__name__) 8 | 9 | def register(cb): 10 | cb(WebShotMod()) 11 | 12 | 13 | @loader.tds 14 | class WebShotMod(loader.Module): 15 | """link to screen""" 16 | strings = { 17 | "name": "WebShot" 18 | } 19 | 20 | async def client_ready(self, client, db): 21 | self.client = client 22 | 23 | def __init__(self): 24 | self.name = self.strings['name'] 25 | 26 | 27 | 28 | @loader.sudo 29 | async def webshotcmd(self, message): 30 | reply = None 31 | link = utils.get_args_raw(message) 32 | if not link: 33 | reply = await message.get_reply_message() 34 | if not reply: 35 | await message.delete() 36 | return 37 | link = reply.raw_text 38 | await message.edit("S c r e e n s h o t i n g . . .") 39 | url = "https://webshot.deam.io/{}/?width=1920&height=1080?type=png" 40 | file = get(url.format(link)) 41 | if not file.ok: 42 | await message.edit("Something went wrong...") 43 | return 44 | file = io.BytesIO(file.content) 45 | file.name = "webshot.png" 46 | file.seek(0) 47 | await message.client.send_file(message.to_id, file, reply_to=reply) 48 | await message.delete() 49 | -------------------------------------------------------------------------------- /pypng.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils # pylint: disable=relative-beyond-top-level 2 | import logging 3 | import pygments 4 | from pygments.lexers import Python3Lexer 5 | from pygments.formatters import ImageFormatter 6 | import os 7 | 8 | 9 | logger = logging.getLogger(__name__) 10 | 11 | def register(cb): 12 | cb(py2pngMod()) 13 | 14 | 15 | @loader.tds 16 | class py2pngMod(loader.Module): 17 | """Uploader""" 18 | strings = { 19 | "name": "pypng" 20 | } 21 | 22 | async def client_ready(self, client, db): 23 | self.client = client 24 | 25 | 26 | @loader.sudo 27 | async def pypngcmd(self, message): 28 | """reply to text code or py file""" 29 | await message.edit("Py to PNG") 30 | reply = await message.get_reply_message() 31 | if not reply: 32 | await message.edit("reply to file.py") 33 | return 34 | media = reply.media 35 | if not media: 36 | await message.edit("reply to file.py") 37 | return 38 | file = await message.client.download_file(media) 39 | text = file.decode('utf-8') 40 | pygments.highlight(text, Python3Lexer(), ImageFormatter(font_name='DejaVu Sans Mono', line_numbers=True), 'out.png') 41 | await message.client.send_file(message.to_id, 'out.png', force_document=True) 42 | os.remove("out.png") 43 | await message.delete() 44 | -------------------------------------------------------------------------------- /filename.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import logging 3 | from telethon.tl.types import DocumentAttributeFilename 4 | from .. import loader, utils 5 | 6 | logger = logging.getLogger(__name__) 7 | 8 | 9 | @loader.tds 10 | class filenameMod(loader.Module): 11 | """filename changer""" 12 | strings = {"name": "filename", 13 | "wf": "Reply to file?", 14 | "wn": "What is the name?", 15 | "tnf":"It's not a file!"} 16 | 17 | 18 | @loader.unrestricted 19 | async def filenamecmd(self, message): 20 | """.filename + reply.file""" 21 | reply = await message.get_reply_message() 22 | if not reply or not reply.file: 23 | await message.edit(self.strings["wf"]) 24 | return 25 | name = utils.get_args_raw(message) 26 | if not name: 27 | await message.edit(self.strings["wn"]) 28 | return 29 | fn = reply.file.name 30 | if not fn: 31 | fn = "" 32 | fs = reply.file.size 33 | 34 | [await message.edit(f"Downloading {fn}") if fs > 500000 else ...] 35 | file = await reply.download_media(bytes) 36 | [await message.edit(f"Uploading {name}") if fs > 500000 else ...] 37 | await message.client.send_file(message.to_id, file, force_document=True, reply_to=reply, attributes=[DocumentAttributeFilename(file_name=name)]) 38 | await message.delete() 39 | -------------------------------------------------------------------------------- /valute.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import logging 3 | from requests import get 4 | from .. import loader, utils 5 | 6 | logger = logging.getLogger(__name__) 7 | 8 | 9 | @loader.tds 10 | class ValitesMod(loader.Module): 11 | """Valute converter""" 12 | strings = {"name": "Valutes"} 13 | 14 | @loader.unrestricted 15 | async def valutecmd(self, message): 16 | """.valute """ 17 | valutes = get("https://www.cbr-xml-daily.ru/daily_json.js").json() 18 | names = valutes["Valute"].keys() 19 | args = utils.get_args(message) 20 | req = [] 21 | 22 | if args: 23 | for val in args: 24 | val = val.upper() 25 | if val in names: 26 | req.append(val) 27 | valutes["Valute"] = {val: valutes["Valute"][val] for val in req} 28 | 29 | text = [] 30 | temp = "{}\n{} {}: {}₽ ({}{}₽)" 31 | for val in valutes["Valute"].values(): 32 | name = val["Name"] 33 | code = val["CharCode"] 34 | nom = int(val["Nominal"]) 35 | now = round(float(val["Value"]), 3) 36 | pre = round(float(val["Previous"]), 3) 37 | way = "🔹" if now == pre else "🔻" if now < pre else "🔺" 38 | text.append(temp.format(name, nom, code, now, way, pre)) 39 | if not text: 40 | return await utils.answer(message, "Запрос неверен - ответ пуст!") 41 | await utils.answer(message, "\n".join(text)) 42 | -------------------------------------------------------------------------------- /TgsKiller.py: -------------------------------------------------------------------------------- 1 | 2 | import logging, os 3 | from random import choice, randint 4 | 5 | from .. import loader, utils 6 | 7 | logger = logging.getLogger(__name__) 8 | 9 | 10 | @loader.tds 11 | class TgsKillerMod(loader.Module): 12 | """Хуярит""" 13 | strings = {"name": "TgsKiller"} 14 | 15 | 16 | @loader.unrestricted 17 | async def tgscmd(self, message): 18 | """хуярит стикеры""" 19 | reply = await message.get_reply_message() 20 | if not reply: 21 | await message.edit("Реплай на стикер анимированный") 22 | return 23 | if not reply.file: 24 | await message.edit("Реплай на стикер анимированный") 25 | return 26 | if not reply.file.name.endswith(".tgs"): 27 | await message.edit("Реплай на стикер анимированный") 28 | return 29 | await message.edit("///Пахуярили нахуй!///") 30 | await reply.download_media("tgs.tgs") 31 | os.system("lottie_convert.py tgs.tgs json.json") 32 | with open("json.json","r") as f: 33 | stick = f.read() 34 | f.close() 35 | 36 | for i in range(1, randint(6, 10)): 37 | 38 | stick = choice([stick.replace(f'[{i}]', f'[{(i+i)*3}]'), stick.replace(f'.{i}', f'.{i}{i}')]) 39 | 40 | 41 | with open("json.json","w") as f: 42 | f.write(stick) 43 | f.close() 44 | 45 | os.system("lottie_convert.py json.json tgs.tgs") 46 | await reply.reply(file="tgs.tgs") 47 | os.remove("tgs.tgs") 48 | os.remove("json.json") 49 | await message.delete() -------------------------------------------------------------------------------- /LoremIpsum.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | import io 3 | from requests import get 4 | 5 | def register(cb): 6 | cb(LoremIpsumMod()) 7 | 8 | 9 | class LoremIpsumMod(loader.Module): 10 | """Lorem Ipsum generation""" 11 | 12 | strings = {'name': 'LoermIpsum'} 13 | 14 | def __init__(self): 15 | self.name = self.strings['name'] 16 | 17 | async def loremipsumcmd(self, message): 18 | """.loremipsum 19 | count - number of paragraphs| std: 1 20 | length - s-short, m-medium, l-long, v-verylong|std: m(edium) 21 | file - if nothing- send as message, if anything- send as file""" 22 | s = 'small' 23 | m = length = 'medium' 24 | l = 'long' 25 | v = 'verylong' 26 | args = utils.get_args(message) 27 | count = 1 28 | as_file = False 29 | if args: 30 | count = int(args[0]) if args[0].isdigit() else 1 31 | if len(args) == 2: 32 | lenght = args[1].lower() 33 | length = s if lenght in [s[:i+1] for i in range(len(s))] else l if lenght in [l[:i+1] for i in range(len(l))] else v if lenght in [v[:i+1] for i in range(len(v))] else m # сижу ахуел 34 | if len(args) >= 3: 35 | as_file = True 36 | url = f"https://loripsum.net/api/{count}/{length}/plaintext" 37 | out = get(url) 38 | if as_file: 39 | out = io.BytesIO(out.content) 40 | out.name = f"LoremIpsum.{count}.txt" 41 | out.seek(0) 42 | else: out = out.text 43 | await utils.answer(message, out) 44 | -------------------------------------------------------------------------------- /MirrorFlipV2.py: -------------------------------------------------------------------------------- 1 | from PIL import Image, ImageOps 2 | from .. import loader, utils 3 | from io import BytesIO 4 | from asyncio import sleep 5 | 6 | class MirrorFlipMod(loader.Module): 7 | strings = {"name": "MirrorFlip", 0:"Reply to image."} 8 | 9 | async def llcmd(self, m): 10 | return await make(m, 1) 11 | async def rrcmd(self, m): 12 | return await make(m, 2) 13 | async def uucmd(self, m): 14 | return await make(m, 3) 15 | async def ddcmd(self, m): 16 | return await make(m, 4) 17 | 18 | async def make(m, o): 19 | r = await m.get_reply_message() 20 | s = None 21 | try: 22 | s = await r.download_media(bytes, thumb=-1 if not r.sticker else None) 23 | img = Image.open(BytesIO(s)) 24 | except: 25 | pass 26 | if not s: 27 | return await utils.answer(m, MirrorFlipMod.strings[0]) 28 | await m.delete() 29 | w, h = img.size 30 | if o in [1, 2]: 31 | if o == 2: 32 | img = ImageOps.mirror(img) 33 | part = img.crop([0, 0, w//2, h]) 34 | img = ImageOps.mirror(img) 35 | else: 36 | if o == 4: 37 | img = ImageOps.flip(img) 38 | part = img.crop([0, 0, w, h//2]) 39 | img = ImageOps.flip(img) 40 | img.paste(part, (0, 0)) 41 | out = BytesIO() 42 | out.name = "x.webp" if r.sticker else "x.png" 43 | img.save(out) 44 | out.seek(0) 45 | return await r.reply(file=out) 46 | -------------------------------------------------------------------------------- /ttdl.py: -------------------------------------------------------------------------------- 1 | from requests import head,get 2 | from urllib.parse import urlsplit as E,parse_qs as H 3 | import json,io,re 4 | from .. import loader as A,utils 5 | class TikTokDlMod(A.Module): 6 | strings={'name':'TikTokDl'} 7 | async def ttcmd(J,message): 8 | A=message;B=await A.get_reply_message();F=utils.get_args_raw(A);C=lambda x:f"{x}" 9 | if F:D=F 10 | elif B and B.raw_text:D=B.raw_text 11 | else:return await A.edit(C('No url.')) 12 | if'.tiktok.com'not in D:return await A.edit(C('Bad url.')) 13 | await A.edit(C('Loading...'));G,K=await I(D) 14 | try:await A.client.send_file(A.to_id,file=G,reply_to=B);await A.delete() 15 | except: 16 | try:await A.edit(C('DownLoading...'));H=get(G).content;E=io.BytesIO(H);E.name='video.mp4';E.seek(0);await A.client.send_file(A.to_id,file=E,reply_to=B);await A.delete() 17 | except:await A.edit(C('я чёт нихуя не могу загрузить...')) 18 | async def I(url): 19 | A=url 20 | async def F(video_id,_): 21 | A=f"https://api-va.tiktokv.com/aweme/v1/multi/aweme/detail/?aweme_ids=%5B{video_id}%5D";A=get(A);B=A.json().get('aweme_details') 22 | if not B:return 0,0,A 23 | return B,True,A 24 | A=head(A).headers;A=A.get('Location') 25 | try: 26 | I=H(E(A).query);B=I.get('share_item_id')[0];G,C,D=await F(B,1) 27 | if not C:raise 28 | except: 29 | B=''.join(re.findall('[0-9]',E(A).path.split('/')[-1]));G,C,D=await F(B,2) 30 | if not C:return False,D 31 | return G[0]['video']['bit_rate'][0]['play_addr']['url_list'][-1],D 32 | -------------------------------------------------------------------------------- /Lines50.py: -------------------------------------------------------------------------------- 1 | from telethon import events 2 | from telethon.errors.rpcerrorlist import YouBlockedUserError 3 | from .. import loader, utils 4 | 5 | 6 | def register(cb): 7 | cb(Lines50Mod()) 8 | 9 | 10 | class Lines50Mod(loader.Module): 11 | """Draw photo with 50 lines via @Lines50Bot""" 12 | 13 | strings = {'name': 'Lines50'} 14 | 15 | def __init__(self): 16 | self.name = self.strings['name'] 17 | self._me = None 18 | self._ratelimit = [] 19 | 20 | async def client_ready(self, client, db): 21 | self._db = db 22 | self._client = client 23 | self.me = await client.get_me() 24 | 25 | async def linescmd(self, message): 26 | """.lines """ 27 | 28 | reply = await message.get_reply_message() 29 | if not reply: 30 | await message.edit("reply to photo") 31 | return 32 | try: 33 | photo = reply.media.photo 34 | except: 35 | await message.edit("reply to photo only") 36 | return 37 | 38 | 39 | 40 | 41 | chat = '@Lines50Bot' 42 | await message.edit('@Lines50Bot in process...') 43 | async with message.client.conversation(chat) as conv: 44 | try: 45 | response = conv.wait_event(events.NewMessage(incoming=True, from_users=1120861844)) 46 | 47 | await message.client.send_file(chat, photo) 48 | 49 | response = await response 50 | except YouBlockedUserError: 51 | await message.reply('Unblock @Lines50Bot') 52 | return 53 | 54 | await message.delete() 55 | await message.client.send_file(message.to_id, response.media) 56 | -------------------------------------------------------------------------------- /tagall.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | import logging 3 | 4 | 5 | logger = logging.getLogger(__name__) 6 | 7 | def register(cb): 8 | cb(TagallMod()) 9 | 10 | 11 | @loader.tds 12 | class TagallMod(loader.Module): 13 | """Tagall""" 14 | strings = { 15 | "name": "TagAll", "subscribe to": "https://t.me/KeyZenD" 16 | } 17 | 18 | async def client_ready(self, client, db): 19 | self.client = client 20 | 21 | def __init__(self): 22 | self.name = self.strings['name'] 23 | 24 | 25 | 26 | @loader.sudo 27 | async def tagallcmd(self, message): 28 | args = utils.get_args(message) 29 | tag_ = 5 30 | notext = False 31 | if args: 32 | if args[0].isdigit(): 33 | tag_ = int(args[0]) 34 | if len(args) > 1: 35 | notext = True 36 | text = " ".join(args[1:]) 37 | 38 | await message.delete() 39 | all = message.client.iter_participants(message.to_id) 40 | chunk = [] 41 | async for user in all: 42 | if not user.deleted: 43 | name = f"{user.first_name} {user.last_name}" if user.last_name else user.first_name 44 | name = name.replace("<","<").replace(">",">") 45 | name = name[:30]+"..." if len(name) > 33 else name 46 | tag = f'{name}' if not notext else f'{text}' 47 | chunk.append(tag) 48 | if len(chunk) == tag_: 49 | await message.client.send_message(message.to_id, "\n".join(chunk)) 50 | chunk = [] 51 | if len(chunk) != 0: 52 | await message.client.send_message(message.to_id, "\n".join(chunk)) -------------------------------------------------------------------------------- /jpeg.py: -------------------------------------------------------------------------------- 1 | from PIL import Image 2 | from telethon.tl.types import DocumentAttributeFilename 3 | from uniborg.util import admin_cmd 4 | import io 5 | 6 | @borg.on(admin_cmd(pattern=".jpeg?(.*)", allow_sudo=True)) 7 | async def shacal(event): 8 | async def check_media(reply_message): 9 | if reply_message and reply_message.media: 10 | if reply_message.photo: 11 | data = reply_message.photo 12 | elif reply_message.document: 13 | if DocumentAttributeFilename(file_name='AnimatedSticker.tgs') in reply_message.media.document.attributes: 14 | return False 15 | if reply_message.gif or reply_message.video or reply_message.audio or reply_message.voice: 16 | return False 17 | data = reply_message.media.document 18 | else: 19 | return False 20 | else: 21 | return False 22 | 23 | if not data or data is None: 24 | return False 25 | else: 26 | return data 27 | 28 | if event.is_reply: 29 | reply_message = await event.get_reply_message() 30 | data = await check_media(reply_message) 31 | if isinstance(data, bool): 32 | await event.delete() 33 | return 34 | else: 35 | await event.delete() 36 | return 37 | 38 | image = io.BytesIO() 39 | await event.client.download_media(data, image) 40 | image = Image.open(image) 41 | fried_io = io.BytesIO() 42 | fried_io.name = "image.jpeg" 43 | image = image.convert("RGB") 44 | image.save(fried_io, "JPEG", quality=0) 45 | fried_io.seek(0) 46 | await event.delete() 47 | await event.client.send_file(event.chat_id, fried_io, reply_to=reply_message.id) 48 | 49 | -------------------------------------------------------------------------------- /BlackLines.py: -------------------------------------------------------------------------------- 1 | from telethon import events 2 | from telethon.errors.rpcerrorlist import YouBlockedUserError 3 | from .. import loader, utils 4 | 5 | 6 | def register(cb): 7 | cb(BlackLinesMod()) 8 | 9 | 10 | class BlackLinesMod(loader.Module): 11 | """Draw line via @BlackLinesBot""" 12 | 13 | strings = {'name': 'BlackLines'} 14 | 15 | def __init__(self): 16 | self.name = self.strings['name'] 17 | self._me = None 18 | self._ratelimit = [] 19 | 20 | async def client_ready(self, client, db): 21 | self._db = db 22 | self._client = client 23 | self.me = await client.get_me() 24 | 25 | async def linecmd(self, message): 26 | """.line """ 27 | 28 | reply = await message.get_reply_message() 29 | if not reply: 30 | await message.edit("reply to photo") 31 | return 32 | try: 33 | photo = reply.media.photo 34 | except: 35 | await message.edit("reply to photo only") 36 | return 37 | 38 | args = utils.get_args_raw(message) 39 | 40 | 41 | chat = '@BlackLinesBot' 42 | await message.edit('@BlackLinesBot in process...') 43 | async with message.client.conversation(chat) as conv: 44 | try: 45 | response = conv.wait_event(events.NewMessage(incoming=True, from_users=1051644279)) 46 | await message.client.send_file(chat, photo, caption=args) 47 | response = await response 48 | except YouBlockedUserError: 49 | await message.reply('Unblock @BlackLinesBot') 50 | return 51 | 52 | await message.delete() 53 | await message.client.send_file(message.to_id, response.media) 54 | 55 | #у меня каждый коммит в чате упоминается ботом 56 | -------------------------------------------------------------------------------- /delme.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | 3 | class DelmeMod(loader.Module): 4 | """Удаляет все сообщения""" 5 | strings = {'name': 'DelMe'} 6 | @loader.sudo 7 | async def delmecmd(self, message): 8 | """Удаляет все сообщения от тебя""" 9 | chat = message.chat 10 | if chat: 11 | args = utils.get_args_raw(message) 12 | if args != str(message.chat.id+message.sender_id): 13 | await message.edit(f"Если ты точно хочешь это сделать, то напиши:\n.delme {message.chat.id+message.sender_id}") 14 | return 15 | await delete(chat, message, True) 16 | else: 17 | await message.edit("В лс не чищу!") 18 | @loader.sudo 19 | async def delmenowcmd(self, message): 20 | """Удаляет все сообщения от тебя без вопросов""" 21 | chat = message.chat 22 | if chat: 23 | await delete(chat, message, False) 24 | else: 25 | await message.edit("В лс не чищу!") 26 | 27 | async def delete(chat, message, now): 28 | if now: 29 | all = (await message.client.get_messages(chat, from_user="me")).total 30 | await message.edit(f"{all} сообщений будет удалено!") 31 | else: await message.delete() 32 | _ = not now 33 | async for msg in message.client.iter_messages(chat, from_user="me"): 34 | if _: 35 | await msg.delete() 36 | else: 37 | _ = "_" 38 | await message.delete() if now else "хули мусара хули мусара хули, едем так как ехали даже в хуй не дули" 39 | -------------------------------------------------------------------------------- /biography.py: -------------------------------------------------------------------------------- 1 | # requires: pydub 2 | from pydub import AudioSegment 3 | from .. import loader, utils 4 | from telethon import types 5 | import io 6 | import requests 7 | 8 | biography = requests.get("https://raw.githubusercontent.com/KeyZenD/l/master/biography.mp3").content 9 | 10 | class BiographyMod(loader.Module): 11 | """Биография""" 12 | strings = {'name': 'Биография'} 13 | 14 | 15 | async def biographycmd(self, message): 16 | """.biography 17 |     Наложение реплайнутого войса на минус кровостока 18 | """ 19 | reply = await message.get_reply_message() 20 | if not reply or not reply.file or not reply.file.mime_type.startswith("audio"): 21 | return await message.edit("Reply to audio.") 22 | await message.edit("Biography...") 23 | voice = io.BytesIO() 24 | await reply.download_media(voice) 25 | voice.seek(0) 26 | voice = AudioSegment.from_file(voice) 27 | biogr = io.BytesIO(biography) 28 | vol = utils.get_args_raw(message) 29 | if vol and vol.isdigit(): 30 | vol = 100-int(vol) 31 | else: 32 | vol = 20 33 | biogr.seek(0) 34 | biogr = AudioSegment.from_file(biogr)[0:len(voice)]-vol 35 | out = biogr.overlay(voice, position=0) 36 | output = io.BytesIO() 37 | output.name="biography.ogg" 38 | out.export(output, format="ogg", bitrate="64k", codec="libopus") 39 | output.seek(0) 40 | await message.client.send_file(message.to_id, output, reply_to=reply.id, voice_note=True, duration=len(out)/1000) 41 | await message.delete() 42 | -------------------------------------------------------------------------------- /MacAshoT.py: -------------------------------------------------------------------------------- 1 | from .. import loader,utils 2 | from PIL import Image,ImageFilter 3 | import io,random,string 4 | class aMod(loader.Module): 5 | strings={'name':'MacAshoT'} 6 | async def maccmd(S,message): 7 | R=True;Q='image';P='/';L='RGBA';K='Image?';A=message;C=await A.get_reply_message();B=io.BytesIO();M=None 8 | if A.file: 9 | if A.file.mime_type.split(P)[0]==Q:await A.download_media(B) 10 | elif C: 11 | if C.file: 12 | if C.file.mime_type.split(P)[0]==Q:M=R;await C.download_media(B) 13 | else:await A.edit(K);return 14 | else:await A.edit(K);return 15 | elif C: 16 | if C.file: 17 | if C.file.mime_type.split(P)[0]==Q:M=R;await C.download_media(B) 18 | else:await A.edit(K);return 19 | else:await A.edit(K);return 20 | try:I=Image.open(B) 21 | except:await A.edit(K);return 22 | await A.edit('Working...');F,G=I.size;B=Image.new(L,(F,G));J=min(F//100,G//100);D=Image.new(L,(F+J*40,G+J*40),'#fff') 23 | if I.mode==L: 24 | B.paste(I,(0,0),I);E=Image.new(L,(F,G)) 25 | for N in range(F): 26 | for O in range(G): 27 | if B.getpixel((N,O))!=(0,0,0,0):E.putpixel((N,O),(0,0,0)) 28 | else:B.paste(I,(0,0));E=Image.new(L,(F,G),'black') 29 | E=E.resize((F+J*5,G+J*5));D.paste(E,((D.width-E.width)//2,(D.height-E.height)//2),E);D=D.filter(ImageFilter.GaussianBlur(J*5));D.paste(B,((D.width-B.width)//2,(D.height-B.height)//2),B);H=io.BytesIO();H.name='-'.join([''.join([random.choice(string.hexdigits)for B in range(A)])for A in[5,4,3,2,1]])+'.png';D.save(H,'PNG');H.seek(0) 30 | if utils.get_args_raw(A):await A.client.send_file(A.to_id,H,force_document=R);await A.delete() 31 | elif M:await C.reply(file=H);await A.delete() 32 | else:await A.edit(file=H,text='') 33 | -------------------------------------------------------------------------------- /rysianskiy.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from .. import loader, utils 3 | 4 | logger = logging.getLogger(__name__) 5 | 6 | 7 | @loader.tds 8 | class RysianskiyMod(loader.Module): 9 | """Perevodit rysskiy na rysianskiy yazyk""" 10 | strings = {"name": "Rysianskiy yazyk", 11 | "nety_teksta": "Nety teksta dlya izmeneniya!"} 12 | 13 | async def client_ready(self, client, db): 14 | self.client = client 15 | 16 | @loader.owner 17 | async def rysianskiycmd(self, soobshenie): 18 | """.rysianskiy """ 19 | 20 | otvet = await soobshenie.get_reply_message() 21 | vvod = utils.get_args_raw(soobshenie) 22 | if not vvod: 23 | if not otvet or not otvet.text: 24 | await utils.answer(soobshenie, self.strings("nety_teksta", soobshenie)) 25 | return 26 | else: 27 | tekst = otvet.raw_text 28 | else: 29 | tekst = vvod 30 | vyvod = "" 31 | for simvol in tekst: 32 | if simvol.lower() in bykvy: 33 | bykva = bykvy[simvol.lower()] 34 | if simvol.isupper(): 35 | bykva = bykva.upper() 36 | else: 37 | bykva = simvol 38 | vyvod += bykva 39 | await utils.answer(soobshenie, vyvod) 40 | bykvy = {"а": "a", "б": "b", "в": "v", "г": "g", "д": "d", "е": "e", "ё": "yo", "ж": "j", "з": "z", "и": "i", "й": "y", "к": "k", "л": "l", "м": "m", "н": "n", "о": "o", "п": "p", "р": "r", "с": "s", "т": "t", "у": "y", "ф": "f", "х": "h", "ц": "ts", "ч": "ch", "ш": "sh", "щ": "sh'", "ъ": '"', "ы": "y", "ь": "'", "э": "e", "ю": "yu", "я": "ya"} 41 | -------------------------------------------------------------------------------- /OneMessage.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | from telethon.tl.types import Message 3 | 4 | class OneMessageMod(loader.Module): 5 | """@faq lines""" 6 | strings = {'name': 'OneMessage'} 7 | def __init__(self): 8 | self.name = self.strings['name'] 9 | async def client_ready(self, client, db): 10 | self.client = client 11 | self._db = db 12 | 13 | @loader.sudo 14 | async def omstartcmd(self, message): 15 | """Start OneMessage mode""" 16 | self._db.set("OneMessage", "status", True) 17 | self._db.set("OneMessage", "my_id", message.sender_id) 18 | await message.edit("OneMessage mode activated!") 19 | 20 | async def omstopcmd(self, message): 21 | """Stop OneMessage mode""" 22 | self._db.set("OneMessage", "status", False) 23 | await message.edit("OneMessage mode diactivated!") 24 | 25 | async def watcher(self, message): 26 | if not isinstance(message, Message): 27 | return 28 | if message.message: 29 | if message.raw_text[0] in self._db.get("friendly-telegram.modules.corectrl", "command_prefix", ".") or message.fwd_from: 30 | return 31 | if self._db.get("OneMessage", "status", None) and message.sender_id == self._db.get("OneMessage", "my_id", None) and not message.media: 32 | last_msg = (await self.client.get_messages(message.to_id, limit=2))[-1] 33 | if last_msg.sender_id == message.sender_id and not last_msg.fwd_from: 34 | text = last_msg.text 35 | text += "\n"*2 36 | text += message.text 37 | if message.is_reply: 38 | message, last_msg = last_msg, message 39 | try: 40 | await last_msg.edit(text) 41 | await message.delete() 42 | except: 43 | return 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /codefy.py: -------------------------------------------------------------------------------- 1 | # Friendly Telegram (telegram userbot) 2 | # Copyright (C) 2018-2019 The Authors 3 | 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # SUBSCRIBE TO t.me/keyzend pls 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | from .. import loader, utils 18 | 19 | import logging 20 | import asyncio 21 | 22 | logger = logging.getLogger(__name__) 23 | 24 | @loader.tds 25 | class CodefyMod(loader.Module): 26 | """Makes message monospace""" 27 | strings = {"name": "Codefy", 28 | "msg_is_emp": "Message is empty!"} 29 | @loader.ratelimit 30 | async def codecmd(self, message): 31 | """.code """ 32 | if message.is_reply: 33 | reply = await message.get_reply_message() 34 | code = reply.raw_text 35 | code = code.replace("<","<").replace(">",">") 36 | await message.edit(f"{code}") 37 | else: 38 | code = message.raw_text[5:] 39 | code = code.replace("<","<").replace(">",">") 40 | try: 41 | await message.edit(f"{code}") 42 | except: 43 | await message.edit(self.strings["msg_is_emp"]) 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /mediaspam.py: -------------------------------------------------------------------------------- 1 | from telethon import events 2 | from .. import loader, utils 3 | 4 | #испольуйте только на свой страх и риск 5 | #используя этот модуль вы принимаете то 6 | #что если получите бан, то на мне никакой ответственности 7 | 8 | 9 | 10 | def register(cb): 11 | cb(MSMod()) 12 | 13 | 14 | class MSMod(loader.Module): 15 | """Спаммер медиа(стикер/гиф/фото/видео/войс/видеовойс""" 16 | 17 | strings = {'name': 'МедиаСпам'} 18 | 19 | def __init__(self): 20 | self.name = self.strings['name'] 21 | self._me = None 22 | self._ratelimit = [] 23 | 24 | async def client_ready(self, client, db): 25 | self._db = db 26 | self._client = client 27 | self.me = await client.get_me() 28 | 29 | async def mediaspamcmd(self, message): 30 | """.mediaspam <количество> + реплай на медиа(стикер/гиф/фото/видео/войс/видеовойс)""" 31 | reply = await message.get_reply_message() 32 | if not reply: 33 | await message.edit(".mediaspam <количество> + реплай на медиа(стикер/гиф/фото/видео/войс/видеовойс") 34 | return 35 | if not reply.media: 36 | await message.edit(".mediaspam <количество> + реплай на медиа(стикер/гиф/фото/видео/войс/видеовойс") 37 | return 38 | media = reply.media 39 | 40 | args = utils.get_args(message) 41 | if not args: 42 | await message.edit(".mediaspam <количество> + реплай на медиа(стикер/гиф/фото/видео/войс/видеовойс") 43 | return 44 | count = args[0] 45 | count = count.strip() 46 | if not count.isdigit(): 47 | await message.edit(".mediaspam <количество> + реплай на медиа(стикер/гиф/фото/видео/войс/видеовойс") 48 | return 49 | count = int(count) 50 | 51 | await message.delete() 52 | for _ in range(count): 53 | await message.client.send_file(message.to_id, media) -------------------------------------------------------------------------------- /ph.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | import asyncio 3 | import requests 4 | from telethon.tl.types import DocumentAttributeFilename 5 | 6 | def register(cb): 7 | cb(UploadPHMod()) 8 | 9 | # @KeyZenD pls sub :3 10 | 11 | class UploadPHMod(loader.Module): 12 | """Upload video and photo to telegra.ph""" 13 | strings = {"name": "UploadPH"} 14 | 15 | def __init__(self): 16 | self.name = self.strings['name'] 17 | 18 | 19 | async def phcmd(self, message): 20 | """.ph """ 21 | if message.is_reply: 22 | reply_message = await message.get_reply_message() 23 | data = await check_media(reply_message) 24 | if isinstance(data, bool): 25 | await message.edit("Reply to photo or video/gif") 26 | return 27 | else: 28 | await message.edit("Reply to photo or video/gif") 29 | return 30 | 31 | 32 | file = await message.client.download_media(data, bytes) 33 | path = requests.post('https://te.legra.ph/upload', files={'file': ('file', file, None)}).json() 34 | try: 35 | link = 'https://te.legra.ph'+path[0]['src'] 36 | except KeyError: 37 | link = path["error"] 38 | await message.edit(""+link+"") 39 | 40 | 41 | async def check_media(reply_message): 42 | if reply_message and reply_message.media: 43 | if reply_message.photo: 44 | data = reply_message.photo 45 | elif reply_message.document: 46 | if DocumentAttributeFilename(file_name='AnimatedSticker.tgs') in reply_message.media.document.attributes: 47 | return False 48 | if reply_message.audio or reply_message.voice: 49 | return False 50 | data = reply_message.media.document 51 | else: 52 | return False 53 | else: 54 | return False 55 | if not data or data is None: 56 | return False 57 | else: 58 | return data 59 | 60 | 61 | -------------------------------------------------------------------------------- /ticker.py: -------------------------------------------------------------------------------- 1 | # Friendly Telegram (telegram userbot) 2 | # Copyright (C) 2018-2019 The Authors 3 | 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # SUBSCRIBE TO t.me/keyzend pls 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | from .. import loader, utils 18 | 19 | import logging 20 | import asyncio 21 | 22 | logger = logging.getLogger(__name__) 23 | 24 | 25 | @loader.tds 26 | class TickerMod(loader.Module): 27 | """Makes your messages type slower""" 28 | strings = {"name": "Ticker", 29 | "no_message": ".ticker [any text?]", 30 | "delay_typer_cfg_doc": "How long to delay showing?"} 31 | 32 | def __init__(self): 33 | self.config = loader.ModuleConfig("DELAY_TICKER", 0.04, lambda m: self.strings("delay_tikcer_cfg_doc", m)) 34 | 35 | @loader.ratelimit 36 | async def tickercmd(self, message): 37 | """.ticker """ 38 | a = utils.get_args_raw(message) 39 | if not a: 40 | await utils.answer(message, self.strings("no_message", message)) 41 | return 42 | for c in a: 43 | a = a[-1]+a[0:-1] 44 | message = await utils.answer(message, f"⁠⁠⁠⁠⁠ {a} ⁠⁠⁠⁠⁠") 45 | await asyncio.sleep(0.3) -------------------------------------------------------------------------------- /StickTools.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | import io 3 | from PIL import Image 4 | from string import hexdigits 5 | 6 | def register(cb): 7 | cb(StickToolsMod()) 8 | 9 | 10 | class StickToolsMod(loader.Module): 11 | """""" 12 | 13 | strings = {'name': 'StickTools'} 14 | 15 | def __init__(self): 16 | self.name = self.strings['name'] 17 | 18 | async def stick2piccmd(self, message): 19 | """reply to Sticker\nsend stricker as image""" 20 | await convert(message, False) 21 | 22 | async def stick2filecmd(self, message): 23 | """reply to Sticker\nsend stricker as image""" 24 | await convert(message, True) 25 | 26 | async def convert(message, as_file): 27 | reply = await message.get_reply_message() 28 | if not reply or not reply.sticker: 29 | await message.edit("Reply to sticker!") 30 | return 31 | fname = reply.sticker.attributes[-1].file_name 32 | if ".tgs" in fname: 33 | await message.edit("Reply to not animated sticker!") 34 | return 35 | bg = (0,0,0,0) 36 | args = utils.get_args(message) 37 | if args: 38 | args = args[0] 39 | if args.startswith("#"): 40 | for ch in args[1:]: 41 | if ch not in hexdigits: 42 | break 43 | bg = args 44 | 45 | im = io.BytesIO() 46 | await message.client.download_file(reply, im) 47 | im = Image.open(im) 48 | img = Image.new("RGBA", im.size, bg) 49 | if im.mode == "RGBA": 50 | img.paste(im, (0,0), im) 51 | else: 52 | img.paste(im, (0,0)) 53 | out = io.BytesIO() 54 | out.name = fname+".png" 55 | img.save(out, "PNG") 56 | out.seek(0) 57 | await message.delete() 58 | await message.client.send_file(message.to_id, out, force_document=as_file, reply_to=reply) 59 | -------------------------------------------------------------------------------- /cheval.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | 3 | 4 | class channelEvalMod(loader.Module): 5 | """Выполняет команду в канале""" 6 | strings = {"name":"ChannelEval"} 7 | 8 | async def chevalcmd(self, message): 9 | """.channel <канал> <комманда в том виде, в котором бы ты отправил её в чат>""" 10 | args = utils.get_args(message) 11 | reply = await message.get_reply_message() 12 | if not args: 13 | return await message.edit("Укажи канал.") 14 | if len(args) < 1: 15 | return await message.edit("Укажи команду для выполнения.") 16 | channel = args[0] 17 | args = args[1:] 18 | if not args[0].isdigit() and reply: 19 | rmsg = reply.fwd_from.saved_from_msg_id if (reply and reply.fwd_from) else None 20 | fullcmd = " ".join(args) 21 | elif args[0].isdigit(): 22 | rmsg = int(args[0]) 23 | fullcmd = " ".join(args[1:]) 24 | else: 25 | rmsg = None 26 | fullcmd = " ".join(args) 27 | 28 | cmd = fullcmd.split(" ")[0] 29 | if cmd.startswith("."): cmd = cmd[1:] 30 | if channel.isdigit(): channel = int(channel) 31 | if not cmd in self.allmodules.commands.keys(): 32 | return await message.edit("Кажется у тебя нет в списке команды ."+cmd+"\nКстати сокращения команд я не понимяу)\n"+message.raw_text+"") 33 | 34 | try: m = await message.client.send_message(channel, fullcmd, reply_to=rmsg) 35 | except Exception as e: return await message.edit("Возникла ошибка:\n"+repr(e)) 36 | await self.allmodules.commands[cmd](m) 37 | try: url = f"https://t.me/c/{m.to_id.channel_id}/{m.id}" 38 | except: url = "" 39 | await message.edit(f'Команда отправлена!') -------------------------------------------------------------------------------- /MicroQuotes.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | import io 3 | from PIL import Image, ImageFont, ImageDraw 4 | import requests 5 | import textwrap 6 | 7 | @loader.tds 8 | class MicroQuotesMod(loader.Module): 9 | """Микроцитаты""" 10 | strings = {"name": "MicroQuotes"} 11 | 12 | async def mqcmd(self, message): 13 | """.mq <реплай на текст>""" 14 | bw = False if utils.get_args(message) else True 15 | reply = await message.get_reply_message() 16 | if not reply or not reply.raw_text: 17 | await message.edit("Ответь командой на умную цитату!") 18 | return 19 | sender = reply.sender_id 20 | 21 | if not sender: 22 | sender = message.chat.id 23 | if sender == 1087968824: 24 | sender = message.chat.id 25 | pfp = await message.client.download_profile_photo(sender, bytes) 26 | await message.edit("И сказал этот гений...") 27 | if not pfp: 28 | pfp = b'BM:\x00\x00\x00\x00\x00\x00\x006\x00\x00\x00(\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x18\x00\x00\x00\x00\x00\x04\x00\x00\x00\xc4\x0e\x00\x00\xc4\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00' 29 | text = "\n".join(textwrap.wrap(reply.raw_text, 30)) 30 | text = "“"+text+"„" 31 | bf = requests.get("https://raw.githubusercontent.com/KeyZenD/l/master/times.ttf").content 32 | font = ImageFont.truetype(io.BytesIO(bf), 50) 33 | im = Image.open(io.BytesIO(pfp)) 34 | if bw: 35 | im = im.convert("L") 36 | im = im.convert("RGBA").resize((1024, 1024)) 37 | w, h = im.size 38 | w_, h_ = 20*(w//100), 20*(h//100) 39 | im_ = Image.new("RGBA", (w-w_, h-h_), (0, 0, 0)) 40 | im_.putalpha(150) 41 | im.paste(im_, (w_//2, h_//2), im_) 42 | draw = ImageDraw.Draw(im) 43 | _w, _h = draw.textsize(text=text, font=font) 44 | x, y = (w-_w)//2, (h-_h)//2 45 | draw.text((x, y), text=text, font=font, fill="#fff", align="center") 46 | output=io.BytesIO() 47 | im.save(output, "PNG") 48 | output.seek(0) 49 | await reply.reply(file=output) 50 | await message.delete() 51 | -------------------------------------------------------------------------------- /YTsearch.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Friendly Telegram (telegram userbot) 4 | # Copyright (C) 2018-2020 The Authors 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # если не подписан на t.me/keyzend 16 | # твоя мама шлюха 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from .. import loader, utils # pylint: disable=relative-beyond-top-level 21 | from telethon.tl.types import DocumentAttributeFilename 22 | import logging 23 | 24 | from youtube_search import YoutubeSearch 25 | 26 | 27 | logger = logging.getLogger(__name__) 28 | 29 | def register(cb): 30 | cb(YTsearchod()) 31 | 32 | 33 | @loader.tds 34 | class YTsearchMod(loader.Module): 35 | """Поиск видео на ютубе""" 36 | strings = { 37 | "name": "YTsearch" 38 | } 39 | 40 | async def client_ready(self, client, db): 41 | self.client = client 42 | 43 | 44 | @loader.sudo 45 | async def ytcmd(self, message): 46 | """текст или реплай""" 47 | text = utils.get_args_raw(message) 48 | if not text: 49 | reply = await message.get_reply_message() 50 | if not reply: 51 | await message.delete() 52 | return 53 | text = reply.raw_text 54 | results = YoutubeSearch(text, max_results=10).to_dict() 55 | out = f'Найдено по запросу: {text}' 56 | for r in results: 57 | out += f'\n\n{r["title"]}' 58 | 59 | await message.edit(out) 60 | -------------------------------------------------------------------------------- /MirrorFlip.py: -------------------------------------------------------------------------------- 1 | _C='png' 2 | _B='name' 3 | _A='image' 4 | _R='отражает' 5 | _P='часть.' 6 | from .. import loader as _L,utils as U 7 | import logging,asyncio 8 | from telethon.tl.types import DocumentAttributeFilename as DAF 9 | from PIL import Image,ImageOps as IO 10 | from io import BytesIO as ist 11 | logger=logging.getLogger(__name__) 12 | @_L.tds 13 | class MFMod(_L.Module): 14 | f'{_R} фоточки';strings={_B:'MirrorFlip'} 15 | def __init__(A):A.name=A.strings[_B] 16 | async def llcmd(A,message):await KZD(message,1) 17 | async def rrcmd(A,message):await KZD(message,2) 18 | async def uucmd(A,message):await KZD(message,3) 19 | async def ddcmd(A,message):await KZD(message,4) 20 | async def KZD(message,type): 21 | S='sticker';A=message;N=await A.get_reply_message();Q,J=await CM(N) 22 | if not Q or not N:await A.edit('Реплай на стикер или фото!');return 23 | O='KZD.'+J;P=U.get_args_raw(A) 24 | if P: 25 | if P in[_A[:A]for A in range(1,len(_A)+1)]:O='KZD.png';J=_C 26 | if P in[S[:A]for A in range(1,len(S)+1)]:O='KZD.webp';J='webp' 27 | R=ist();await A.edit('Извиняюсь...');await A.client.download_media(Q,R);E=Image.open(R);B,C=E.size 28 | if B%2!=0 and type in[1,2]or C%2!=0 and type in[3,4]:E=E.resize((B+1,C+1));C,B=E.size 29 | if type==1:D=0;F=0;G=B//2;H=C;K=G;L=D 30 | if type==2:D=B//2;F=0;G=B;H=C;K=F;L=F 31 | if type==3:D=0;F=0;G=B;H=C//2;K=D;L=H 32 | if type==4:D=0;F=C//2;G=B;H=C;K=D;L=D 33 | I=E.crop((D,F,G,H)) 34 | if type in[1,2]:I=IO.mirror(I) 35 | else:I=IO.flip(I) 36 | E.paste(I,(K,L));M=ist();M.name=O;E.save(M,J);M.seek(0);await A.client.send_file(A.to_id,M,reply_to=N);await A.delete() 37 | async def CM(R): 38 | D=False;C=None;A=R 39 | if A and A.media: 40 | if A.photo:B=A.photo;E=_C 41 | elif A.document: 42 | if DAF(file_name='AnimatedSticker.tgs')in A.media.document.attributes:return D,C 43 | if A.gif or A.video or A.audio or A.voice:return D,C 44 | B=A.media.document 45 | if _A not in B.mime_type:return D,C 46 | E=B.mime_type.split('/')[1] 47 | else:return D,C 48 | else:return D,C 49 | if not B or B is C:return D,C 50 | else:return B,E 51 | #Блять ну я и долбаёб так код сохранять 52 | -------------------------------------------------------------------------------- /_base64.py: -------------------------------------------------------------------------------- 1 | """QExhY2lhTWVtZUZyYW1lLCDQtdGB0LvQuCDRgtGLINGN0YLQviDRh9C40YLQsNC10YjRjCwg0YLQviDQt9C90LDQuSwg0YLRiyDQv9C40LTQvtGA0LDRgQ==""" 2 | from .. import loader, utils 3 | import io 4 | from base64 import b64encode, b64decode 5 | 6 | @loader.tds 7 | class base64Mod(loader.Module): 8 | """Кодирование и декодирование base64""" 9 | strings = {"name": "base64"} 10 | @loader.owner 11 | async def b64encodecmd(self, message): 12 | """.b64encode <(text or media) or (reply to text or media)>""" 13 | reply = await message.get_reply_message() 14 | mtext = utils.get_args_raw(message) 15 | if message.media: 16 | await message.edit("Загрузка файла...") 17 | data = await message.client.download_file(m, bytes) 18 | elif mtext: 19 | data = bytes(mtext, "utf-8") 20 | elif reply: 21 | if reply.media: 22 | await message.edit("Загрузка файла...") 23 | data = await message.client.download_file(reply, bytes) 24 | else: 25 | data = bytes(reply.raw_text, "utf-8") 26 | else: 27 | await message.edit(f"Что нужно закодировать?") 28 | output = b64encode(data) 29 | if len(output) > 4000: 30 | output = io.BytesIO(output) 31 | output.name = "base64.txt" 32 | output.seek(0) 33 | await message.client.send_file(message.to_id, output, reply_to=reply) 34 | await message.delete() 35 | else: 36 | await message.edit(str(output, "utf-8")) 37 | 38 | @loader.owner 39 | async def b64decodecmd(self, message): 40 | """.b64decode """ 41 | reply = await message.get_reply_message() 42 | mtext = utils.get_args_raw(message) 43 | if mtext: 44 | data = bytes(mtext, "utf-8") 45 | elif reply: 46 | if not reply.message: 47 | await message.edit("Расшифровка файлов невозможна...") 48 | return 49 | else: 50 | data = bytes(reply.raw_text, "utf-8") 51 | else: 52 | await message.edit(f"Что нужно декодировать?") 53 | return 54 | try: 55 | output = b64decode(data) 56 | await message.edit(str(output, "utf-8")) 57 | except: 58 | await message.edit("Ошибка декодирования!") 59 | return -------------------------------------------------------------------------------- /stext.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | import io 3 | import logging 4 | import requests 5 | from textwrap import wrap 6 | from PIL import Image, ImageDraw, ImageFont 7 | bytes_font = requests.get("https://github.com/KeyZenD/l/blob/master/bold.ttf?raw=true").content 8 | logger = logging.getLogger(__name__) 9 | 10 | def register(cb): 11 | cb(Text2stickMod()) 12 | 13 | @loader.tds 14 | class Text2stickMod(loader.Module): 15 | """Text to sticker""" 16 | strings = {"name": "StickText"} 17 | 18 | async def client_ready(self, client, db): 19 | self.client = client 20 | 21 | @loader.owner 22 | async def stextcmd(self, message): 23 | """.stext """ 24 | await message.delete() 25 | text = utils.get_args_raw(message) 26 | reply = await message.get_reply_message() 27 | if not text: 28 | if not reply: 29 | text = "#ffffff .stext " 30 | elif not reply.message: 31 | text = "#ffffff .stext " 32 | else: 33 | text = reply.raw_text 34 | color = text.split(" ", 1)[0] 35 | if color.startswith("#") and len(color) == 7: 36 | for ch in color.lower()[1:]: 37 | if ch not in "0123456789abcdef": 38 | break 39 | if len(text.split(" ", 1)) > 1: 40 | text = text.split(" ", 1)[1] 41 | else: 42 | if reply: 43 | if reply.message: 44 | text = reply.raw_text 45 | else: 46 | color = "#FFFFFF" 47 | txt = [] 48 | for line in text.split("\n"): 49 | txt.append("\n".join(wrap(line, 30))) 50 | text = "\n".join(txt) 51 | font = io.BytesIO(bytes_font) 52 | font = ImageFont.truetype(font, 100) 53 | image = Image.new("RGBA", (1, 1), (0,0,0,0)) 54 | draw = ImageDraw.Draw(image) 55 | w, h = draw.multiline_textsize(text=text, font=font) 56 | image = Image.new("RGBA", (w+100, h+100), (0,0,0,0)) 57 | draw = ImageDraw.Draw(image) 58 | draw.multiline_text((50,50), text=text, font=font, fill=color, align="center") 59 | output = io.BytesIO() 60 | output.name = color+".webp" 61 | image.save(output, "WEBP") 62 | output.seek(0) 63 | await self.client.send_file(message.to_id, output, reply_to=reply) 64 | -------------------------------------------------------------------------------- /YandexRS.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | import json 3 | import io 4 | import requests 5 | from PIL import Image 6 | import random 7 | import string 8 | 9 | @loader.tds 10 | class YandexReverseSearchMod(loader.Module): 11 | """Reverse image search via Yandex (he is the best, imho)""" 12 | strings = {"name": "YandexReverseSearch", 13 | "search": "⚪⚪⚪\n⚪❓⚪\n⚪⚪⚪", 14 | "no_reply": "Reply to image or sticker!", 15 | "result": '🔴⚪🔴|See\n⚪🔴⚪|Search\n⚪🔴⚪|Results', 16 | "error": 'Something went wrong...'} 17 | @loader.owner 18 | async def yarscmd(self, message): 19 | """.yars """ 20 | reply = await message.get_reply_message() 21 | data = await check_media(message, reply) 22 | if not data: 23 | await utils.answer(message, self.strings("no_reply", message)) 24 | return 25 | await utils.answer(message, self.strings("search", message)) 26 | searchUrl = 'https://yandex.ru/images/search' 27 | files = {'upfile': ('blob', data, 'image/jpeg')} 28 | params = {'rpt': 'imageview', 'format': 'json', 'request': '{"blocks":[{"block":"b-page_type_search-by-image__link"}]}'} 29 | response = requests.post(searchUrl, params=params, files=files) 30 | if response.ok: 31 | query_string = json.loads(response.content)['blocks'][0]['params']['url'] 32 | link = searchUrl + '?' + query_string 33 | text = self.strings("result", message).format(link) 34 | await utils.answer(message, text) 35 | else: 36 | await utils.answer(message, self.strings("error", message)) 37 | 38 | async def check_media(message, reply): 39 | if reply and reply.media: 40 | if reply.photo: 41 | data = reply.photo 42 | elif reply.document: 43 | if reply.gif or reply.video or reply.audio or reply.voice: 44 | return None 45 | data = reply.media.document 46 | else: 47 | return None 48 | else: 49 | return None 50 | if not data or data is None: 51 | return None 52 | else: 53 | data = await message.client.download_file(data, bytes) 54 | img = io.BytesIO(data) 55 | return img 56 | -------------------------------------------------------------------------------- /dotify.py: -------------------------------------------------------------------------------- 1 | from PIL import Image, ImageDraw 2 | import io 3 | import asyncio 4 | import logging 5 | 6 | from .. import loader, utils 7 | 8 | logger = logging.getLogger(__name__) 9 | 10 | class DotifyMod(loader.Module): 11 | """Image to dot 12 | .cmd + reply to img 13 | the bigger, the slower and bugger 14 | recommended not more 1000""" 15 | strings = {"name": "[PRIVATE]Dotify"} 16 | 17 | @loader.unrestricted 18 | async def dotifycmd(self, message): 19 | """Image to RGB dots""" 20 | mode = False 21 | reply, pix = await parse(message) 22 | if reply: 23 | await dotify(message, reply, pix, mode) 24 | async def dotificmd(self, message): 25 | """Image to BW dots """ 26 | mode = True 27 | reply, pix = await parse(message) 28 | if reply: 29 | await dotify(message, reply, pix, mode) 30 | 31 | async def parse(message): 32 | reply = await message.get_reply_message() 33 | if not reply: 34 | await message.edit("Reply to Image!") 35 | return None, None 36 | args = utils.get_args(message) 37 | pix = 100 38 | if args: 39 | args=args[0] 40 | if args.isdigit(): 41 | pix = int(args) if int(args) > 0 else 100 42 | return reply, pix 43 | 44 | async def dotify(message, reply, pix, mode): 45 | await message.edit("Putting dots...") 46 | count = 24 47 | im_ = Image.open(io.BytesIO(await reply.download_media(bytes))) 48 | if im_.mode == "RGBA": 49 | temp = Image.new("RGB", im_.size, "#000") 50 | temp.paste(im_, (0, 0), im_) 51 | im_ = temp 52 | 53 | im = im_.convert("L") 54 | im_ = im if mode else im_ 55 | [_.thumbnail((pix, pix)) for _ in[im, im_]] 56 | w, h = im.size 57 | img = Image.new(im_.mode, (w*count+(count//2), h*count+(count//2)), 0) 58 | draw = ImageDraw.Draw(img) 59 | 60 | def cirsle(im, x, y, r, fill): 61 | x += r//2 62 | y += r//2 63 | draw = ImageDraw.Draw(im) 64 | draw.ellipse((x-r, y-r, x+r, y+r), fill) 65 | return im 66 | 67 | _x = _y = count//2 68 | for x in range(w): 69 | for y in range(h): 70 | r = im.getpixel((x, y)) 71 | fill = im_.getpixel((x, y)) 72 | cirsle(img, _x, _y, r//count, fill) 73 | _y += count 74 | _x += count 75 | _y = count//2 76 | 77 | out = io.BytesIO() 78 | out.name = "out.png" 79 | img.save(out) 80 | out.seek(0) 81 | await reply.reply(file=out) 82 | await message.delete() 83 | -------------------------------------------------------------------------------- /distortion_no_api.py: -------------------------------------------------------------------------------- 1 | import io, random, glob, os 2 | from PIL import Image 3 | from telethon.tl.types import DocumentAttributeFilename 4 | from uniborg.util import admin_cmd 5 | """Не подписался без матери остался""" 6 | """https://t.me/KeyZenD""" 7 | """автор этого говнокода @DneZyeK""" 8 | 9 | @borg.on(admin_cmd(pattern=".d(.*)", allow_sudo=True)) 10 | async def d(message): 11 | inp =message.pattern_match.group(1) 12 | pop = 60 13 | if inp: 14 | inp = inp.strip() 15 | if inp.isdigit(): 16 | if int(inp) > 0: 17 | pop = inp 18 | 19 | if message.is_reply: 20 | reply_message = await message.get_reply_message() 21 | data = await check_media(reply_message) 22 | if isinstance(data, bool): 23 | await message.edit("‮Reply to image, fucking idiot") 24 | return 25 | else: 26 | await message.edit("‮Reply to image, fucking idiot") 27 | return 28 | await message.edit(" ‮`P` `r` `o` `c` `e` `s` `s` `i` `n` `g` `.` `.` `.`") 29 | for distorted in glob.glob("distorted*"): 30 | os.remove(distorted) 31 | for findistorted in glob.glob("*/distorted*"): 32 | os.remove(findistorted) 33 | fname = f"distorted{random.randint(1, 100)}.png" 34 | image = io.BytesIO() 35 | await message.client.download_media(data, image) 36 | image = Image.open(image) 37 | image.save(fname) 38 | imgdimens = image.width, image.height 39 | distortcmd = f"convert {fname} -liquid-rescale {pop}%x{pop}%! -resize {imgdimens[0]}x{imgdimens[1]}\! {fname}" 40 | os.system(distortcmd) 41 | image = Image.open(f"{fname}") 42 | buf = io.BytesIO() 43 | buf.name = f'image.png' 44 | image.save(buf, 'PNG') 45 | buf.seek(0) 46 | await message.edit("‮`S` `e` `n` `d` `i` `n` `g` `.` `.` `.`") 47 | await message.client.send_file(message.chat_id, buf, reply_to=reply_message.id) 48 | await message.delete() 49 | 50 | 51 | 52 | 53 | async def check_media(reply_message): 54 | if reply_message and reply_message.media: 55 | if reply_message.photo: 56 | data = reply_message.photo 57 | elif reply_message.document: 58 | if DocumentAttributeFilename(file_name='AnimatedSticker.tgs') in reply_message.media.document.attributes: 59 | return False 60 | if reply_message.gif or reply_message.video or reply_message.audio or reply_message.voice: 61 | return False 62 | data = reply_message.media.document 63 | else: 64 | return False 65 | else: 66 | return False 67 | 68 | if not data or data is None: 69 | return False 70 | else: 71 | return data -------------------------------------------------------------------------------- /gg.gg.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Friendly Telegram (telegram userbot) 4 | # Copyright (C) 2018-2020 @DneZyeK | sub to @KeyZenD 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | 19 | import logging 20 | from .. import loader, utils 21 | import telethon 22 | from requests import post 23 | 24 | logger = logging.getLogger(__name__) 25 | 26 | async def register(cb): 27 | cb(WhoIsMod()) 28 | 29 | 30 | @loader.tds 31 | class GGdotGGMod(loader.Module): 32 | """Сокращение ссылок через сервис gg.gg""" 33 | strings = { 34 | "name": "gg.gg", 35 | "some_rong": "Ты делаешь что-то не так!\nНапиши .help gg.gg для информации." 36 | } 37 | 38 | async def client_ready(self, client, db): 39 | self.client = client 40 | 41 | async def ggcmd(self, message): 42 | """.gg <длинная ссылка или реплай на ссылку> """ 43 | m_text = utils.get_args_raw(message) 44 | if not m_text: 45 | reply = await message.get_reply_message() 46 | if not reply: 47 | await utils.answer(message, self.strings["some_rong"]) 48 | return 49 | long_url = reply.raw_text 50 | else: 51 | long_url = m_text 52 | 53 | 54 | if 'http://' not in long_url and 'https://' not in long_url: 55 | long_url = 'http://' + long_url 56 | t_check = f"URL: {long_url}\nCheck..." 57 | await utils.answer(message, t_check) 58 | check = post('http://gg.gg/check', data={'custom_path': None, 'use_norefs': '0', 'long_url': long_url, 'app': 'site', 'version': '0.1'}).text 59 | if check != "ok": 60 | await utils.answer(message, check) 61 | return 62 | await utils.answer(message, "Create...") 63 | short = post('http://gg.gg/create', data={'custom_path': None, 'use_norefs': '0', 'long_url': long_url, 'app': 'site', 'version': '0.1'}).text 64 | await utils.answer(message, short) 65 | 66 | -------------------------------------------------------------------------------- /urldl.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | import io 3 | from telethon.tl.types import MessageEntityUrl, MessageEntityTextUrl 4 | import os 5 | import aiohttp 6 | 7 | class aMod(loader.Module): 8 | strings = {"name": "UrlDl"} 9 | 10 | async def urldlcmd(self, event): 11 | await downloading(event) 12 | 13 | async def urldlbigcmd(self, event): 14 | await downloading(event, True) 15 | 16 | async def downloading(event, big=False): 17 | args = utils.get_args_raw(event) 18 | reply = await event.get_reply_message() 19 | if not args: 20 | if not reply: 21 | await event.edit("Ссылки нету!") 22 | return 23 | message = reply 24 | else: 25 | message = event 26 | 27 | if not message.entities: 28 | await event.edit("Ссылки нету!") 29 | return 30 | 31 | urls = [] 32 | for ent in message.entities: 33 | if type(ent) in [MessageEntityUrl, MessageEntityTextUrl]: 34 | url_ = True 35 | if type(ent) == MessageEntityUrl: 36 | offset = ent.offset 37 | length = ent.length 38 | url = message.raw_text[offset:offset+length] 39 | else: 40 | url = ent.url 41 | if not url.startswith("http"): 42 | url = "http://"+url 43 | urls.append(url) 44 | 45 | if not urls: 46 | await event.edit("Ссылки нету!") 47 | return 48 | async with aiohttp.ClientSession() as session: 49 | for url in urls: 50 | try: 51 | await event.edit("Загрузка...\n"+url) 52 | fname = url.split("/")[-1] 53 | async with session.get(url) as response: 54 | if big: 55 | f = open(fname, "wb") 56 | async for chunk in response.content.iter_chunked(1024): 57 | f.write(chunk) 58 | f.close() 59 | await event.edit("Отправка...\n"+url) 60 | await event.client.send_file(event.to_id, open(fname, "rb"), reply_to=reply) 61 | os.remove(fname) 62 | else: 63 | file = io.BytesIO(await response.read()) 64 | file.name = fname 65 | file.seek(0) 66 | await event.edit("Отправка...\n"+url) 67 | await event.client.send_file(event.to_id, file, reply_to=reply) 68 | 69 | except Exception as e: 70 | await event.reply("Ошибка при загрузке!\n"+url+"\n"+str(e)+"") 71 | 72 | await event.delete() 73 | -------------------------------------------------------------------------------- /Hasher.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | from hashlib import md5, sha1, sha224, sha256, sha384, sha512, blake2b, blake2s 3 | 4 | def register(cb): 5 | cb(HasherMod()) 6 | 7 | class HasherMod(loader.Module): 8 | """Hashing text and files""" 9 | strings = {'name': 'Hasher'} 10 | def __init__(self): 11 | self.name = self.strings['name'] 12 | self._me = None 13 | self._ratelimit = [] 14 | async def client_ready(self, client, db): 15 | self._db = db 16 | self._client = client 17 | self.me = await client.get_me() 18 | 19 | async def md5cmd(self, message): 20 | """.md5 <(text or media) or (reply to text or media)>\nHashing to md5""" 21 | await hashing(message, 0) 22 | async def sha1cmd(self, message): 23 | """.sha1 <(text or media) or (reply to text or media)\nHashing to sha1""" 24 | await hashing(message, 1) 25 | async def sha224cmd(self, message): 26 | """.sha224 <(text or media) or (reply to text or media)\nHashing to sha224""" 27 | await hashing(message, 2) 28 | async def sha256cmd(self, message): 29 | """.sha255 <(text or media) or (reply to text or media)\nHashing to sha256""" 30 | await hashing(message, 3) 31 | async def sha384cmd(self, message): 32 | """.sha384 <(text or media) or (reply to text or media)\nHashing to sha384""" 33 | await hashing(message, 4) 34 | async def sha512cmd(self, message): 35 | """.sha512 <(text or media) or (reply to text or media)\nHashing to sha512""" 36 | await hashing(message, 5) 37 | async def blake2bcmd(self, message): 38 | """.blake2 <(text or media) or (reply to text or media)\nHashing to blake2""" 39 | await hashing(message, 6) 40 | async def blake2scmd(self, message): 41 | """.blake2s <(text or media) or (reply to text or media)\nHashing to blake2s""" 42 | await hashing(message, 7) 43 | 44 | async def hashing(m, type): 45 | types = [md5, sha1, sha224, sha256, sha384, sha512, blake2b, blake2s] 46 | typez = ["md5", "sha1", "sha224", "sha256", "sha384", "sha512", "blake2b", "blake2s"] 47 | 48 | reply = await m.get_reply_message() 49 | mtext = utils.get_args_raw(m) 50 | if m.media: 51 | await m.edit("D o w n l o a d i n g . . .") 52 | data = await m.client.download_file(m, bytes) 53 | elif mtext: 54 | data = mtext.encode() 55 | elif reply: 56 | if reply.media: 57 | await m.edit("D o w n l o a d i n g . . .") 58 | data = await m.client.download_file(reply, bytes) 59 | else: 60 | data = reply.raw_text.encode() 61 | else: 62 | await m.edit(f"What hashing to {typez[type]}?") 63 | return 64 | 65 | await m.edit("H a s h i n g . . .") 66 | try: 67 | result = types[type](data) 68 | await m.edit(typez[type].upper()+": " + str(result.hexdigest()).upper()+"") 69 | except: 70 | await m.edit("ERЯOR!") 71 | -------------------------------------------------------------------------------- /QRtools.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | from telethon.tl.types import DocumentAttributeFilename 3 | from requests import get, post 4 | from PIL import Image 5 | from io import BytesIO 6 | 7 | @loader.tds 8 | class QRtoolsMod(loader.Module): 9 | """Generator and reader of QR codes""" 10 | strings = {"name": "QR tool's"} 11 | @loader.owner 12 | async def makeqrcmd(self, message): 13 | """.makeqr """ 14 | text = utils.get_args_raw(message) 15 | reply = await message.get_reply_message() 16 | file = False 17 | if not text or text.lower() == ".file": 18 | if text and text == ".file": 19 | file = True 20 | if not reply or not reply.message: 21 | await message.edit("Нет текста для кодирования!") 22 | return 23 | text = reply.raw_text 24 | else: 25 | if text.startswith(".file"): 26 | file = True 27 | text = text[5:].strip() 28 | url = "https://api.qrserver.com/v1/create-qr-code/?data={}&size=512x512&charset-source=UTF-8&charset-target=UTF-8&ecc=L&color=0-0-0&bgcolor=255-255-255&margin=1&qzone=1&format=png" 29 | r = get(url.format(text), stream=True) 30 | qrcode = BytesIO() 31 | qrcode.name = "qr.png" if file else "qr.webp" 32 | Image.open(BytesIO(r.content)).save(qrcode) 33 | qrcode.seek(0) 34 | await message.delete() 35 | await message.client.send_file(message.to_id, qrcode, reply_to=reply, force_document=file) 36 | 37 | @loader.owner 38 | async def readqrcmd(self, message): 39 | """.readqr """ 40 | ok = await check(message) 41 | if not ok: 42 | reply = await message.get_reply_message() 43 | ok = await check(reply) 44 | if not ok: 45 | text = "Это не изображение!" if reply else "Нечего не передано!" 46 | await message.edit(text) 47 | return 48 | file = BytesIO() 49 | file.name = "qr.png" 50 | data = await message.client.download_file(ok) 51 | Image.open(BytesIO(data)).save(file) 52 | url = "https://api.qrserver.com/v1/read-qr-code/?outputformat=json" 53 | resp = post(url, files={"file": file.getvalue()}) 54 | text = resp.json()[0]["symbol"][0]["data"] 55 | if not text: 56 | text = "Невозможно распознать или QR пуст!" 57 | await utils.answer(message, text) 58 | 59 | async def check(msg): 60 | if msg and msg.media: 61 | if msg.photo: 62 | ok = msg.photo 63 | elif msg.document: 64 | if DocumentAttributeFilename(file_name='AnimatedSticker.tgs') in msg.media.document.attributes: 65 | return False 66 | if msg.gif or msg.video or msg.audio or msg.voice: 67 | return False 68 | ok = msg.media.document 69 | else: 70 | return False 71 | else: 72 | return False 73 | if not ok or ok is None: 74 | return False 75 | else: 76 | return ok 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /Glitcher.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import logging 3 | import sys, os, random 4 | from .. import loader, utils 5 | 6 | logger = logging.getLogger(__name__) 7 | 8 | 9 | @loader.tds 10 | class GlitcherMod(loader.Module): 11 | """Glitcher of anything""" 12 | strings = {"name": "Glitcher", 13 | "reply": "Reply to message!", 14 | "error": "Impossible to upload file!", 15 | "processing": "Work in progress!"} 16 | 17 | @loader.unrestricted 18 | async def glitchcmd(self, message): 19 | """.glitch level: float or int """ 20 | reply = await message.get_reply_message() 21 | if not reply: 22 | await message.edit("".join([ random.choice(html).format(ch) for ch in self.strings("reply", message)])) 23 | return 24 | if not reply.file: 25 | infile = "message.txt" 26 | f = open(infile,"w") 27 | f.write(reply.text) 28 | f.close() 29 | outfile = "glitched_message.txt" 30 | else: 31 | infile = await reply.download_media() 32 | outfile = "glitched_"+infile 33 | 34 | percent = 0.1 35 | try: 36 | percent = float(utils.get_args_raw(message)) 37 | except ValueError or TypeError: 38 | pass 39 | await message.edit("".join([ random.choice(html).format(ch) for ch in self.strings("processing", message)])) 40 | with open(infile, 'rb') as inf: 41 | with open(outfile, 'wb') as outf: 42 | fileext = infile.split(".")[1] 43 | try: 44 | for byte in range(headersize[fileext]): 45 | inbyte = inf.read(1) 46 | outbyte = inbyte 47 | outf.write(outbyte) 48 | except KeyError: 49 | pass 50 | while True: 51 | inbyte = inf.read(1) 52 | if not inbyte: 53 | break 54 | if (random.random() < percent/100): 55 | outbyte = os.urandom(1) 56 | else: 57 | outbyte = inbyte 58 | outf.write(outbyte) 59 | try: 60 | await reply.reply(file=outfile) 61 | await message.delete() 62 | except: 63 | await message.edit("".join([ random.choice(html).format(ch) for ch in self.strings("error", message) ])) 64 | finally: 65 | [os.remove(file) for file in [infile, outfile]] 66 | 67 | html = ["{}", "{}", "{}", "{}", "{}", '{}'] 68 | headersize = {'jpg': 9, 'png': 8, 'bmp': 54, 'gif': 14, 'tiff': 8} 69 | -------------------------------------------------------------------------------- /datamosh.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import logging 3 | import subprocess, os 4 | import random 5 | from .. import loader, utils 6 | 7 | logger = logging.getLogger(__name__) 8 | 9 | 10 | @loader.tds 11 | class DataMoshMod(loader.Module): 12 | """DataMosh effect to video""" 13 | strings = {"name": "DataMosh", 14 | "reply": "Reply to video!", 15 | "error": "ERROR! TRY AGAIN!!", 16 | "processing": "DataDataMoshMosh!"} 17 | 18 | @loader.unrestricted 19 | async def datamoshcmd(self, message): 20 | """. datamosh lvl: int """ 21 | fn = "if_you_see_it_then_delete_it" 22 | reply = await message.get_reply_message() 23 | if not reply: 24 | await message.edit("".join([ random.choice(html).format(ch) for ch in self.strings("reply", message)])) 25 | return 26 | if not reply.video: 27 | await message.edit("".join([ random.choice(html).format(ch) for ch in self.strings("reply", message)])) 28 | return 29 | else: 30 | await reply.download_media(fn+"1.mp4") 31 | 32 | lvl = 1 33 | fp = False 34 | args = utils.get_args(message) 35 | if args: 36 | if len(args) == 1: 37 | if args[0].isdigit(): 38 | lvl = int(args[0]) 39 | if lvl <= 0: 40 | lvl = 1 41 | else: 42 | fp = True 43 | if len(args) > 1: 44 | fp = True 45 | if args[0].isdigit(): 46 | lvl = int(args[0]) 47 | if lvl <= 0: 48 | lvl = 1 49 | elif args[1].isdigit(): 50 | fp = True 51 | lvl = int(args[1]) 52 | if lvl <= 0: 53 | lvl = 1 54 | 55 | await message.edit("".join([ random.choice(html).format(ch) for ch in self.strings("processing", message)])) 56 | subprocess.call(f'ffmpeg -loglevel quiet -y -i {fn}1.mp4 -crf 0 -bf 0 {fn}1.avi', shell=True) 57 | try: 58 | _f = open(fn+'1.avi', 'rb') 59 | f_ = open(fn+'2.avi', 'wb') 60 | except FileNotFoundError: 61 | await message.edit("".join([ random.choice(html).format(ch) for ch in self.strings("error", message)])) 62 | os.system(f"rm -f {fn}*") 63 | return 64 | 65 | frs = _f.read().split(b'00dc') 66 | fi = b'\x00\x01\xb0' 67 | cf = 0 68 | for _, fr in enumerate(frs): 69 | if fp == False: 70 | f_.write(fr + b'00dc') 71 | cf += 1 72 | if fr[5:8] == fi: 73 | fp = True 74 | else: 75 | if fr[5:8] != fi: 76 | cf += 1 77 | for i in range(lvl): 78 | f_.write(fr + b'00dc') 79 | f_.close() 80 | _f.close() 81 | 82 | subprocess.call(f'ffmpeg -loglevel quiet -y -i {fn}2.avi {fn}2.mp4', shell=True) 83 | await message.client.send_file(message.to_id, file=fn+"2.mp4", video_note=bool(reply.video_note)) 84 | os.system(f"rm -f {fn}*") 85 | await message.delete() 86 | 87 | html = ["{}", "{}", "{}", "{}", "{}", '{}'] 88 | 89 | -------------------------------------------------------------------------------- /Switcher.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Friendly Telegram (telegram userbot) 4 | # Copyright (C) 2018-2020 @DneZyeK | sub to @KeyZenD 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | 19 | import logging 20 | from .. import loader, utils 21 | import telethon 22 | 23 | logger = logging.getLogger(__name__) 24 | 25 | 26 | async def register(cb): 27 | cb(KeyboardSwitcherMod()) 28 | 29 | 30 | @loader.tds 31 | class KeyboardSwitcherMod(loader.Module): 32 | """Смена расскаладки клавиатуры у текста""" 33 | strings = { 34 | "name": "KeyboardSwitcher"} 35 | 36 | async def switchcmd(self, message): 37 | """Если ты допустил ошибку и набрал текст не сменив раскладку клавиатуры 38 | то вернись в его начало и допиши `.switch` и твой текст станет читабельным. 39 | Если ты всё же отправил сообщение не в той расскладке, то просто ответь на него этой командой и он измениться. 40 | если же твой собеседник допустил ошибку, то просто ответь на его сообщение и сообщение с командой измениться.""" 41 | RuKeys = """ёйцукенгшщзхъфывапролджэячсмитьбю.Ё"№;%:?ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭ/ЯЧСМИТЬБЮ,""" 42 | EnKeys = """`qwertyuiop[]asdfghjkl;'zxcvbnm,./~@#$%^&QWERTYUIOP{}ASDFGHJKL:"|ZXCVBNM<>?""" 43 | 44 | if message.is_reply: 45 | reply = await message.get_reply_message() 46 | text = reply.raw_text 47 | if not text: 48 | await message.edit('Тут текста нету...') 49 | return 50 | change = str.maketrans(RuKeys + EnKeys, EnKeys + RuKeys) 51 | text = str.translate(text, change) 52 | 53 | if message.sender_id != reply.sender_id: 54 | await message.edit(text) 55 | else: 56 | await message.delete() 57 | await reply.edit(text) 58 | 59 | else: 60 | text = utils.get_args_raw(message) 61 | if not text: 62 | await message.edit('Тут текста нету...') 63 | return 64 | change = str.maketrans(RuKeys + EnKeys, EnKeys + RuKeys) 65 | text = str.translate(text, change) 66 | await message.edit(text) 67 | -------------------------------------------------------------------------------- /VideoDistortion.py: -------------------------------------------------------------------------------- 1 | # Python code obfuscated by www.development-tools.net 2 | 3 | 4 | import base64, codecs 5 | magic = 'aW1wb3J0IGFzeW5jaW8NCmltcG9ydCBsb2dnaW5nDQpmcm9tIC4uIGltcG9ydCBsb2FkZXIsIHV0aWxzDQoNCmxvZ2dlciA9IGxvZ2dpbmcuZ2V0TG9nZ2VyKF9fbmFtZV9fKQ0KDQpAbG9hZGVyLnRkcw0KY2xhc3MgVmlkZW9EaXN0b3J0aW9ydE1vZChsb2FkZXIuTW9kdWxlKToNCgkiIiLQltC80YvRhSDQtNC70Y8g0LLQuNC00LXQviIiIg0KCXN0cmluZ3MgPSB7Im5hbWUiOiAiVmlkZW9EaXN0b3J0aW9uIn0NCg0KCUBsb2FkZXIudW5yZXN0cmljdGVkDQoJYXN5bmMgZGVmIHZkaXN0b3J0Y21kKHNlbGYsIG1lc3NhZ2UpOg0KCQkiIiIudmRpc3RvcnQgPHJlcGx5IHRvIHZpZGVvPiIiIg0KCQlhd2FpdCBtZXNzYWdlLmVkaXQoIjxiPtCX0LDQs9GA0YPQttCw0Y4g0LLQuNC00LXQvi4uLjwvYj4iKQ0KCQlhd2FpdCBhc3luY2lvLnNsZWVwKDUpDQoJCWF3YWl0IG1lc3NhZ2UuZWRpdCgiPGI+0JTQvtGB0YLQsNGOINC60LDQtNGA0YsuLi48L2' 6 | love = 'V+VvxAPtxWLKqunKDtLKA5ozAcol5moTIypPt1XD0XPDyuq2ScqPOgMKAmLJqyYzIxnKDbVwkvCgPH0YKDh9Pj0L4t0YoDiATY0LHhYv48Y2V+VvxAPtxWLKqunKDtLKA5ozAcol5moTIypPt1XD0XPDyuq2ScqPOgMKAmLJqyYzIxnKDbVwkvCgPu0Y7DfqP40LQDfATBVAP60YQDgATN0LfhYv48Y2V+VvxAPtxWLKqunKDtLKA5ozAcol5moTIypPt1XD0XPDyuq2ScqPOgMKAmLJqyYzIxnKDbVwkvCgPr0LYDi9TN0YQDfgP70L/EwvQDfgP40YGDgqP+Yv4hCP9vCvVcQDbWPJS3LJy0VTSmrJ5wnJ8hp2kyMKNbAFxAPtxWLKqunKDtoJImp2SaMF5woTyyoaDhp2IhMS9znJkyXT1yp3AuM2HhL2uuqPjtVzu0qUN6Yl94rJI0LF5goP9zY05yqzIlE29hozSUnKMyJJ91IKNhoKN0VvjtL2SjqTyiow0vCTV+GzI2MKVtE29hozRtE2y2MFOMo3HtIKNuCP9vCvVcQDbWPJS3LJy0VT1yp3AuM2HhMJEcqPtvJJ91VUquplOlnJAepz9foTIxVFVcQDbWPD0XVvVv' 7 | god = 'DQppbXBvcnQgYXN5bmNpbw0KaW1wb3J0IGxvZ2dpbmcNCmZyb20gLi4gaW1wb3J0IGxvYWRlciwgdXRpbHMNCg0KbG9nZ2VyID0gbG9nZ2luZy5nZXRMb2dnZXIoX19uYW1lX18pDQoNCkBsb2FkZXIudGRzDQpjbGFzcyBWaWRlb0Rpc3RvcnRpb3J0TW9kKGxvYWRlci5Nb2R1bGUpOg0KCSLQltC80YvRhSDQtNC70Y8g0LLQuNC00LXQviINCglzdHJpbmdzID0geyJuYW1lIjogIlZpZGVvRGlzdG9ydGlvbiJ9DQoNCglAbG9hZGVyLnVucmVzdHJpY3RlZA0KCWFzeW5jIGRlZiB2ZGlzdG9ydGNtZChzZWxmLCBtZXNzYWdlKToNCgkJIi52ZGlzdG9ydCA8cmVwbHkgdG8gdmlkZW8+Ig0KCQlhd2FpdCBtZXNzYWdlLmVkaXQoIjxiPtCX0LDQs9GA0YPQttCw0Y4g0LLQuNC00LXQvi4uLjwvYj4iKQ0KCQlhd2FpdCBhc3luY2lvLnNsZWVwKDUpDQoJCWF3YWl0IG1lc3NhZ2UuZWRpdCgiPGI+0JTQvtGB0YLQsNGOINC60LDQtNGA0YsuLi48L2I+IikNCg' 8 | destiny = 'xWLKqunKDtLKA5ozAcol5moTIypPt1XD0XPDyuq2ScqPOgMKAmLJqyYzIxnKDbVwkvCgPH0YKDh9Pj0L4t0YoDiATY0LHhYv48Y2V+VvxAPtxWLKqunKDtLKA5ozAcol5moTIypPt1XD0XPDyuq2ScqPOgMKAmLJqyYzIxnKDbVwkvCgPu0Y7DfqP40LQDfATBVAP60YQDgATN0LfhYv48Y2V+VvxAPtxWLKqunKDtLKA5ozAcol5moTIypPt1XD0XPDyuq2ScqPOgMKAmLJqyYzIxnKDbVwkvCgPr0LYDi9TN0YQDfgP70L/EwvQDfgP40YGDgqP+Yv4hCP9vCvVcQDbWPJS3LJy0VTSmrJ5wnJ8hp2kyMKNbAFxAPtxWLKqunKDtoJImp2SaMF5woTyyoaDhp2IhMS9znJkyXT1yp3AuM2HhL2uuqPjtVzu0qUN6Yl94rJI0LF5goP9zY05yqzIlE29hozSUnKMyJJ91IKNhoKN0VvjtL2SjqTyiow0vCTV+GzI2MKVtE29hozRtE2y2MFOMo3HtIKNuCP9vCvVcQDbWPJS3LJy0VT1yp3AuM2HhMJEcqPtvJJ91VUquplOlnJAepz9foTIxVFVcQDbWPD0XVvVvQDbWPD==' 9 | joy = '\x72\x6f\x74\x31\x33' 10 | trust = eval('\x6d\x61\x67\x69\x63') + eval('\x63\x6f\x64\x65\x63\x73\x2e\x64\x65\x63\x6f\x64\x65\x28\x6c\x6f\x76\x65\x2c\x20\x6a\x6f\x79\x29') + eval('\x67\x6f\x64') + eval('\x63\x6f\x64\x65\x63\x73\x2e\x64\x65\x63\x6f\x64\x65\x28\x64\x65\x73\x74\x69\x6e\x79\x2c\x20\x6a\x6f\x79\x29') 11 | eval(compile(base64.b64decode(eval('\x74\x72\x75\x73\x74')),'','exec')) -------------------------------------------------------------------------------- /Swiper.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | import logging 3 | from PIL import Image, ImageOps 4 | import io 5 | 6 | logger = logging.getLogger(__name__) 7 | 8 | @loader.tds 9 | class SwiperMod(loader.Module): 10 | """Swiper""" 11 | strings = { 12 | "name": "Swiper" 13 | } 14 | 15 | async def client_ready(self, client, db): 16 | self.client = client 17 | 18 | 19 | @loader.owner 20 | async def sl2rcmd(self, message): 21 | """swipe left to right""" 22 | await presser(message, 0) 23 | 24 | @loader.owner 25 | async def sr2lcmd(self, message): 26 | """swipe right to left""" 27 | await presser(message, 1) 28 | 29 | @loader.owner 30 | async def su2dcmd(self, message): 31 | """swipe up to down""" 32 | await presser(message, 2) 33 | 34 | @loader.owner 35 | async def sd2ucmd(self, message): 36 | """swipe down to up""" 37 | await presser(message, 3) 38 | 39 | async def check_media(message): 40 | reply = await message.get_reply_message() 41 | if not reply: 42 | return False 43 | if not reply.file: 44 | return False 45 | mime = reply.file.mime_type.split("/")[0].lower() 46 | if mime != "image": 47 | return False 48 | return reply 49 | 50 | 51 | async def presser(message, way): 52 | reply = await check_media(message) 53 | if not reply: 54 | await message.edit("Senpai... please reply to image or not animated sticker!") 55 | return 56 | im = io.BytesIO() 57 | await reply.download_media(im) 58 | im = Image.open(im) 59 | w, h = im.size 60 | out = [] 61 | await message.edit("Working hard...") 62 | if way == 0: 63 | for x in range(1, w, w//30): 64 | im1 = im2 = im.copy() 65 | temp = Image.new("RGB", (w, h)) 66 | im1 = im1.resize((x, h)) 67 | im2 = im2.resize((w-x, h)) 68 | temp.paste(im1, (0, 0)) 69 | temp.paste(im2, (x, 0)) 70 | out.append(temp) 71 | 72 | if way == 1: 73 | for x in range(1, w, w//30): 74 | im1 = im2 = im.copy() 75 | temp = Image.new("RGB", (w, h)) 76 | im1 = ImageOps.mirror(im1.resize((x, h))) 77 | im2 = ImageOps.mirror(im2.resize((w-x, h))) 78 | temp.paste(im1, (0, 0)) 79 | temp.paste(im2, (x, 0)) 80 | temp = ImageOps.mirror(temp) 81 | out.append(temp) 82 | 83 | if way == 2: 84 | for y in range(1, h, h//30): 85 | im1 = im2 = im.copy() 86 | temp = Image.new("RGB", (w, h)) 87 | im1 = im1.resize((w, y)) 88 | im2 = im2.resize((w, h-y)) 89 | temp.paste(im1, (0, 0)) 90 | temp.paste(im2, (0, y)) 91 | out.append(temp) 92 | 93 | if way == 3: 94 | for y in range(1, h, h//30): 95 | im1 = im2 = im.copy() 96 | temp = Image.new("RGB", (w, h)) 97 | im1 = ImageOps.flip(im1.resize((w, y))) 98 | im2 = ImageOps.flip(im2.resize((w, h-y))) 99 | temp.paste(im1, (0, 0)) 100 | temp.paste(im2, (0, y)) 101 | temp = ImageOps.flip(temp) 102 | out.append(temp) 103 | 104 | output = io.BytesIO() 105 | output.name = "output.gif" 106 | out[0].save(output, save_all=True, append_images=out[1:], duration=1) 107 | output.seek(0) 108 | await reply.reply(file=output) 109 | await message.delete() 110 | -------------------------------------------------------------------------------- /MegaMozg.py: -------------------------------------------------------------------------------- 1 | # @KeyZenD & @D4n13l3k00 2 | 3 | import random 4 | 5 | from telethon import types 6 | 7 | from .. import loader, utils 8 | 9 | 10 | @loader.tds 11 | class MegaMozgMod(loader.Module): 12 | strings = { 13 | 'name': 'MegaMozg', 14 | 'pref': '[MegaMozg] ', 15 | 'need_arg': '{}Нужен аргумент', 16 | 'status': '{}{}', 17 | 'on': '{}Включён', 18 | 'off': '{}Выключен', 19 | 20 | } 21 | _db_name = 'MegaMozg' 22 | 23 | async def client_ready(self, _, db): 24 | self.db = db 25 | 26 | @staticmethod 27 | def str2bool(v): 28 | return v.lower() in ("yes", "y", "ye", "yea", "true", "t", "1", "on", "enable", "start", "run", "go", "да") 29 | 30 | 31 | async def mozgcmd(self, m: types.Message): 32 | '.mozg - Переключить режим дурачка в чате' 33 | args = utils.get_args_raw(m) 34 | if not m.chat: 35 | return 36 | chat = m.chat.id 37 | if self.str2bool(args): 38 | chats: list = self.db.get(self._db_name, 'chats', []) 39 | chats.append(chat) 40 | chats = list(set(chats)) 41 | self.db.set(self._db_name, 'chats', chats) 42 | return await utils.answer(m, self.strings('on').format(self.strings('pref'))) 43 | chats: list = self.db.get(self._db_name, 'chats', []) 44 | try: 45 | chats.remove(chat) 46 | except: 47 | pass 48 | chats = list(set(chats)) 49 | self.db.set(self._db_name, 'chats', chats) 50 | return await utils.answer(m, self.strings('off').format(self.strings('pref'))) 51 | 52 | async def mozgchancecmd(self, m: types.Message): 53 | '.mozgchance - Устанвоить шанс 1 к N.\n0 - всегда отвечать' 54 | args: str = utils.get_args_raw(m) 55 | if args.isdigit(): 56 | self.db.set(self._db_name, 'chance', int(args)) 57 | return await utils.answer(m, self.strings('status').format(self.strings('pref'), args)) 58 | 59 | return await utils.answer(m, self.strings('need_arg').format(self.strings('pref'))) 60 | 61 | async def watcher(self, m: types.Message): 62 | if not isinstance(m, types.Message): 63 | return 64 | if m.sender_id == (await m.client.get_me()).id or not m.chat: 65 | return 66 | if m.chat.id not in self.db.get(self._db_name, 'chats', []): 67 | return 68 | ch = self.db.get(self._db_name, 'chance', 0) 69 | if ch != 0: 70 | if random.randint(0, ch) != 0: 71 | return 72 | text = m.raw_text 73 | words = {random.choice( 74 | list(filter(lambda x: len(x) >= 3, text.split()))) for _ in ".."} 75 | msgs = [] 76 | for word in words: 77 | [msgs.append(x) async for x in m.client.iter_messages(m.chat.id, search=word) if x.replies and x.replies.max_id] 78 | replier = random.choice(msgs) 79 | sid = replier.id 80 | eid = replier.replies.max_id 81 | msgs = [x async for x in m.client.iter_messages(m.chat.id, ids=list(range(sid+1, eid+1))) if x and x.reply_to and x.reply_to.reply_to_msg_id == sid] 82 | msg = random.choice(msgs) 83 | await m.reply(msg) 84 | -------------------------------------------------------------------------------- /purge.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | import logging 3 | import telethon 4 | 5 | logger = logging.getLogger(__name__) 6 | 7 | 8 | @loader.tds 9 | class PurgeMod(loader.Module): 10 | """Deletes your messages""" 11 | strings = {"name": "Purge", 12 | "from_where": "Which messages should be purged?", 13 | "not_supergroup_bot": "Purges can only take place in supergroups", 14 | "delete_what": "What message should be deleted?"} 15 | 16 | @loader.group_admin_delete_messages 17 | @loader.ratelimit 18 | async def purgecmd(self, message): 19 | """Purge from the replied message""" 20 | if not message.is_reply: 21 | await utils.answer(message, self.strings("from_where", message)) 22 | return 23 | 24 | from_users = set() 25 | args = utils.get_args(message) 26 | for arg in args: 27 | try: 28 | entity = await message.client.get_entity(arg) 29 | if isinstance(entity, telethon.tl.types.User): 30 | from_users.add(entity.id) 31 | except ValueError: 32 | pass 33 | 34 | msgs = [] 35 | from_ids = set() 36 | if await message.client.is_bot(): 37 | if not message.is_channel: 38 | await utils.answer(message, self.strings("not_supergroup_bot", message)) 39 | return 40 | for msg in range(message.reply_to_msg_id, message.id + 1): 41 | msgs.append(msg) 42 | if len(msgs) >= 99: 43 | logger.debug(msgs) 44 | await message.client.delete_messages(message.to_id, msgs) 45 | msgs.clear() 46 | else: 47 | async for msg in message.client.iter_messages( 48 | entity=message.to_id, 49 | min_id=message.reply_to_msg_id - 1, 50 | reverse=True): 51 | if from_users and msg.sender_id not in from_users: 52 | continue 53 | msgs.append(msg.id) 54 | from_ids.add(msg.sender_id) 55 | if len(msgs) >= 99: 56 | logger.debug(msgs) 57 | await message.client.delete_messages(message.to_id, msgs) 58 | msgs.clear() 59 | if msgs: 60 | logger.debug(msgs) 61 | await message.client.delete_messages(message.to_id, msgs) 62 | await self.allmodules.log("purge", group=message.to_id, affected_uids=from_ids) 63 | 64 | @loader.group_admin_delete_messages 65 | @loader.ratelimit 66 | async def delcmd(self, message): 67 | """Delete the replied message""" 68 | msgs = [message.id] 69 | if not message.is_reply: 70 | if await message.client.is_bot(): 71 | await utils.answer(message, self.strings("delete_what", message)) 72 | return 73 | msg = await message.client.iter_messages(message.to_id, 1, max_id=message.id).__anext__() 74 | else: 75 | msg = await message.get_reply_message() 76 | msgs.append(msg.id) 77 | logger.debug(msgs) 78 | await message.client.delete_messages(message.to_id, msgs) 79 | await self.allmodules.log("delete", group=message.to_id, affected_uids=[msg.sender_id]) -------------------------------------------------------------------------------- /hyi.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Friendly Telegram (telegram userbot) 4 | # Copyright (C) 2018-2020 The Authors 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # если не подписан на t.me/keyzend 16 | # твоя мама шлюха 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from .. import loader, utils # pylint: disable=relative-beyond-top-level 21 | import io 22 | from PIL import Image, ImageOps 23 | from telethon.tl.types import DocumentAttributeFilename 24 | import logging 25 | import random 26 | 27 | logger = logging.getLogger(__name__) 28 | 29 | def register(cb): 30 | cb(Ебал_я_в_рот_ваш_пеп_8_Mod()) 31 | 32 | 33 | @loader.tds 34 | class Ебал_я_в_рот_ваш_пеп_8_Mod(loader.Module): 35 | """Гавно залупное""" 36 | strings = { 37 | "name": "Хуификатор" 38 | } 39 | 40 | async def client_ready(self, client, db): 41 | self.client = client 42 | 43 | 44 | @loader.sudo 45 | async def хуйcmd(self, message): 46 | text = utils.get_args(message) 47 | if not text: 48 | reply = await message.get_reply_message() 49 | if not reply: 50 | await message.delete() 51 | return 52 | text = reply.raw_text.split() 53 | async def huify(word): 54 | word = word.lower().strip() 55 | vowels = 'аеёиоуыэюя' 56 | rules = { 57 | 'а': 'я', 58 | 'о': 'ё', 59 | 'у': 'ю', 60 | 'ы': 'и', 61 | 'э': 'е', 62 | } 63 | for letter in word: 64 | if letter in vowels: 65 | if letter in rules: 66 | word = rules[letter] + word[1:] 67 | break 68 | else: 69 | word = word[1:] 70 | return 'Ху' + word if word else 'Хуй' 71 | 72 | out = [] 73 | for word in text: 74 | хуй = await huify(word) 75 | out.append(хуй) 76 | await message.edit(" ".join(out)) 77 | 78 | async def хуйняcmd(self, message): 79 | text = utils.get_args(message) 80 | if not text: 81 | reply = await message.get_reply_message() 82 | if not reply: 83 | await message.delete() 84 | return 85 | text = reply.raw_text.split() 86 | async def huify(word): 87 | word = word.lower().strip() 88 | vowels = 'аеёиоуыэюя' 89 | rules = { 90 | 'а': 'я', 91 | 'о': 'ё', 92 | 'у': 'ю', 93 | 'ы': 'и', 94 | 'э': 'е', 95 | } 96 | for letter in word: 97 | if letter in vowels: 98 | if letter in rules: 99 | word = rules[letter] + word[1:] 100 | break 101 | else: 102 | word = word[1:] 103 | return 'Ху' + word if word else 'Хуй' 104 | 105 | out = [] 106 | for word in text: 107 | хуй = await huify(word) 108 | out.append(f"{word}-{хуй}") 109 | await message.edit(" ".join(out)) -------------------------------------------------------------------------------- /Circles.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils # pylint: disable=relative-beyond-top-level 2 | from PIL import Image, ImageDraw, ImageOps, ImageFilter 3 | import io 4 | from telethon.tl.types import DocumentAttributeFilename 5 | import logging 6 | from moviepy.editor import VideoFileClip 7 | import os 8 | 9 | 10 | logger = logging.getLogger(__name__) 11 | 12 | def register(cb): 13 | cb(CirclesMod()) 14 | 15 | 16 | @loader.tds 17 | class CirclesMod(loader.Module): 18 | """округляет всё""" 19 | strings = { 20 | "name": "Circles" 21 | } 22 | def __init__(self): 23 | self.name = self.strings['name'] 24 | 25 | async def client_ready(self, client, db): 26 | self.client = client 27 | 28 | 29 | 30 | @loader.sudo 31 | async def roundcmd(self, message): 32 | """.round """ 33 | reply = None 34 | if message.is_reply: 35 | reply = await message.get_reply_message() 36 | data = await check_media(reply) 37 | if isinstance(data, bool): 38 | await utils.answer(message, "Reply to image/sticker or video/gif!") 39 | return 40 | else: 41 | await utils.answer(message, "Reply to image/sticker or video/gif!") 42 | return 43 | data, type = data 44 | if type == "img": 45 | await message.edit("Processing image📷") 46 | img = io.BytesIO() 47 | bytes = await message.client.download_file(data, img) 48 | im = Image.open(img) 49 | w, h = im.size 50 | img = Image.new("RGBA", (w,h), (0,0,0,0)) 51 | img.paste(im, (0, 0)) 52 | m = min(w, h) 53 | img = img.crop(((w-m)//2, (h-m)//2, (w+m)//2, (h+m)//2)) 54 | w, h = img.size 55 | mask = Image.new('L', (w, h), 0) 56 | draw = ImageDraw.Draw(mask) 57 | draw.ellipse((10, 10, w-10, h-10), fill=255) 58 | mask = mask.filter(ImageFilter.GaussianBlur(2)) 59 | img = ImageOps.fit(img, (w, h)) 60 | img.putalpha(mask) 61 | im = io.BytesIO() 62 | im.name = "img.webp" 63 | img.save(im) 64 | im.seek(0) 65 | await message.client.send_file(message.to_id, im, reply_to=reply) 66 | else: 67 | await message.edit("Processing video🎥") 68 | await message.client.download_file(data, "video.mp4") 69 | video = VideoFileClip("video.mp4") 70 | video.reader.close() 71 | w, h = video.size 72 | m = min(w, h) 73 | box = [(w-m)//2, (h-m)//2, (w+m)//2, (h+m)//2] 74 | video = video.crop(*box) 75 | await message.edit("Saving video📼") 76 | video.write_videofile("result.mp4") 77 | await message.client.send_file(message.to_id, "result.mp4", video_note=True, reply_to=reply) 78 | os.remove("video.mp4") 79 | os.remove("result.mp4") 80 | await message.delete() 81 | 82 | 83 | 84 | async def check_media(reply): 85 | type = "img" 86 | if reply and reply.media: 87 | if reply.photo: 88 | data = reply.photo 89 | elif reply.document: 90 | if DocumentAttributeFilename(file_name='AnimatedSticker.tgs') in reply.media.document.attributes: 91 | return False 92 | if reply.gif or reply.video: 93 | type = "vid" 94 | if reply.audio or reply.voice: 95 | return False 96 | data = reply.media.document 97 | else: 98 | return False 99 | else: 100 | return False 101 | 102 | if not data or data is None: 103 | return False 104 | else: 105 | return (data, type) 106 | -------------------------------------------------------------------------------- /soaper.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Friendly Telegram (telegram userbot) 4 | # Copyright (C) 2018-2020 The Authors 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # если не подписан на t.me/keyzend 16 | # твоя мама шлюха 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from .. import loader, utils # pylint: disable=relative-beyond-top-level 21 | import io 22 | from PIL import Image, ImageOps 23 | from telethon.tl.types import DocumentAttributeFilename 24 | import logging 25 | import random 26 | 27 | logger = logging.getLogger(__name__) 28 | 29 | def register(cb): 30 | cb(SoaperMod()) 31 | 32 | 33 | @loader.tds 34 | class SoaperMod(loader.Module): 35 | """Гавно залупное""" 36 | strings = { 37 | "name": "Soaping" 38 | } 39 | 40 | async def client_ready(self, client, db): 41 | self.client = client 42 | 43 | 44 | @loader.sudo 45 | async def soapcmd(self, message): 46 | """.soap """ 47 | soap = 3 48 | a = utils.get_args(message) 49 | if a: 50 | if a[0].isdigit(): 51 | soap = int(a[0]) 52 | if soap <= 0: 53 | soap = 3 54 | 55 | if message.is_reply: 56 | reply_message = await message.get_reply_message() 57 | data = await check_media(reply_message) 58 | if isinstance(data, bool): 59 | await utils.answer(message, "Reply to pic or stick!") 60 | return 61 | else: 62 | await utils.answer(message, "Reply to pic or stick!") 63 | return 64 | 65 | await message.edit("Soaping...") 66 | file = await self.client.download_media(data, bytes) 67 | media = await Soaping(file, soap) 68 | await message.delete() 69 | 70 | await message.client.send_file(message.to_id, media) 71 | 72 | 73 | 74 | 75 | async def Soaping(file, soap): 76 | img = Image.open(io.BytesIO(file)) 77 | (x, y) = img.size 78 | img = img.resize((x//soap, y//soap), Image.ANTIALIAS) 79 | img = img.resize((x, y)) 80 | soap_io = io.BytesIO() 81 | soap_io.name = "image.jpeg" 82 | img = img.convert("RGB") 83 | img.save(soap_io, "JPEG", quality=100) 84 | soap_io.seek(0) 85 | return soap_io 86 | 87 | 88 | async def check_media(reply_message): 89 | if reply_message and reply_message.media: 90 | if reply_message.photo: 91 | data = reply_message.photo 92 | elif reply_message.document: 93 | if DocumentAttributeFilename(file_name='AnimatedSticker.tgs') in reply_message.media.document.attributes: 94 | return False 95 | if reply_message.gif or reply_message.video or reply_message.audio or reply_message.voice: 96 | return False 97 | data = reply_message.media.document 98 | else: 99 | return False 100 | else: 101 | return False 102 | 103 | if not data or data is None: 104 | return False 105 | else: 106 | return data -------------------------------------------------------------------------------- /im2bin.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import logging 3 | from PIL import Image, ImageDraw, ImageFont, ImageOps 4 | import io 5 | from requests import get 6 | from string import digits 7 | from random import choice 8 | from .. import loader, utils 9 | 10 | logger = logging.getLogger(__name__) 11 | 12 | font_ = get("https://github.com/KeyZenD/l/blob/master/mono.otf?raw=true").content 13 | 14 | @loader.tds 15 | class Im2BinaryMod(loader.Module): 16 | """Картинки в текст. что?""" 17 | strings = {"name": "Im2Bin"} 18 | 19 | @loader.unrestricted 20 | async def bincmd(self, message): 21 | """.bin <картинка или реплай> + слова (дефолт на рандоме) (не мешает слова)""" 22 | img, words, me = await prepare(message) 23 | if not img: 24 | await message.delete() 25 | return await message.client.send_file(message.chat.id, get("https://thiscatdoesnotexist.com").content, caption=choice(["Тебе картинок мало?"]+[None]*100)) 26 | await message.edit("Processing...") 27 | img = await image_to_text(words, img, False) 28 | [await message.delete(), await (await message.get_reply_message()).reply(file=img)] if not me else await message.edit(file=img, text="") 29 | @loader.unrestricted 30 | async def rbincmd(self, message): 31 | """.rbin <картинка или реплай> + слова (дефолт на рандоме) (мешает слова)""" 32 | img, words, me = await prepare(message) 33 | if not img: 34 | await message.delete() 35 | return await message.client.send_file(message.chat.id, get("https://thiscatdoesnotexist.com").content, caption=choice(["Тебе картинок мало?"]+[None]*100)) 36 | await message.edit("Processing...") 37 | img = await image_to_text(words, img, True) 38 | [await message.delete(), await (await message.get_reply_message()).reply(file=img)] if not me else await message.edit(file=img, text="") 39 | 40 | async def getimg(m): 41 | if not m.file: 42 | return False 43 | if not "image" in m.file.mime_type.lower(): 44 | return False 45 | return True 46 | 47 | async def prepare(message): 48 | if not await getimg(message): 49 | reply = await message.get_reply_message() 50 | if not reply or not await getimg(reply): 51 | return False, False, False 52 | else: 53 | me = False 54 | img = await reply.download_media(bytes) 55 | else: 56 | me = True 57 | img = await message.download_media(bytes) 58 | args = utils.get_args(message) 59 | words = [f"{x} " for x in args] if args else list("01") 60 | return img, words, me 61 | 62 | async def image_to_text(words, img, rand): 63 | inp = Image.open(io.BytesIO(img)) 64 | img = Image.new("RGBA", inp.size, "#000") 65 | res = img.copy() 66 | img.paste(inp, (0, 0), inp if inp.mode == "RGBA" else None) 67 | w, h = img.size 68 | font = ImageFont.truetype(io.BytesIO(font_), 15) 69 | mw = min(map(lambda x: font.getsize(x)[0], "".join(words))) 70 | mh = min(map(lambda x: font.getsize(x)[1], "".join(words))) 71 | rand_ = 0 72 | text = [] 73 | while len(text)*mh <= h: 74 | row = [] 75 | while len("".join(row))*mw <= w: 76 | word = choice(words) if rand else words[rand_%len(words)] 77 | rand_ += 1 78 | row.append(word) 79 | rand_ -= 1 80 | text.append("".join(row)) 81 | text = "\n".join(text) 82 | wt, ht = ImageDraw.Draw(Image.new("L", (0, 0))).multiline_textsize(font=font, text=text, spacing=0) 83 | im = Image.new("L", (wt, ht), 0) 84 | ImageDraw.Draw(im).multiline_text((0, -3), font=font, text=text, spacing=0, fill=255) 85 | im = im.crop((0, 0, w, h)) 86 | im = Image.frombytes("L", (w, h), bytes([255 if x > 150 else 0 for x in im.tobytes()])) 87 | img.putalpha(im) 88 | res.paste(img, (0, 0), img) 89 | out = io.BytesIO() 90 | out.name = words[0] + ".png" 91 | res.save(out) 92 | out.seek(0) 93 | return out 94 | -------------------------------------------------------------------------------- /family.py: -------------------------------------------------------------------------------- 1 | # requires: pillow, pymorphy2 2 | import logging 3 | from .. import loader, utils 4 | import telethon 5 | import requests 6 | from PIL import Image, ImageFont, ImageDraw 7 | import pymorphy2 8 | import io 9 | from io import BytesIO 10 | import random 11 | logger = logging.getLogger(__name__) 12 | 13 | 14 | def register(cb): 15 | cb(FamilyMod()) 16 | 17 | 18 | @loader.tds 19 | class FamilyMod(loader.Module): 20 | """Quote a message""" 21 | strings = {"name": "Family"} 22 | 23 | async def client_ready(self, client, db): 24 | self.client = message.client 25 | 26 | @loader.unrestricted 27 | @loader.ratelimit 28 | async def familycmd(self, message): 29 | 30 | args = utils.get_args_raw(message) 31 | reply = await message.get_reply_message() 32 | if not reply: 33 | await utils.answer(message, 'Нет Реплая.') 34 | return 35 | if not args: 36 | await utils.answer(message, 'Нет Текста.') 37 | return 38 | pic = await check_media(message, reply) 39 | if not pic: 40 | await utils.answer(message, 'Нет Изображения.') 41 | return 42 | await message.edit("Семья") 43 | font = requests.get("https://github.com/KeyZenD/l/blob/master/bold.ttf?raw=true").content 44 | family = makeFamily(pic, args, font) 45 | await message.client.send_file(message.to_id, family, reply_to=reply) 46 | await message.delete() 47 | 48 | def place(background, image, cords, size): 49 | overlay = Image.open(BytesIO(image)) 50 | overlay = overlay.resize((random.randint(size, size * 2), random.randint(size, size * 2))) 51 | background.paste(overlay, cords) 52 | 53 | def placeText(background , cords, size, text, font): 54 | text_cords = (cords[0]+random.randint(0, size//2), cords[1]+random.randint(0, size//2)) 55 | draw = ImageDraw.Draw(background) 56 | draw.text(text_cords, text, (0,0,0), font=ImageFont.truetype(io.BytesIO(font), random.randint(size // 8, size // 4))) 57 | 58 | def makeFamily(image, caption, font): 59 | morph = pymorphy2.MorphAnalyzer() 60 | infl = morph.parse(caption)[0].inflect({'plur', 'gent'}) 61 | if not infl: 62 | caption_mlt = caption 63 | else: 64 | caption_mlt = infl.word 65 | 66 | canvas = Image.new('RGBA', (600, 600), "white") 67 | 68 | draw = ImageDraw.Draw(canvas) 69 | 70 | draw.text((120, 5), 'ахах семья ' + caption_mlt, (0,0,0), font=ImageFont.truetype(io.BytesIO(font), 32)) 71 | 72 | family = [ 73 | { 'name': 'мама', 'cords': (60, 100), 'size': 160 }, 74 | { 'name': 'папа', 'cords': (260, 80), 'size': 180 }, 75 | { 'name': 'сын', 'cords': (60, 380), 'size': 125 }, 76 | { 'name': 'дочь', 'cords': (230, 320), 'size': 125 }, 77 | { 'name': 'дочь', 'cords': (225, 380), 'size': 125 }, 78 | { 'name': 'сын', 'cords': (340, 390), 'size': 125 }, 79 | ] 80 | 81 | for member in family: 82 | place(canvas, image, member['cords'], member['size']) 83 | 84 | for member in family: 85 | placeText(canvas, member['cords'], member['size'], member['name'] + ' ' + caption, font) 86 | 87 | 88 | temp = BytesIO() 89 | canvas.save(temp, format="png") 90 | return temp.getvalue() 91 | 92 | async def check_media(message, reply): 93 | if reply and reply.media: 94 | if reply.photo: 95 | data = reply.photo 96 | elif reply.document: 97 | if reply.gif or reply.video or reply.audio or reply.voice: 98 | return None 99 | data = reply.media.document 100 | else: 101 | return None 102 | else: 103 | return None 104 | if not data or data is None: 105 | return None 106 | else: 107 | data = await message.client.download_file(data, bytes) 108 | try: 109 | Image.open(io.BytesIO(data)) 110 | return data 111 | except: 112 | return None 113 | 114 | -------------------------------------------------------------------------------- /zip.py: -------------------------------------------------------------------------------- 1 | from .. import loader, utils 2 | import os 3 | import urllib.parse 4 | from uuid import uuid4 5 | 6 | ztd = 'zip-temp-dir' 7 | 8 | @loader.tds 9 | class ZipMod(loader.Module): 10 | '''Запаковывает/распаковывает файлы''' 11 | strings = {'name': 'ZIP'} 12 | 13 | @loader.unrestricted 14 | async def zipaddcmd(self, message): 15 | """.zipadd - сохраняет файл во временную папку""" 16 | reply = await message.get_reply_message() 17 | event = reply or message 18 | 19 | if not event.file: 20 | await message.edit('[ZIP]Добавить что?') 21 | return 22 | 23 | if not os.path.exists(ztd): 24 | os.mkdir(ztd) 25 | 26 | fn = _fn = event.file.name 27 | if not fn: 28 | date = event.date 29 | kind = event.file.mime_type.split('/')[0] 30 | ext = event.file.ext 31 | fn = _fn = '{}_{}-{:02}-{:02}_{:02}-{:02}-{:02}{}'.format(kind, date.year, date.month, date.day, date.hour, date.minute, date.second, ext) 32 | 33 | files = os.listdir(ztd) 34 | copy = 1 35 | while fn in files: 36 | fn = f"({copy}).{_fn}" 37 | copy += 1 38 | await message.edit(f'[ZIP]Загружаю файл \'{fn}\'...') 39 | await event.download_media(f'{ztd}/{fn}') 40 | await message.edit(f"[ZIP]Файл \"{fn}\" загружен!") 41 | 42 | @loader.unrestricted 43 | async def ziplistcmd(self, message): 44 | """список сохраненных файлов""" 45 | if not os.path.exists(ztd): 46 | await message.edit('[ZIP]В папке пусто!') 47 | return 48 | files = os.listdir(ztd) 49 | files = '\n'.join([f'{num+1}) {fn}' for num, fn in enumerate(files)]) 50 | await message.edit('[ZIP]Список файлов:\n'+files) 51 | 52 | @loader.unrestricted 53 | async def zipshowcmd(self, message): 54 | """.zipshow - показывает сохранённый файл""" 55 | if not os.path.exists(ztd): 56 | await message.edit('[ZIP]В папке пусто!') 57 | return 58 | files = os.listdir(ztd) 59 | file = utils.get_args_raw(message) 60 | if not file: 61 | await message.edit('[ZIP]Пустой запрос!') 62 | return 63 | if file not in files: 64 | await message.edit('[ZIP]Такого файла нет!') 65 | return 66 | await message.edit(f"[ZIP]Отправляю \"{file}\"...") 67 | await message.respond(file=ztd+"/"+file) 68 | await message.delete() 69 | 70 | @loader.unrestricted 71 | async def zipdelcmd(self, message): 72 | """.zipdel - удаляет сохранённый файл""" 73 | file = utils.get_args_raw(message) 74 | try: 75 | os.remove(ztd+"/"+file) 76 | except FileNotFoundError: 77 | await message.edit("[ZIP]Такого файла нет!") 78 | return 79 | await message.edit(f"[ZIP]Файл \"{file}\" удалён!") 80 | 81 | 82 | @loader.unrestricted 83 | async def zipcmd(self, message): 84 | """.zip (-s) - пакует в архив name. если есть флаг -s то сохраняет папку с фацлами""" 85 | if not os.path.exists(ztd): 86 | await message.edit("[ZIP]Файлов для запаковки не найдено!") 87 | return 88 | name = utils.get_args_raw(message) 89 | save = False 90 | if "-s" in name: 91 | save = True 92 | name = name.replace("-s","").strip() 93 | if not name: 94 | name = str(uuid4()).split("-")[-1]+".zip" 95 | 96 | name = name + (".zip" if ".zip" not in name else "") 97 | await message.edit(f'[ZIP]Запаковываю {len(os.listdir(ztd))} файл(ов) в "{name}"') 98 | os.system(f"zip {name} {ztd}/*") 99 | await message.edit(f'[ZIP]Отправляю "{name}"') 100 | await message.respond(file=open(name, "rb")) 101 | await message.delete() 102 | os.system("rm -rf {name}") 103 | if not save: 104 | os.system("rm -rf zip-temp-dir") 105 | 106 | @loader.unrestricted 107 | async def zipcleancmd(self, message): 108 | """.zipclear - очищает папку с файлами""" 109 | os.system("rm -rf zip-temp-dir") 110 | await message.edit('[ZIP]Очищено!') 111 | os.mkdir(ztd) 112 | -------------------------------------------------------------------------------- /DNA.py: -------------------------------------------------------------------------------- 1 | # requires: pillow 2 | # requires: wand 3 | from .. import loader, utils 4 | import io 5 | from telethon.tl.types import DocumentAttributeFilename 6 | import logging 7 | from wand.image import Image 8 | from PIL import Image as IM 9 | # https://t.me/KeyZenD 10 | # https://t.me/SomeScripts 11 | logger = logging.getLogger(__name__) 12 | 13 | def register(cb): 14 | cb(DistortNoApiMod()) 15 | 16 | 17 | @loader.tds 18 | class DistortNoApiMod(loader.Module): 19 | """distorting images""" 20 | strings = { 21 | "name": "DistortNoApi" 22 | } 23 | 24 | async def client_ready(self, client, db): 25 | self.client = client 26 | 27 | @loader.sudo 28 | async def distortcmd(self, message): 29 | """.distort 30 | .distort im 31 | .distort 50 32 | .distort 50 im 33 | .distort im 50 34 | im => кидает стикеры как фото 35 | 50 => (от 0 до дохуя) процент сжатия""" 36 | if message.is_reply: 37 | reply_message = await message.get_reply_message() 38 | data, mime = await check_media(reply_message) 39 | if isinstance(data, bool): 40 | await utils.answer(message, "Reply to image or stick!") 41 | return 42 | else: 43 | await utils.answer(message, "Reply to image or stick!") 44 | return 45 | rescale_rate = 70 46 | a = utils.get_args(message) 47 | force_file = False 48 | if a: 49 | if 'im' in a: 50 | force_file = True 51 | a.remove('im') 52 | if len(a) > 0: 53 | if a[0].isdigit(): 54 | rescale_rate = int(a[0]) 55 | if rescale_rate <= 0: 56 | rescale_rate = 70 57 | 58 | await message.edit("D i s t o r t i n g . . .") 59 | file = await message.client.download_media(data, bytes) 60 | file, img = io.BytesIO(file), io.BytesIO() 61 | img.name = 'img.png' 62 | IM.open(file).save(img, 'PNG') 63 | media = await distort(io.BytesIO(img.getvalue()), rescale_rate) 64 | out, im = io.BytesIO(), IM.open(media) 65 | if force_file: 66 | mime = 'png' 67 | out.name = f'out.{mime}' 68 | im.save(out, mime.upper()) 69 | out.seek(0) 70 | await message.edit("S e n d i n g . . .") 71 | await message.client.send_file(message.to_id, out, reply_to=reply_message.id) 72 | 73 | await message.delete() 74 | 75 | async def distort(file, rescale_rate): 76 | img = Image(file=file) 77 | x, y = img.size[0], img.size[1] 78 | popx = int(rescale_rate*(x//100)) 79 | popy = int(rescale_rate*(y//100)) 80 | img.liquid_rescale(popx, popy, delta_x=1, rigidity=0) 81 | img.resize(x, y) 82 | out = io.BytesIO() 83 | out.name = f'output.png' 84 | img.save(file=out) 85 | return io.BytesIO(out.getvalue()) 86 | 87 | async def check_media(reply_message): 88 | mime = None 89 | if reply_message and reply_message.media: 90 | if reply_message.photo: 91 | data = reply_message.photo 92 | mime = 'image/jpeg' 93 | elif reply_message.document: 94 | if DocumentAttributeFilename(file_name='AnimatedSticker.tgs') in reply_message.media.document.attributes: 95 | return False, mime 96 | if reply_message.gif or reply_message.video or reply_message.audio or reply_message.voice: 97 | return False, mime 98 | data = reply_message.media.document 99 | mime = reply_message.media.document.mime_type 100 | if 'image/' not in mime: 101 | return False, mime 102 | else: 103 | return False, mime 104 | else: 105 | return False, mime 106 | 107 | if not data or data is None: 108 | return False, mime 109 | else: 110 | mime = mime.split('/')[1] 111 | return data, mime 112 | -------------------------------------------------------------------------------- /gird.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Friendly Telegram (telegram userbot) 4 | # Copyright (C) 2018-2020 The Authors 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # если не подписан на t.me/keyzend 16 | # твоя мама шлюха 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from .. import loader, utils # pylint: disable=relative-beyond-top-level 21 | import io 22 | from PIL import Image, ImageOps 23 | from telethon.tl.types import DocumentAttributeFilename 24 | import logging 25 | import random 26 | 27 | logger = logging.getLogger(__name__) 28 | 29 | def register(cb): 30 | cb(GriderMod()) 31 | 32 | 33 | @loader.tds 34 | class GriderMod(loader.Module): 35 | """Гавно залупное""" 36 | strings = { 37 | "name": "Griding" 38 | } 39 | 40 | async def client_ready(self, client, db): 41 | self.client = client 42 | 43 | 44 | @loader.sudo 45 | async def gridcmd(self, message): 46 | """.gird """ 47 | if message.is_reply: 48 | reply_message = await message.get_reply_message() 49 | data = await check_media(reply_message) 50 | if isinstance(data, bool): 51 | await utils.answer(message, "Реплай на пикчу или стикер блять!") 52 | return 53 | else: 54 | await utils.answer(message, "`Реплай на пикчу или стикер блять`") 55 | return 56 | 57 | await message.edit("Режу ебать") 58 | file = await self.client.download_media(data, bytes) 59 | media = await griding(file) 60 | await message.delete() 61 | await message.client.send_file(message.to_id, media) 62 | 63 | 64 | 65 | 66 | @loader.sudo 67 | async def revgridcmd(self, message): 68 | """.gird """ 69 | if message.is_reply: 70 | reply_message = await message.get_reply_message() 71 | data = await check_media(reply_message) 72 | if isinstance(data, bool): 73 | await utils.answer(message, "Реплай на пикчу или стикер блять!") 74 | return 75 | else: 76 | await utils.answer(message, "`Реплай на пикчу или стикер блять`") 77 | return 78 | 79 | await message.edit("Режу ебать") 80 | file = await self.client.download_media(data, bytes) 81 | media = await griding(file) 82 | media = media[::-1] 83 | await message.delete() 84 | await message.client.send_file(message.to_id, media) 85 | 86 | 87 | 88 | 89 | 90 | async def griding(file): 91 | img = Image.open(io.BytesIO(file)) 92 | (x, y) = img.size 93 | cy = 3 94 | cx = 3 95 | sx = x//cx 96 | sy = y//cy 97 | if (sx*cx, sy*cy) != (x, y): 98 | img = img.resize((sx*cx, sy*cy)) 99 | (lx, ly) = (0, 0) 100 | media = [] 101 | for i in range(1, cy+1): 102 | for o in range(1, cx+1): 103 | mimg = img.crop((lx, ly, lx+sx, ly+sy)) 104 | bio = io.BytesIO() 105 | bio.name = 'image.png' 106 | mimg.save(bio, 'PNG') 107 | media.append(bio.getvalue()) 108 | lx = lx + sx 109 | lx = 0 110 | ly = ly + sy 111 | return media 112 | 113 | 114 | async def check_media(reply_message): 115 | if reply_message and reply_message.media: 116 | if reply_message.photo: 117 | data = reply_message.photo 118 | elif reply_message.document: 119 | if DocumentAttributeFilename(file_name='AnimatedSticker.tgs') in reply_message.media.document.attributes: 120 | return False 121 | if reply_message.gif or reply_message.video or reply_message.audio or reply_message.voice: 122 | return False 123 | data = reply_message.media.document 124 | else: 125 | return False 126 | else: 127 | return False 128 | 129 | if not data or data is None: 130 | return False 131 | else: 132 | return data -------------------------------------------------------------------------------- /spinner.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Friendly Telegram (telegram userbot) 4 | # Copyright (C) 2018-2020 The Authors 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | 19 | from .. import loader, utils # pylint: disable=relative-beyond-top-level 20 | import io 21 | from PIL import Image, ImageOps 22 | from telethon.tl.types import DocumentAttributeFilename 23 | import logging 24 | import random 25 | 26 | logger = logging.getLogger(__name__) 27 | 28 | def register(cb): 29 | cb(SpinnerMod()) 30 | 31 | 32 | @loader.tds 33 | class SpinnerMod(loader.Module): 34 | """Гавно залупное""" 35 | strings = { 36 | "name": "Spinner" 37 | } 38 | 39 | async def client_ready(self, client, db): 40 | self.client = client 41 | 42 | @loader.sudo 43 | async def spincmd(self, message): 44 | """you spin me round...""" 45 | args = utils.get_args(message) 46 | 47 | if message.is_reply: 48 | reply_message = await message.get_reply_message() 49 | data = await check_media(reply_message) 50 | if isinstance(data, bool): 51 | await utils.answer(message, "Реплай на пикчу или стикер блять!") 52 | return 53 | else: 54 | await utils.answer(message, "`Реплай на пикчу или стикер блять`") 55 | return 56 | 57 | image = io.BytesIO() 58 | await self.client.download_media(data, image) 59 | image = Image.open(image) 60 | image.thumbnail((512, 512), Image.ANTIALIAS) 61 | img = Image.new("RGB", (512, 512), "black") 62 | img.paste(image, ((512-image.width)//2, (512-image.height)//2)) 63 | image = img 64 | way = random.choice([1, -1]) 65 | frames = [] 66 | for i in range(1, 60): 67 | im = image.rotate(i*6*way) 68 | frames.append(im) 69 | frames.remove(im) 70 | 71 | image_stream = io.BytesIO() 72 | image_stream.name = "spin.gif" 73 | im.save(image_stream, "GIF", save_all=True, append_images=frames, duration = 10) 74 | image_stream.seek(0) 75 | await utils.answer(message, image_stream) 76 | 77 | @loader.sudo 78 | async def epilepsycmd(self, message): 79 | """ПРИВЕТ ЭПИЛЕТИКИ АХАХАХХА""" 80 | args = utils.get_args(message) 81 | 82 | if message.is_reply: 83 | reply_message = await message.get_reply_message() 84 | data = await check_media(reply_message) 85 | if isinstance(data, bool): 86 | await utils.answer(message, "Реплай на пикчу или стикер блять!") 87 | return 88 | else: 89 | await utils.answer(message, "`Реплай на пикчу или стикер блять`") 90 | return 91 | 92 | image = io.BytesIO() 93 | await self.client.download_media(data, image) 94 | image = Image.open(image).convert("RGB") 95 | invert = ImageOps.invert(image) 96 | 97 | image_stream = io.BytesIO() 98 | image_stream.name = "epilepsy.gif" 99 | image.save(image_stream, "GIF", save_all=True, append_images=[invert], duration = 1) 100 | image_stream.seek(0) 101 | await utils.answer(message, image_stream) 102 | 103 | 104 | 105 | async def check_media(reply_message): 106 | if reply_message and reply_message.media: 107 | if reply_message.photo: 108 | data = reply_message.photo 109 | elif reply_message.document: 110 | if DocumentAttributeFilename(file_name='AnimatedSticker.tgs') in reply_message.media.document.attributes: 111 | return False 112 | if reply_message.gif or reply_message.video or reply_message.audio or reply_message.voice: 113 | return False 114 | data = reply_message.media.document 115 | else: 116 | return False 117 | else: 118 | return False 119 | 120 | if not data or data is None: 121 | return False 122 | else: 123 | return data -------------------------------------------------------------------------------- /notexec.py: -------------------------------------------------------------------------------- 1 | # Friendly Telegram (telegram userbot) 2 | # Copyright (C) 2018-2019 The Authors 3 | 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | import logging 17 | import traceback 18 | import sys 19 | import itertools 20 | import types 21 | from meval import meval 22 | 23 | import telethon 24 | 25 | from .. import loader, utils 26 | logger = logging.getLogger(__name__) 27 | 28 | 29 | @loader.tds 30 | class ExecutorMod(loader.Module): 31 | """Stores global notes (aka snips)""" 32 | strings = {"name": "Notexec", 33 | "what_note": "What notexec should be executed?", 34 | "no_note": "Notexec not found", 35 | "execute_fail": ("Failed to execute expression:\n{}") 36 | } 37 | async def notexeccmd(self, message): 38 | """Gets the note specified""" 39 | args = utils.get_args(message) 40 | if not args: 41 | await utils.answer(message, self.strings("what_note", message)) 42 | return 43 | 44 | asset_id = self._db.get("friendly-telegram.modules.notes", "notes", {}).get(args[0], None) 45 | logger.debug(asset_id) 46 | if asset_id is not None: 47 | asset = await self._db.fetch_asset(asset_id) 48 | else: 49 | asset_id = self._db.get("friendly-telegram.modules.notes", "notes", {}).get(args[0].lower(), None) 50 | if asset_id is not None: 51 | asset = await self._db.fetch_asset(asset_id) 52 | else: 53 | asset = None 54 | if asset is None: 55 | await utils.answer(message, self.strings("no_note", message)) 56 | return 57 | 58 | cmd = await self._db.fetch_asset(asset_id) 59 | 60 | try: 61 | await meval(cmd.raw_text, globals(), **await self.getattrs(message)) 62 | except Exception: 63 | exc = sys.exc_info() 64 | exc = "".join(traceback.format_exception(exc[0], exc[1], exc[2].tb_next.tb_next.tb_next)) 65 | await utils.answer(message, self.strings("execute_fail", message) 66 | .format(utils.escape_html(exc))) 67 | return 68 | 69 | 70 | async def client_ready(self, client, db): 71 | self.client = client 72 | self.db = db 73 | self._db = db 74 | 75 | async def getattrs(self, message): 76 | return {"message": message, "client": self.client, "self": self, "db": self.db, 77 | "reply": await message.get_reply_message(), "event": message,"chat": message.to_id , **self.get_types(), **self.get_functions()} 78 | 79 | def get_types(self): 80 | return self.get_sub(telethon.tl.types) 81 | 82 | def get_functions(self): 83 | return self.get_sub(telethon.tl.functions) 84 | 85 | def get_sub(self, it, _depth=1): 86 | """Get all callable capitalised objects in an object recursively, ignoring _*""" 87 | return {**dict(filter(lambda x: x[0][0] != "_" and x[0][0].upper() == x[0][0] and callable(x[1]), 88 | it.__dict__.items())), 89 | **dict(itertools.chain.from_iterable([self.get_sub(y[1], _depth + 1).items() for y in 90 | filter(lambda x: x[0][0] != "_" 91 | and isinstance(x[1], types.ModuleType) 92 | and x[1] != it 93 | and x[1].__package__.rsplit(".", _depth)[0] 94 | == "telethon.tl", 95 | it.__dict__.items())]))} 96 | -------------------------------------------------------------------------------- /pic2pack.py: -------------------------------------------------------------------------------- 1 | from telethon import events 2 | from telethon.errors.rpcerrorlist import YouBlockedUserError 3 | from .. import loader, utils 4 | import string 5 | import random 6 | from PIL import Image 7 | import io 8 | from asyncio import sleep 9 | 10 | def register(cb): 11 | cb(pic2packMod()) 12 | 13 | 14 | class pic2packMod(loader.Module): 15 | """pic2pack""" 16 | 17 | strings = {'name': 'pic2pack'} 18 | 19 | def __init__(self): 20 | self.name = self.strings['name'] 21 | self._me = None 22 | self._ratelimit = [] 23 | 24 | async def client_ready(self, client, db): 25 | self._db = db 26 | self._client = client 27 | self.me = await client.get_me() 28 | 29 | async def pic2packcmd(self, message): 30 | """.pic2pack {packname} + """ 31 | 32 | reply = await message.get_reply_message() 33 | if not reply: 34 | await message.edit("Reply to photo❗") 35 | return 36 | 37 | args = utils.get_args_raw(message) 38 | if not args: 39 | await message.edit("Packname❓") 40 | return 41 | chat = '@Stickers' 42 | name = "".join([random.choice(list(string.ascii_lowercase+string.ascii_uppercase)) for _ in range(16)]) 43 | emoji = "▫️" 44 | image = io.BytesIO() 45 | await message.client.download_file(reply, image) 46 | image = Image.open(image) 47 | w, h = image.size 48 | www = max(w, h) 49 | await message.edit("🔪Cropping...") 50 | img = Image.new("RGBA", (www,www), (0,0,0,0)) 51 | img.paste(image, ((www-w)//2, 0)) 52 | face = img.resize((100,100)) 53 | fface = io.BytesIO() 54 | fface.name = name+".png" 55 | images = await cropping(img) 56 | face.save(fface) 57 | fface.seek(0) 58 | await message.edit("📤Uploading...") 59 | async with message.client.conversation(chat) as conv: 60 | try: 61 | x = await message.client.send_message(chat, "/cancel") 62 | await (await conv.wait_event(events.NewMessage(incoming=True, from_users=chat))).delete() 63 | await x.delete() 64 | x = await message.client.send_message(chat, "/newpack") 65 | await (await conv.wait_event(events.NewMessage(incoming=True, from_users=chat))).delete() 66 | await x.delete() 67 | x = await message.client.send_message(chat, args) 68 | await (await conv.wait_event(events.NewMessage(incoming=True, from_users=chat))).delete() 69 | await x.delete() 70 | 71 | for im in images: 72 | blank = io.BytesIO(im) 73 | blank.name = name+".png" 74 | blank.seek(0) 75 | x = await message.client.send_file(chat, blank, force_document=True) 76 | await (await conv.wait_event(events.NewMessage(incoming=True, from_users=chat))).delete() 77 | await x.delete() 78 | x = await message.client.send_message(chat, emoji) 79 | await (await conv.wait_event(events.NewMessage(incoming=True, from_users=chat))).delete() 80 | await x.delete() 81 | 82 | 83 | 84 | x = await message.client.send_message(chat, "/publish") 85 | await (await conv.wait_event(events.NewMessage(incoming=True, from_users=chat))).delete() 86 | await x.delete() 87 | x = await message.client.send_file(chat, fface, force_document=True) 88 | await (await conv.wait_event(events.NewMessage(incoming=True, from_users=chat))).delete() 89 | await x.delete() 90 | x = await message.client.send_message(chat, name) 91 | ending = await conv.wait_event(events.NewMessage(incoming=True, from_users=chat)) 92 | await x.delete() 93 | await ending.delete() 94 | for part in ending.raw_text.split(): 95 | if part.startswith("https://t.me/"): 96 | break 97 | await message.edit('✅Uploaded successful!\n'+part) 98 | 99 | except YouBlockedUserError: 100 | await message.edit('@Stickers BLOCKED⛔') 101 | return 102 | 103 | 104 | async def cropping(img): 105 | (x, y) = img.size 106 | cy = 5 107 | cx = 5 108 | sx = x//cx 109 | sy = y//cy 110 | if (sx*cx, sy*cy) != (x, y): 111 | img = img.resize((sx*cx, sy*cy)) 112 | (lx, ly) = (0, 0) 113 | media = [] 114 | for i in range(1, cy+1): 115 | for o in range(1, cx+1): 116 | mimg = img.crop((lx, ly, lx+sx, ly+sy)) 117 | mimg = mimg.resize((512,512)) 118 | bio = io.BytesIO() 119 | bio.name = 'image.png' 120 | mimg.save(bio, 'PNG') 121 | media.append(bio.getvalue()) 122 | lx = lx + sx 123 | lx = 0 124 | ly = ly + sy 125 | return media -------------------------------------------------------------------------------- /kicklast.py: -------------------------------------------------------------------------------- 1 | # @KeyZenD & @D4n13l3k00 2 | # requires: bs4 aiogram 3 | 4 | from random import choice 5 | from string import ascii_lowercase 6 | 7 | from aiogram import Bot 8 | from bs4 import BeautifulSoup as bs4 9 | from telethon import events, functions, types 10 | from telethon.tl.functions.channels import InviteToChannelRequest 11 | from telethon.tl.types import Channel 12 | 13 | from .. import loader, utils 14 | 15 | 16 | class KickLastMod(loader.Module): 17 | """Удаляет из чата последних Х зашедших""" 18 | 19 | strings = { 20 | 'name': 'KickLast', 21 | 'pref': '[KickLast] ', 22 | 'cdne': '{}Такого чата не существует', 23 | 'cfju': '{}Не могу обнаружить зашедших...', 24 | 'success': '{}Операция завершена! Кикнуто {} юзеров', 25 | 'found': '{}Найдено {} зашедших юзеров! Кикаю...', 26 | 'howmany': '{}Сколько нужно кикнуть?\n0 если всех зашедших за 48 часов', 27 | 'createerr': '{}Создание бота недоступно.\nПовтори попытку через {}' 28 | } 29 | 30 | async def botkicklastcmd(self, message): 31 | """.botkicklst <количество> <юзернейм, если канал> - Кикает при помощи тг бота""" 32 | await kick(self, message, True) 33 | 34 | async def kicklastcmd(self, message): 35 | """.kicklst <количество> <юзернейм, если канал> - Кикает юзерботом""" 36 | await kick(self, message, False) 37 | 38 | 39 | async def kick(self, message, bot=False): 40 | client = message.client 41 | args = utils.get_args(message) 42 | if not args: 43 | return await utils.answer(message, self.strings('howmany').format(self.strings('pref'))) 44 | limit = int(args[0]) 45 | limit = limit or 99999 46 | group = args[-1] if len(args) > 1 else message.chat.id 47 | try: 48 | group = await client.get_entity(group) 49 | except: 50 | await utils.answer(message, self.strings('cdne').format(self.strings('pref'))) 51 | if not isinstance(group, Channel): 52 | return await utils.answer(message, self.strings('cdne').format(self.strings('pref'))) 53 | if bot: 54 | botfather = 93372553 55 | bantoolbot = "".join(choice(list(ascii_lowercase)) 56 | for _ in range(29))+"bot" 57 | async with client.conversation(botfather) as conv: 58 | await (await client.send_message(botfather, "/newbot")).delete() 59 | newbot = await conv.wait_event(events.NewMessage(incoming=True, from_users=botfather)) 60 | await newbot.delete() 61 | if "Sorry" in newbot.text: 62 | return await utils.answer(message, self.strings('howmany').format(self.strings('pref'), newbot.text[45:])) 63 | await (await client.send_message(botfather, "BanTool")).delete() 64 | await (await conv.wait_event(events.NewMessage(incoming=True, from_users=botfather))).delete() 65 | await (await client.send_message(botfather, bantoolbot)).delete() 66 | html = await conv.wait_event(events.NewMessage(incoming=True, from_users=botfather)) 67 | await html.delete() 68 | soup = bs4(html.text, "html.parser") 69 | token = soup.findAll("code")[0].text 70 | await client(InviteToChannelRequest(group, [bantoolbot])) 71 | await client(functions.channels.EditAdminRequest( 72 | channel=group, 73 | user_id=bantoolbot, 74 | admin_rights=types.ChatAdminRights(ban_users=True), rank='BanToolBot')) 75 | banlist = [x.user_id async for x in client.iter_admin_log(group, join=True, limit=limit)] 76 | 77 | message = await utils.answer(message, self.strings('found').format(self.strings('pref'), str(len(banlist)))) 78 | if not banlist: 79 | return await utils.answer(message, self.strings('cfju').format(self.strings('pref'))) 80 | for banid in banlist: 81 | if bot: 82 | await Bot(token).kick_chat_member(f"-100{group}", banid) 83 | else: 84 | await client.kick_participant(group, banid) 85 | if bot: 86 | await client.kick_participant(group, bantoolbot) 87 | async with client.conversation(botfather) as conv: 88 | await client.send_message(botfather, "/deletebot") 89 | await conv.wait_event(events.NewMessage(incoming=True, from_users=botfather)) 90 | await client.send_message(botfather, "@"+bantoolbot) 91 | await conv.wait_event(events.NewMessage(incoming=True, from_users=botfather)) 92 | await client.send_message(botfather, "Yes, I am totally sure.") 93 | return await utils.answer(message, self.strings('success').format(self.strings('pref'), str(len(banlist)))) 94 | -------------------------------------------------------------------------------- /help.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import inspect 3 | 4 | from telethon.tl.functions.channels import JoinChannelRequest 5 | 6 | from .. import loader, utils, main, security 7 | 8 | logger = logging.getLogger(__name__) 9 | 10 | 11 | @loader.tds 12 | class HelpMod(loader.Module): 13 | """Provides this help message""" 14 | strings = {"name": "Help", 15 | "bad_module": 'Модуля "{}" нет в базе!', 16 | "single_mod_header": "Информация о {}:\n", 17 | "single_cmd": "\n {}\n", 18 | "undoc_cmd": "Для этой команды нет документации", 19 | "all_header": 'Список из {} доступных модулей:\n\n', 20 | "mod_tmpl": '\n‣{}', 21 | "first_cmd_tmpl": "⋮( {}", 22 | "cmd_tmpl": " | {}", 23 | "SomeScripts": "SomeScripts"} 24 | 25 | @loader.unrestricted 26 | async def helpcmd(self, message): 27 | """.help [module]""" 28 | args = utils.get_args_raw(message) 29 | id = message.sender_id 30 | if args: 31 | module = None 32 | for mod in self.allmodules.modules: 33 | if mod.strings("name", message).lower() == args.lower(): 34 | module = mod 35 | if module is None: 36 | await utils.answer(message, self.strings("bad_module", message).format(args)) 37 | return 38 | # Translate the format specification and the module separately 39 | try: 40 | name = module.strings("name", message) 41 | except KeyError: 42 | name = getattr(module, "name", "ERROR") 43 | reply = self.strings("single_mod_header", message).format(utils.escape_html(name), 44 | utils.escape_html((self.db.get(main.__name__, 45 | "command_prefix", 46 | False) or ".")[0])) 47 | if module.__doc__: 48 | reply += "\n"+"\n".join(" " + t for t in utils.escape_html(inspect.getdoc(module)).split("\n")) 49 | else: 50 | logger.warning("Module %s is missing docstring!", module) 51 | commands = {name: func for name, func in module.commands.items() 52 | if await self.allmodules.check_security(message, func)} 53 | for name, fun in commands.items(): 54 | reply += self.strings("single_cmd", message).format(name) 55 | if fun.__doc__: 56 | reply += utils.escape_html("\n".join(" " + t for t in inspect.getdoc(fun).split("\n"))) 57 | else: 58 | reply += self.strings("undoc_cmd", message) 59 | else: 60 | count = 0 61 | for i in self.allmodules.modules: 62 | if len(i.commands) != 0: 63 | count += 1 64 | reply = self.strings("all_header", message).format(count) 65 | 66 | for mod in self.allmodules.modules: 67 | if len(mod.commands) != 0: 68 | try: 69 | name = mod.strings("name", message) 70 | except KeyError: 71 | name = getattr(mod, "name", "ERROR") 72 | reply += self.strings("mod_tmpl", message).format(id, name) 73 | first = True 74 | commands = [name for name, func in mod.commands.items() 75 | if await self.allmodules.check_security(message, func)] 76 | for cmd in commands: 77 | if first: 78 | reply += self.strings("first_cmd_tmpl", message).format(cmd) 79 | first = False 80 | else: 81 | reply += self.strings("cmd_tmpl", message).format(cmd) 82 | reply += " )" 83 | 84 | await utils.answer(message, reply) 85 | 86 | @loader.unrestricted 87 | async def KeyZenDcmd(self, message): 88 | """ДА Я ЗНАЮ ЧТО Я ОХУЕЛ НО МНЕ ПОХУЙ, МОЙ ХЕЛП!""" 89 | await message.delete() 90 | await self.client(JoinChannelRequest(self.strings("SomeScripts", message))) 91 | 92 | 93 | async def client_ready(self, client, db): 94 | self.client = client 95 | self.is_bot = await client.is_bot() 96 | self.db = db 97 | -------------------------------------------------------------------------------- /python.py: -------------------------------------------------------------------------------- 1 | # Friendly Telegram (telegram userbot) 2 | # Copyright (C) 2018-2019 The Authors 3 | 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | import logging 18 | import traceback 19 | import sys 20 | import itertools 21 | import types 22 | from meval import meval 23 | 24 | import telethon 25 | 26 | from .. import loader, utils 27 | 28 | logger = logging.getLogger(__name__) 29 | 30 | 31 | @loader.tds 32 | class PythonMod(loader.Module): 33 | """Python stuff""" 34 | strings = {"name": "Python", 35 | "evaluated": "Выполненное выражение:\n{}\nВозвращено:\n{}", 36 | "evaluate_fail": ("(eval)Не удалось выполнить выражение:\n{}" 37 | "\n\nОшибка:\n{}"), 38 | "execute_fail": ("(exec)Не удалось выполнить выражение:\n{}" 39 | "\n\nОшибка:\n{}")} 40 | 41 | async def client_ready(self, client, db): 42 | self.client = client 43 | self.db = db 44 | 45 | @loader.owner 46 | async def evalcmd(self, message): 47 | """.eval 48 | Evaluates python code""" 49 | phone = message.client.phone 50 | ret = self.strings("evaluated", message) 51 | try: 52 | it = await meval(utils.get_args_raw(message), globals(), **await self.getattrs(message)) 53 | except Exception: 54 | exc = sys.exc_info() 55 | exc = "".join(traceback.format_exception(exc[0], exc[1], exc[2].tb_next.tb_next.tb_next)) 56 | exc = exc.replace(phone, "❚"*len(phone)) 57 | await utils.answer(message, self.strings("evaluate_fail", message) 58 | .format(utils.escape_html(utils.get_args_raw(message)), utils.escape_html(exc))) 59 | return 60 | ret = ret.format(utils.escape_html(utils.get_args_raw(message)), utils.escape_html(it)) 61 | ret = ret.replace(str(phone), "❚"*len(str(phone))) 62 | await utils.answer(message, ret) 63 | 64 | @loader.owner 65 | async def execcmd(self, message): 66 | """.exec 67 | Executes python code""" 68 | phone = message.client.phone 69 | try: 70 | await meval(utils.get_args_raw(message), globals(), **await self.getattrs(message)) 71 | except Exception: 72 | exc = sys.exc_info() 73 | exc = "".join(traceback.format_exception(exc[0], exc[1], exc[2].tb_next.tb_next.tb_next)) 74 | exc = exc.replace(str(phone), "❚"*len(str(phone))) 75 | await utils.answer(message, self.strings("execute_fail", message) 76 | .format(utils.escape_html(utils.get_args_raw(message)), utils.escape_html(exc))) 77 | return 78 | 79 | async def getattrs(self, message): 80 | return {"message": message, "client": self.client, "self": self, "db": self.db, 81 | "reply": await message.get_reply_message(), **self.get_types(), **self.get_functions(), 82 | "event": message, "chat": message.to_id} 83 | 84 | def get_types(self): 85 | return self.get_sub(telethon.tl.types) 86 | 87 | def get_functions(self): 88 | return self.get_sub(telethon.tl.functions) 89 | 90 | def get_sub(self, it, _depth=1): 91 | """Get all callable capitalised objects in an object recursively, ignoring _*""" 92 | return {**dict(filter(lambda x: x[0][0] != "_" and x[0][0].upper() == x[0][0] and callable(x[1]), 93 | it.__dict__.items())), 94 | **dict(itertools.chain.from_iterable([self.get_sub(y[1], _depth + 1).items() for y in 95 | filter(lambda x: x[0][0] != "_" 96 | and isinstance(x[1], types.ModuleType) 97 | and x[1] != it 98 | and x[1].__package__.rsplit(".", _depth)[0] 99 | == "telethon.tl", 100 | it.__dict__.items())]))} 101 | -------------------------------------------------------------------------------- /pydraft.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import itertools 3 | import logging 4 | import re 5 | import sys 6 | import telethon 7 | import traceback 8 | import types 9 | from meval import meval 10 | from .. import loader, utils 11 | 12 | logger = logging.getLogger(__name__) 13 | 14 | 15 | class ModuleNotForBot(Exception): 16 | pass 17 | 18 | 19 | @loader.tds 20 | class PyDraftMod(loader.Module): 21 | """Выполняет выражение из черновиков (работает 10 минут) 22 | инструкция на канале @SomeScripts""" 23 | strings = { 24 | 'name': 'PyDraft', 25 | 'on': 'PyDraft: Включен', 26 | 'off': 'PyDraft: Отключен', 27 | 'isolator': 'pydraft:', 28 | 'timer': 60 * 10, 29 | 'note': '(PyDraft) ExecNote {} не найден!', 30 | "evaluated": "(PyDratf)Выполненное выражение:\n{}\nВозвращено:\n{}", 31 | "execute_fail": "(PyDraft)Не удалось выполнить выражение:\n{}\nОшибка:\n{}"} 32 | 33 | def __init__(self): 34 | self.name = self.strings['name'] 35 | 36 | async def client_ready(self, client, db): 37 | self.client: telethon.client.telegramclient.TelegramClient = client 38 | self.db = db 39 | self._db = db 40 | 41 | async def pydraftcmd(self, message): 42 | """Запустить/Остановить""" 43 | status = self.db.get(self.name, "status", False) 44 | if not status: 45 | self.db.set(self.name, "status", True) 46 | self.client.loop.create_task(self.check_drafts(message)) 47 | await utils.answer(message, self.strings['on']) 48 | else: 49 | self.db.set(self.name, 'status', False) 50 | await utils.answer(message, self.strings['off']) 51 | 52 | async def pydraft(self, draft): 53 | show = True if draft.text.startswith('!') else False 54 | cmd = draft.text[len(self.strings['isolator'])+(1 if show else 0):].strip() 55 | if cmd.startswith('note:'): 56 | asset_id = self._db.get("friendly-telegram.modules.notes", "notes", {}).get(cmd.replace('note:', ''), None) 57 | if asset_id is not None: 58 | cmd = await self._db.fetch_asset(asset_id) 59 | 60 | await draft.delete() 61 | try: 62 | it = await meval(cmd, globals(), **await self.getattrs(draft)) 63 | if show: 64 | ret = self.strings["evaluated"].format(cmd, utils.escape_html(it)) 65 | await draft.set_message(ret) 66 | except Exception: 67 | exc = sys.exc_info() 68 | exc = "".join(traceback.format_exception(exc[0], exc[1], exc[2].tb_next.tb_next.tb_next)) 69 | await draft.set_message(self.strings["execute_fail"].format(cmd, exc)) 70 | return 71 | 72 | async def check_drafts(self, message): 73 | msg = await self.client.send_message('me', 'PyDraft') 74 | timer = 0 75 | while True: 76 | await msg.edit(f"PyDraft time left {self.strings['timer']-timer}") 77 | if not self.db.get(self.name, "status", False): 78 | await utils.answer(message, self.strings['off']) 79 | break 80 | isolator = self.strings['isolator'] 81 | drafts = await self.client.get_drafts() 82 | for draft in drafts: 83 | text = draft.text 84 | if text.startswith(isolator) or text.startswith('!' + isolator): 85 | await self.pydraft(draft) 86 | timer += 1 87 | await asyncio.sleep(1) 88 | if timer >= self.strings['timer']: 89 | self.db.set(self.name, 'status', False) 90 | await utils.answer(message, self.strings['off']) 91 | break 92 | await msg.delete() 93 | 94 | async def getattrs(self, draft): 95 | data = {'draft':draft, "client": self.client, "self": self, "db": self.db, "chat": draft.entity.id, **self.get_types(), **self.get_functions()} 96 | if draft.reply_to_msg_id: 97 | data['message'] = await self.client.get_messages(draft.entity.id, ids=draft.reply_to_msg_id) 98 | data['reply'] = await data['message'].get_reply_message() 99 | return data 100 | 101 | def get_types(self): 102 | return self.get_sub(telethon.tl.types) 103 | 104 | def get_functions(self): 105 | return self.get_sub(telethon.tl.functions) 106 | 107 | def get_sub(self, it, _depth=1): 108 | """Get all callable capitalised objects in an object recursively, ignoring _*""" 109 | return {**dict(filter(lambda x: x[0][0] != "_" and x[0][0].upper() == x[0][0] and callable(x[1]), 110 | it.__dict__.items())), 111 | **dict(itertools.chain.from_iterable([self.get_sub(y[1], _depth + 1).items() for y in 112 | filter(lambda x: x[0][0] != "_" 113 | and isinstance(x[1], types.ModuleType) 114 | and x[1] != it 115 | and x[1].__package__.rsplit(".", _depth)[0] 116 | == "telethon.tl", 117 | it.__dict__.items())]))} 118 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | # Friendly Telegram (telegram userbot) 2 | # Copyright (C) 2018-2019 The Authors 3 | 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | import logging 18 | import time 19 | from datetime import datetime 20 | 21 | from io import BytesIO 22 | 23 | from .. import loader, utils 24 | 25 | logger = logging.getLogger(__name__) 26 | 27 | 28 | @loader.test(args=None) 29 | async def dumptest(conv): 30 | m = await conv.send_message("test") 31 | await conv.send_message(".dump", reply_to=m) 32 | r = await conv.get_response() 33 | assert r.message.startswith("Message(") and "test" in r.message, r 34 | 35 | 36 | @loader.test(args="0") 37 | async def logstest(conv): 38 | r = await conv.get_response() 39 | assert r.message == "Loading media...", r 40 | r2 = await conv.get_response() 41 | assert r2.document, r2 42 | 43 | 44 | @loader.tds 45 | class TestMod(loader.Module): 46 | """Self-tests""" 47 | strings = {"name": "Tester", 48 | "pong": ".pong", 49 | "bad_loglevel": "Не верный уровень логов.", 50 | "uploading_logs": "Собираю логи...", 51 | "no_logs": "Логов с уровнем {} нет.", 52 | "logs_filename": "FTG-Logs[{}].txt", 53 | "logs_unsafe": ("Если ты точно хочешь показать логи с уровнем {lvl}, то напиши .logs {lvl} {force}"), 54 | "logs_force": "FORCE_INSECURE", 55 | "suspend_invalid_time": "Invalid time to suspend"} 56 | 57 | @loader.test(resp="Pong") 58 | @loader.unrestricted 59 | async def pingcmd(self, message): 60 | """Does nothing""" 61 | await utils.answer(message, self.strings("pong", message)) 62 | 63 | @loader.owner 64 | async def pungcmd(self, message): 65 | """Useless pinger""" 66 | a = 5 67 | r = utils.get_args(message) 68 | if r and r[0].isdigit(): 69 | a = int(r[0]) 70 | ping_msg = [] 71 | ping_data = [] 72 | for _ in range(a): 73 | start = datetime.now() 74 | msg = await message.client.send_message("me", "ping") 75 | end = datetime.now() 76 | duration = (end - start).microseconds / 1000 77 | ping_data.append(duration) 78 | ping_msg.append(msg) 79 | ping = sum(ping_data) / len(ping_data) 80 | await message.edit(f"[ ping {str(ping)[0:5]}ms ]") 81 | for i in ping_msg: 82 | await i.delete() 83 | 84 | @loader.test(func=dumptest) 85 | async def dumpcmd(self, message): 86 | """Use in reply to get a dump of a message""" 87 | if not message.is_reply: 88 | return 89 | await utils.answer(message, "" 90 | + utils.escape_html((await message.get_reply_message()).stringify()) + "") 91 | 92 | @loader.test(func=logstest) 93 | async def logscmd(self, message): 94 | """.logs 95 | Dumps logs. Loglevels below WARNING may contain personal info.""" 96 | args = utils.get_args(message) 97 | if not len(args) == 1 and not len(args) == 2: 98 | args = ["40"] 99 | try: 100 | lvl = int(args[0]) 101 | except ValueError: 102 | # It's not an int. Maybe it's a loglevel 103 | lvl = getattr(logging, args[0].upper(), None) 104 | if not isinstance(lvl, int): 105 | await utils.answer(message, self.strings("bad_loglevel", message)) 106 | return 107 | if not (lvl >= logging.WARNING or (len(args) == 2 and args[1] == self.strings("logs_force", message))): 108 | await utils.answer(message, 109 | self.strings("logs_unsafe", message).format(lvl=lvl, force=self.strings("logs_force", message))) 110 | return 111 | [handler] = logging.getLogger().handlers 112 | logs = ("\n".join(handler.dumps(lvl))).encode("utf-8") 113 | if not len(logs) > 0: 114 | await utils.answer(message, self.strings("no_logs", message).format(lvl)) 115 | return 116 | logs = BytesIO(logs) 117 | logs.name = self.strings("logs_filename", message).format(lvl) 118 | await utils.answer(message, logs) 119 | 120 | @loader.owner 121 | async def suspendcmd(self, message): 122 | """.suspend