Commited backup

This commit is contained in:
2025-07-10 21:02:34 +03:00
parent 952c1001e3
commit da0b80823e
1310 changed files with 254133 additions and 41 deletions

View File

@@ -0,0 +1,31 @@
# This workflows will upload a Python Package using Twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
name: Upload Python Package
on:
release:
types: [created]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
- name: Build and publish
env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
python setup.py sdist bdist_wheel
twine upload dist/*

39
KeyZenD/modules/0x.py Normal file
View File

@@ -0,0 +1,39 @@
from .. import loader, utils # pylint: disable=relative-beyond-top-level
from requests import post
import io
@loader.tds
class x0Mod(loader.Module):
"""Uploader"""
strings = {
"name": "x0 Uploader"
}
async def client_ready(self, client, db):
self.client = client
@loader.sudo
async def x0cmd(self, message):
await message.edit("<b>Uploading...</b>")
reply = await message.get_reply_message()
if not reply:
await message.edit("<b>Reply to message!</b>")
return
media = reply.media
if not media:
file = io.BytesIO(bytes(reply.raw_text, "utf-8"))
file.name = "txt.txt"
else:
file = io.BytesIO(await self.client.download_file(media))
file.name = reply.file.name if reply.file.name else reply.file.id+reply.file.ext
try:
x0at = post('https://x0.at', files={'file': file})
except ConnectionError as e:
await message.edit(ste(e))
return
url = x0at.text
output = f'<a href="{url}">URL: </a><code>{url}</code>'
await message.edit(output)

View File

@@ -0,0 +1,55 @@
from telethon import events
from telethon.errors.rpcerrorlist import YouBlockedUserError
from .. import loader, utils
def register(cb):
cb(BlackLinesMod())
class BlackLinesMod(loader.Module):
"""Draw line via @BlackLinesBot"""
strings = {'name': 'BlackLines'}
def __init__(self):
self.name = self.strings['name']
self._me = None
self._ratelimit = []
async def client_ready(self, client, db):
self._db = db
self._client = client
self.me = await client.get_me()
async def linecmd(self, message):
""".line <reply to photo>"""
reply = await message.get_reply_message()
if not reply:
await message.edit("reply to photo")
return
try:
photo = reply.media.photo
except:
await message.edit("reply to photo only")
return
args = utils.get_args_raw(message)
chat = '@BlackLinesBot'
await message.edit('@BlackLinesBot <code>in process...</code>')
async with message.client.conversation(chat) as conv:
try:
response = conv.wait_event(events.NewMessage(incoming=True, from_users=1051644279))
await message.client.send_file(chat, photo, caption=args)
response = await response
except YouBlockedUserError:
await message.reply('<code>Unblock</code> @BlackLinesBot')
return
await message.delete()
await message.client.send_file(message.to_id, response.media)
#у меня каждый коммит в чате упоминается ботом

105
KeyZenD/modules/Circles.py Normal file
View File

@@ -0,0 +1,105 @@
from .. import loader, utils # pylint: disable=relative-beyond-top-level
from PIL import Image, ImageDraw, ImageOps, ImageFilter
import io
from telethon.tl.types import DocumentAttributeFilename
import logging
from moviepy.editor import VideoFileClip
import os
logger = logging.getLogger(__name__)
def register(cb):
cb(CirclesMod())
@loader.tds
class CirclesMod(loader.Module):
"""округляет всё"""
strings = {
"name": "Circles"
}
def __init__(self):
self.name = self.strings['name']
async def client_ready(self, client, db):
self.client = client
@loader.sudo
async def roundcmd(self, message):
""".round <Reply to image/sticker or video/gif>"""
reply = None
if message.is_reply:
reply = await message.get_reply_message()
data = await check_media(reply)
if isinstance(data, bool):
await utils.answer(message, "<b>Reply to image/sticker or video/gif!</b>")
return
else:
await utils.answer(message, "<b>Reply to image/sticker or video/gif!</b>")
return
data, type = data
if type == "img":
await message.edit("<b>Processing image</b>📷")
img = io.BytesIO()
bytes = await message.client.download_file(data, img)
im = Image.open(img)
w, h = im.size
img = Image.new("RGBA", (w,h), (0,0,0,0))
img.paste(im, (0, 0))
m = min(w, h)
img = img.crop(((w-m)//2, (h-m)//2, (w+m)//2, (h+m)//2))
w, h = img.size
mask = Image.new('L', (w, h), 0)
draw = ImageDraw.Draw(mask)
draw.ellipse((10, 10, w-10, h-10), fill=255)
mask = mask.filter(ImageFilter.GaussianBlur(2))
img = ImageOps.fit(img, (w, h))
img.putalpha(mask)
im = io.BytesIO()
im.name = "img.webp"
img.save(im)
im.seek(0)
await message.client.send_file(message.to_id, im, reply_to=reply)
else:
await message.edit("<b>Processing video</b>🎥")
await message.client.download_file(data, "video.mp4")
video = VideoFileClip("video.mp4")
video.reader.close()
w, h = video.size
m = min(w, h)
box = [(w-m)//2, (h-m)//2, (w+m)//2, (h+m)//2]
video = video.crop(*box)
await message.edit("<b>Saving video</b>📼")
video.write_videofile("result.mp4")
await message.client.send_file(message.to_id, "result.mp4", video_note=True, reply_to=reply)
os.remove("video.mp4")
os.remove("result.mp4")
await message.delete()
async def check_media(reply):
type = "img"
if reply and reply.media:
if reply.photo:
data = reply.photo
elif reply.document:
if DocumentAttributeFilename(file_name='AnimatedSticker.tgs') in reply.media.document.attributes:
return False
if reply.gif or reply.video:
type = "vid"
if reply.audio or reply.voice:
return False
data = reply.media.document
else:
return False
else:
return False
if not data or data is None:
return False
else:
return (data, type)

111
KeyZenD/modules/DNA.py Normal file
View File

@@ -0,0 +1,111 @@
# requires: pillow
# requires: wand
from .. import loader, utils
import io
from telethon.tl.types import DocumentAttributeFilename
import logging
from wand.image import Image
from PIL import Image as IM
# https://t.me/KeyZenD
# https://t.me/SomeScripts
logger = logging.getLogger(__name__)
def register(cb):
cb(DistortNoApiMod())
@loader.tds
class DistortNoApiMod(loader.Module):
"""distorting images"""
strings = {
"name": "DistortNoApi"
}
async def client_ready(self, client, db):
self.client = client
@loader.sudo
async def distortcmd(self, message):
""".distort <reply to photo>
.distort im
.distort 50
.distort 50 im
.distort im 50
im => кидает стикеры как фото
50 => (от 0 до дохуя) процент сжатия"""
if message.is_reply:
reply_message = await message.get_reply_message()
data, mime = await check_media(reply_message)
if isinstance(data, bool):
await utils.answer(message, "<code>Reply to image or stick!</code>")
return
else:
await utils.answer(message, "<code>Reply to image or stick!</code>")
return
rescale_rate = 70
a = utils.get_args(message)
force_file = False
if a:
if 'im' in a:
force_file = True
a.remove('im')
if len(a) > 0:
if a[0].isdigit():
rescale_rate = int(a[0])
if rescale_rate <= 0:
rescale_rate = 70
await message.edit("<code>D i s t o r t i n g . . .</code>")
file = await message.client.download_media(data, bytes)
file, img = io.BytesIO(file), io.BytesIO()
img.name = 'img.png'
IM.open(file).save(img, 'PNG')
media = await distort(io.BytesIO(img.getvalue()), rescale_rate)
out, im = io.BytesIO(), IM.open(media)
if force_file:
mime = 'png'
out.name = f'out.{mime}'
im.save(out, mime.upper())
out.seek(0)
await message.edit("<code>S e n d i n g . . .</code>")
await message.client.send_file(message.to_id, out, reply_to=reply_message.id)
await message.delete()
async def distort(file, rescale_rate):
img = Image(file=file)
x, y = img.size[0], img.size[1]
popx = int(rescale_rate*(x//100))
popy = int(rescale_rate*(y//100))
img.liquid_rescale(popx, popy, delta_x=1, rigidity=0)
img.resize(x, y)
out = io.BytesIO()
out.name = f'output.png'
img.save(file=out)
return io.BytesIO(out.getvalue())
async def check_media(reply_message):
mime = None
if reply_message and reply_message.media:
if reply_message.photo:
data = reply_message.photo
mime = 'image/jpeg'
elif reply_message.document:
if DocumentAttributeFilename(file_name='AnimatedSticker.tgs') in reply_message.media.document.attributes:
return False, mime
if reply_message.gif or reply_message.video or reply_message.audio or reply_message.voice:
return False, mime
data = reply_message.media.document
mime = reply_message.media.document.mime_type
if 'image/' not in mime:
return False, mime
else:
return False, mime
else:
return False, mime
if not data or data is None:
return False, mime
else:
mime = mime.split('/')[1]
return data, mime

View File

@@ -0,0 +1,68 @@
import asyncio
import logging
import sys, os, random
from .. import loader, utils
logger = logging.getLogger(__name__)
@loader.tds
class GlitcherMod(loader.Module):
"""Glitcher of anything"""
strings = {"name": "Glitcher",
"reply": "Reply to message!",
"error": "Impossible to upload file!",
"processing": "Work in progress!"}
@loader.unrestricted
async def glitchcmd(self, message):
""".glitch level: float or int <reply to anything>"""
reply = await message.get_reply_message()
if not reply:
await message.edit("".join([ random.choice(html).format(ch) for ch in self.strings("reply", message)]))
return
if not reply.file:
infile = "message.txt"
f = open(infile,"w")
f.write(reply.text)
f.close()
outfile = "glitched_message.txt"
else:
infile = await reply.download_media()
outfile = "glitched_"+infile
percent = 0.1
try:
percent = float(utils.get_args_raw(message))
except ValueError or TypeError:
pass
await message.edit("".join([ random.choice(html).format(ch) for ch in self.strings("processing", message)]))
with open(infile, 'rb') as inf:
with open(outfile, 'wb') as outf:
fileext = infile.split(".")[1]
try:
for byte in range(headersize[fileext]):
inbyte = inf.read(1)
outbyte = inbyte
outf.write(outbyte)
except KeyError:
pass
while True:
inbyte = inf.read(1)
if not inbyte:
break
if (random.random() < percent/100):
outbyte = os.urandom(1)
else:
outbyte = inbyte
outf.write(outbyte)
try:
await reply.reply(file=outfile)
await message.delete()
except:
await message.edit("".join([ random.choice(html).format(ch) for ch in self.strings("error", message) ]))
finally:
[os.remove(file) for file in [infile, outfile]]
html = ["<b>{}<b>", "<code>{}</code>", "<i>{}</i>", "<del>{}</del>", "<u>{}</u>", '<a href="https://bruh.moment">{}</a>']
headersize = {'jpg': 9, 'png': 8, 'bmp': 54, 'gif': 14, 'tiff': 8}

70
KeyZenD/modules/Hasher.py Normal file
View File

@@ -0,0 +1,70 @@
from .. import loader, utils
from hashlib import md5, sha1, sha224, sha256, sha384, sha512, blake2b, blake2s
def register(cb):
cb(HasherMod())
class HasherMod(loader.Module):
"""Hashing text and files"""
strings = {'name': 'Hasher'}
def __init__(self):
self.name = self.strings['name']
self._me = None
self._ratelimit = []
async def client_ready(self, client, db):
self._db = db
self._client = client
self.me = await client.get_me()
async def md5cmd(self, message):
""".md5 <(text or media) or (reply to text or media)>\nHashing to md5"""
await hashing(message, 0)
async def sha1cmd(self, message):
""".sha1 <(text or media) or (reply to text or media)\nHashing to sha1"""
await hashing(message, 1)
async def sha224cmd(self, message):
""".sha224 <(text or media) or (reply to text or media)\nHashing to sha224"""
await hashing(message, 2)
async def sha256cmd(self, message):
""".sha255 <(text or media) or (reply to text or media)\nHashing to sha256"""
await hashing(message, 3)
async def sha384cmd(self, message):
""".sha384 <(text or media) or (reply to text or media)\nHashing to sha384"""
await hashing(message, 4)
async def sha512cmd(self, message):
""".sha512 <(text or media) or (reply to text or media)\nHashing to sha512"""
await hashing(message, 5)
async def blake2bcmd(self, message):
""".blake2 <(text or media) or (reply to text or media)\nHashing to blake2"""
await hashing(message, 6)
async def blake2scmd(self, message):
""".blake2s <(text or media) or (reply to text or media)\nHashing to blake2s"""
await hashing(message, 7)
async def hashing(m, type):
types = [md5, sha1, sha224, sha256, sha384, sha512, blake2b, blake2s]
typez = ["md5", "sha1", "sha224", "sha256", "sha384", "sha512", "blake2b", "blake2s"]
reply = await m.get_reply_message()
mtext = utils.get_args_raw(m)
if m.media:
await m.edit("<b>D o w n l o a d i n g . . .</b>")
data = await m.client.download_file(m, bytes)
elif mtext:
data = mtext.encode()
elif reply:
if reply.media:
await m.edit("<b>D o w n l o a d i n g . . .</b>")
data = await m.client.download_file(reply, bytes)
else:
data = reply.raw_text.encode()
else:
await m.edit(f"<b>What hashing to {typez[type]}?</b>")
return
await m.edit("<b>H a s h i n g . . .</b>")
try:
result = types[type](data)
await m.edit(typez[type].upper()+": <code>" + str(result.hexdigest()).upper()+"</code>")
except:
await m.edit("<b>ERЯOR!</b>")

View File

@@ -0,0 +1,56 @@
from telethon import events
from telethon.errors.rpcerrorlist import YouBlockedUserError
from .. import loader, utils
def register(cb):
cb(Lines50Mod())
class Lines50Mod(loader.Module):
"""Draw photo with 50 lines via @Lines50Bot"""
strings = {'name': 'Lines50'}
def __init__(self):
self.name = self.strings['name']
self._me = None
self._ratelimit = []
async def client_ready(self, client, db):
self._db = db
self._client = client
self.me = await client.get_me()
async def linescmd(self, message):
""".lines <reply to photo>"""
reply = await message.get_reply_message()
if not reply:
await message.edit("reply to photo")
return
try:
photo = reply.media.photo
except:
await message.edit("reply to photo only")
return
chat = '@Lines50Bot'
await message.edit('@Lines50Bot <code>in process...</code>')
async with message.client.conversation(chat) as conv:
try:
response = conv.wait_event(events.NewMessage(incoming=True, from_users=1120861844))
await message.client.send_file(chat, photo)
response = await response
except YouBlockedUserError:
await message.reply('<code>Unblock</code> @Lines50Bot')
return
await message.delete()
await message.client.send_file(message.to_id, response.media)

View File

@@ -0,0 +1,44 @@
from .. import loader, utils
import io
from requests import get
def register(cb):
cb(LoremIpsumMod())
class LoremIpsumMod(loader.Module):
"""Lorem Ipsum generation"""
strings = {'name': 'LoermIpsum'}
def __init__(self):
self.name = self.strings['name']
async def loremipsumcmd(self, message):
""".loremipsum <count: int> <length: str> <file?>
count - number of paragraphs| std: 1
length - s-short, m-medium, l-long, v-verylong|std: m(edium)
file - if nothing- send as message, if anything- send as file"""
s = 'small'
m = length = 'medium'
l = 'long'
v = 'verylong'
args = utils.get_args(message)
count = 1
as_file = False
if args:
count = int(args[0]) if args[0].isdigit() else 1
if len(args) == 2:
lenght = args[1].lower()
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 # сижу ахуел
if len(args) >= 3:
as_file = True
url = f"https://loripsum.net/api/{count}/{length}/plaintext"
out = get(url)
if as_file:
out = io.BytesIO(out.content)
out.name = f"LoremIpsum.{count}.txt"
out.seek(0)
else: out = out.text
await utils.answer(message, out)

33
KeyZenD/modules/MTF.py Normal file
View File

@@ -0,0 +1,33 @@
from .. import loader, utils
import io
@loader.tds
class MTFMod(loader.Module):
"""send Message as file"""
strings = {'name': 'MessageToFile'}
async def mtfcmd(self, message):
""".mtf <reply to text>"""
reply = await message.get_reply_message()
if not reply or not reply.message:
await message.edit("<b>Reply to text!</b>")
return
text = bytes(reply.raw_text, "utf8")
fname = utils.get_args_raw(message) or str(message.id+reply.id)+".txt"
file = io.BytesIO(text)
file.name = fname
file.seek(0)
await reply.reply(file=file)
await message.delete()
async def ftmcmd(self, message):
""".ftm <reply to file>"""
reply = await message.get_reply_message()
if not reply or not reply.file:
await message.edit("<b>Reply to file!</b>")
return
text = await reply.download_media(bytes)
text = str(text, "utf8")
if utils.get_args(message):
text = f"<code>{text}</code>"
await utils.answer(message, utils.escape_html(text))

View File

@@ -0,0 +1,32 @@
from .. import loader,utils
from PIL import Image,ImageFilter
import io,random,string
class aMod(loader.Module):
strings={'name':'MacAshoT'}
async def maccmd(S,message):
R=True;Q='image';P='/';L='RGBA';K='<b>Image?</b>';A=message;C=await A.get_reply_message();B=io.BytesIO();M=None
if A.file:
if A.file.mime_type.split(P)[0]==Q:await A.download_media(B)
elif C:
if C.file:
if C.file.mime_type.split(P)[0]==Q:M=R;await C.download_media(B)
else:await A.edit(K);return
else:await A.edit(K);return
elif C:
if C.file:
if C.file.mime_type.split(P)[0]==Q:M=R;await C.download_media(B)
else:await A.edit(K);return
else:await A.edit(K);return
try:I=Image.open(B)
except:await A.edit(K);return
await A.edit('<b>Working...</b>');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')
if I.mode==L:
B.paste(I,(0,0),I);E=Image.new(L,(F,G))
for N in range(F):
for O in range(G):
if B.getpixel((N,O))!=(0,0,0,0):E.putpixel((N,O),(0,0,0))
else:B.paste(I,(0,0));E=Image.new(L,(F,G),'black')
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)
if utils.get_args_raw(A):await A.client.send_file(A.to_id,H,force_document=R);await A.delete()
elif M:await C.reply(file=H);await A.delete()
else:await A.edit(file=H,text='')

View File

@@ -0,0 +1,83 @@
# @KeyZenD & @D4n13l3k00
import random
from telethon import types
from .. import loader, utils
@loader.tds
class MegaMozgMod(loader.Module):
strings = {
'name': 'MegaMozg',
'pref': '<b>[MegaMozg]</b> ',
'need_arg': '{}Нужен аргумент',
'status': '{}{}',
'on': '{}Включён',
'off': '{}Выключен',
}
_db_name = 'MegaMozg'
async def client_ready(self, _, db):
self.db = db
@staticmethod
def str2bool(v):
return v.lower() in ("yes", "y", "ye", "yea", "true", "t", "1", "on", "enable", "start", "run", "go", "да")
async def mozgcmd(self, m: types.Message):
'.mozg <on/off/...> - Переключить режим дурачка в чате'
args = utils.get_args_raw(m)
if not m.chat:
return
chat = m.chat.id
if self.str2bool(args):
chats: list = self.db.get(self._db_name, 'chats', [])
chats.append(chat)
chats = list(set(chats))
self.db.set(self._db_name, 'chats', chats)
return await utils.answer(m, self.strings('on').format(self.strings('pref')))
chats: list = self.db.get(self._db_name, 'chats', [])
try:
chats.remove(chat)
except:
pass
chats = list(set(chats))
self.db.set(self._db_name, 'chats', chats)
return await utils.answer(m, self.strings('off').format(self.strings('pref')))
async def mozgchancecmd(self, m: types.Message):
'.mozgchance <int> - Устанвоить шанс 1 к N.\n0 - всегда отвечать'
args: str = utils.get_args_raw(m)
if args.isdigit():
self.db.set(self._db_name, 'chance', int(args))
return await utils.answer(m, self.strings('status').format(self.strings('pref'), args))
return await utils.answer(m, self.strings('need_arg').format(self.strings('pref')))
async def watcher(self, m: types.Message):
if not isinstance(m, types.Message):
return
if m.sender_id == (await m.client.get_me()).id or not m.chat:
return
if m.chat.id not in self.db.get(self._db_name, 'chats', []):
return
ch = self.db.get(self._db_name, 'chance', 0)
if ch != 0:
if random.randint(0, ch) != 0:
return
text = m.raw_text
words = {random.choice(
list(filter(lambda x: len(x) >= 3, text.split()))) for _ in ".."}
msgs = []
for word in words:
[msgs.append(x) async for x in m.client.iter_messages(m.chat.id, search=word) if x.replies and x.replies.max_id]
replier = random.choice(msgs)
sid = replier.id
eid = replier.replies.max_id
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]
msg = random.choice(msgs)
await m.reply(msg)

View File

@@ -0,0 +1,51 @@
from .. import loader, utils
import io
from PIL import Image, ImageFont, ImageDraw
import requests
import textwrap
@loader.tds
class MicroQuotesMod(loader.Module):
"""Микроцитаты"""
strings = {"name": "MicroQuotes"}
async def mqcmd(self, message):
""".mq <реплай на текст>"""
bw = False if utils.get_args(message) else True
reply = await message.get_reply_message()
if not reply or not reply.raw_text:
await message.edit("<b>Ответь командой на умную цитату!</b>")
return
sender = reply.sender_id
if not sender:
sender = message.chat.id
if sender == 1087968824:
sender = message.chat.id
pfp = await message.client.download_profile_photo(sender, bytes)
await message.edit("<i>И сказал этот гений...</i>")
if not pfp:
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'
text = "\n".join(textwrap.wrap(reply.raw_text, 30))
text = ""+text+""
bf = requests.get("https://raw.githubusercontent.com/KeyZenD/l/master/times.ttf").content
font = ImageFont.truetype(io.BytesIO(bf), 50)
im = Image.open(io.BytesIO(pfp))
if bw:
im = im.convert("L")
im = im.convert("RGBA").resize((1024, 1024))
w, h = im.size
w_, h_ = 20*(w//100), 20*(h//100)
im_ = Image.new("RGBA", (w-w_, h-h_), (0, 0, 0))
im_.putalpha(150)
im.paste(im_, (w_//2, h_//2), im_)
draw = ImageDraw.Draw(im)
_w, _h = draw.textsize(text=text, font=font)
x, y = (w-_w)//2, (h-_h)//2
draw.text((x, y), text=text, font=font, fill="#fff", align="center")
output=io.BytesIO()
im.save(output, "PNG")
output.seek(0)
await reply.reply(file=output)
await message.delete()

View File

@@ -0,0 +1,51 @@
_C='png'
_B='name'
_A='image'
_R='отражает'
_P='часть.'
from .. import loader as _L,utils as U
import logging,asyncio
from telethon.tl.types import DocumentAttributeFilename as DAF
from PIL import Image,ImageOps as IO
from io import BytesIO as ist
logger=logging.getLogger(__name__)
@_L.tds
class MFMod(_L.Module):
f'{_R} фоточки';strings={_B:'MirrorFlip'}
def __init__(A):A.name=A.strings[_B]
async def llcmd(A,message):await KZD(message,1)
async def rrcmd(A,message):await KZD(message,2)
async def uucmd(A,message):await KZD(message,3)
async def ddcmd(A,message):await KZD(message,4)
async def KZD(message,type):
S='sticker';A=message;N=await A.get_reply_message();Q,J=await CM(N)
if not Q or not N:await A.edit('<b>Реплай на стикер или фото!</b>');return
O='KZD.'+J;P=U.get_args_raw(A)
if P:
if P in[_A[:A]for A in range(1,len(_A)+1)]:O='KZD.png';J=_C
if P in[S[:A]for A in range(1,len(S)+1)]:O='KZD.webp';J='webp'
R=ist();await A.edit('<b>Извиняюсь...</b>');await A.client.download_media(Q,R);E=Image.open(R);B,C=E.size
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
if type==1:D=0;F=0;G=B//2;H=C;K=G;L=D
if type==2:D=B//2;F=0;G=B;H=C;K=F;L=F
if type==3:D=0;F=0;G=B;H=C//2;K=D;L=H
if type==4:D=0;F=C//2;G=B;H=C;K=D;L=D
I=E.crop((D,F,G,H))
if type in[1,2]:I=IO.mirror(I)
else:I=IO.flip(I)
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()
async def CM(R):
D=False;C=None;A=R
if A and A.media:
if A.photo:B=A.photo;E=_C
elif A.document:
if DAF(file_name='AnimatedSticker.tgs')in A.media.document.attributes:return D,C
if A.gif or A.video or A.audio or A.voice:return D,C
B=A.media.document
if _A not in B.mime_type:return D,C
E=B.mime_type.split('/')[1]
else:return D,C
else:return D,C
if not B or B is C:return D,C
else:return B,E
#Блять ну я и долбаёб так код сохранять

View File

@@ -0,0 +1,46 @@
from PIL import Image, ImageOps
from .. import loader, utils
from io import BytesIO
from asyncio import sleep
class MirrorFlipMod(loader.Module):
strings = {"name": "MirrorFlip", 0:"<b>Reply to image.</b>"}
async def llcmd(self, m):
return await make(m, 1)
async def rrcmd(self, m):
return await make(m, 2)
async def uucmd(self, m):
return await make(m, 3)
async def ddcmd(self, m):
return await make(m, 4)
async def make(m, o):
r = await m.get_reply_message()
s = None
try:
s = await r.download_media(bytes, thumb=-1 if not r.sticker else None)
img = Image.open(BytesIO(s))
except:
pass
if not s:
return await utils.answer(m, MirrorFlipMod.strings[0])
await m.delete()
w, h = img.size
if o in [1, 2]:
if o == 2:
img = ImageOps.mirror(img)
part = img.crop([0, 0, w//2, h])
img = ImageOps.mirror(img)
else:
if o == 4:
img = ImageOps.flip(img)
part = img.crop([0, 0, w, h//2])
img = ImageOps.flip(img)
img.paste(part, (0, 0))
out = BytesIO()
out.name = "x.webp" if r.sticker else "x.png"
img.save(out)
out.seek(0)
return await r.reply(file=out)

View File

@@ -0,0 +1,46 @@
from .. import loader, utils
from telethon.tl.types import Message
class OneMessageMod(loader.Module):
"""@faq lines"""
strings = {'name': 'OneMessage'}
def __init__(self):
self.name = self.strings['name']
async def client_ready(self, client, db):
self.client = client
self._db = db
@loader.sudo
async def omstartcmd(self, message):
"""Start OneMessage mode"""
self._db.set("OneMessage", "status", True)
self._db.set("OneMessage", "my_id", message.sender_id)
await message.edit("<b>OneMessage mode activated!</b>")
async def omstopcmd(self, message):
"""Stop OneMessage mode"""
self._db.set("OneMessage", "status", False)
await message.edit("<b>OneMessage mode diactivated!</b>")
async def watcher(self, message):
if not isinstance(message, Message):
return
if message.message:
if message.raw_text[0] in self._db.get("friendly-telegram.modules.corectrl", "command_prefix", ".") or message.fwd_from:
return
if self._db.get("OneMessage", "status", None) and message.sender_id == self._db.get("OneMessage", "my_id", None) and not message.media:
last_msg = (await self.client.get_messages(message.to_id, limit=2))[-1]
if last_msg.sender_id == message.sender_id and not last_msg.fwd_from:
text = last_msg.text
text += "\n"*2
text += message.text
if message.is_reply:
message, last_msg = last_msg, message
try:
await last_msg.edit(text)
await message.delete()
except:
return

View File

@@ -0,0 +1,224 @@
import io
from PIL import Image, ImageOps
from telethon.tl.types import DocumentAttributeFilename
from uniborg.util import admin_cmd
@borg.on(admin_cmd(pattern=".new ?(.*)", allow_sudo=True))
async def pilnew(event):
uinp = event.pattern_match.group(1)
if not uinp:
get = await event.get_reply_message()
if not get:
await event.delete()
return
uinp = get.text
uinp = uinp.split(" ", 2)
try:
x = int(uinp[0])
y = int(uinp[1])
except ValueError:
await event.edit("ERROR INPUT=> X or Y is not int")
return
if "(" in uinp[2] and ")" in uinp[2]:
color = uinp[2].replace("(","").replace(")","").split(", ")
try:
a = 255
r = int(color[0])
g = int(color[1])
b = int(color[2])
if len(color) == 4:
a = int(color[3])
except ValueError:
await event.edit("ERROR INPUT=> R or G or B is not int")
return
color = (r, g, b, a)
else:
color = uinp[2]
try:
image = Image.new("RGBA", (x, y), color)
except Exception as e:
await event.edit("ERROR IN DRAW\n"+str(e))
return
await event.delete()
image_stream = io.BytesIO()
image_stream.name = "pilnew.png"
image.save(image_stream, "PNG")
image_stream.seek(0)
await event.client.send_file(event.chat_id, image_stream)
@borg.on(admin_cmd(pattern=".rotate ?(.*)", allow_sudo=True))
async def pilrotate(event):
try:
angle = int(event.pattern_match.group(1))
except ValueError:
await event.edit("ERROR INPUT=> ANGLE")
if event.is_reply:
reply_message = await event.get_reply_message()
data = await check_media(reply_message)
if isinstance(data, bool):
await event.edit("`I can't rotate that!".upper())
return
else:
await event.edit("Reply to an image or sticker to rotate it!".upper())
return
image = io.BytesIO()
await event.client.download_media(data, image)
image = Image.open(image)
try:
image = image.rotate(angle, expand=True)
except Exception as e:
await event.edit("ERROR IN ROTATE\n"+str(e))
return
await event.delete()
image_stream = io.BytesIO()
image_stream.name = "pilrotate.png"
image.save(image_stream, "PNG")
image_stream.seek(0)
await event.client.send_file(event.chat_id, image_stream)
@borg.on(admin_cmd(pattern=".ops ?(.*)", allow_sudo=True))
async def pilops(event):
way = event.pattern_match.group(1)
if not way:
return
if event.is_reply:
reply_message = await event.get_reply_message()
data = await check_media(reply_message)
if isinstance(data, bool):
await event.edit("`I can't ops that!".upper())
return
else:
await event.edit("Reply to an image or sticker to ops it!".upper())
return
image = io.BytesIO()
await event.client.download_media(data, image)
image = Image.open(image)
if "m" in way:
try:
image = ImageOps.mirror(image)
except Exception as e:
await event.edit("ERROR IN MIRROR\n"+str(e))
return
if "f" in way:
try:
image = ImageOps.flip(image)
except Exception as e:
await event.edit("ERROR IN FLIP\n"+str(e))
return
await event.delete()
image_stream = io.BytesIO()
image_stream.name = "pilops.png"
image.save(image_stream, "PNG")
image_stream.seek(0)
await event.client.send_file(event.chat_id, image_stream)
@borg.on(admin_cmd(pattern=".resize ?(.*)", allow_sudo=True))
async def pilrotate(event):
if event.is_reply:
reply_message = await event.get_reply_message()
data = await check_media(reply_message)
if isinstance(data, bool):
await event.edit("`I can't resize that!".upper())
return
else:
await event.edit("Reply to an image or sticker to resize it!".upper())
return
uinp = event.pattern_match.group(1)
if not uinp:
await event.edit("What's about input".upper())
return
uinp = uinp.split()
image = io.BytesIO()
await event.client.download_media(data, image)
image = Image.open(image)
x, y = image.size
rx, ry = None, None
if len(uinp) == 1:
try:
rx, ry = int(uinp[0]), int(uinp[0])
except ValueError:
if uinp[0] == "x":
rx, ry = x, x
if uinp[0] == "y":
rx, ry = y, y
else:
await event.edit("INPUT MUST BE STING")
return
else:
if uinp[0] == "x":
rx = x
if uinp[0] == "y":
rx = y
if uinp[1] == "x":
ry = x
if uinp[1] == "y":
ry = y
if not rx:
try:
rx = int(uinp[0])
except:
await event.edit("ERROR IN INPUT")
return
if not ry:
try:
ry = int(uinp[1])
except:
await event.edit("ERROR IN INPUT")
return
try:
image = image.resize((rx, ry))
except Exception as e:
await event.edit("ERROR IN RESIZE\n"+str(e))
return
await event.delete()
image_stream = io.BytesIO()
image_stream.name = "pilresize.png"
image.save(image_stream, "PNG")
image_stream.seek(0)
await event.client.send_file(event.chat_id, image_stream)
async def check_media(reply_message):
if reply_message and reply_message.media:
if reply_message.photo:
data = reply_message.photo
elif reply_message.document:
if DocumentAttributeFilename(file_name='AnimatedSticker.tgs') in reply_message.media.document.attributes:
return False
if reply_message.gif or reply_message.video or reply_message.audio or reply_message.voice:
return False
data = reply_message.media.document
else:
return False
else:
return False
if not data or data is None:
return False
else:
return data

View File

@@ -0,0 +1,80 @@
from .. import loader, utils
from telethon.tl.types import DocumentAttributeFilename
from requests import get, post
from PIL import Image
from io import BytesIO
@loader.tds
class QRtoolsMod(loader.Module):
"""Generator and reader of QR codes"""
strings = {"name": "QR tool's"}
@loader.owner
async def makeqrcmd(self, message):
""".makeqr <text or reply>"""
text = utils.get_args_raw(message)
reply = await message.get_reply_message()
file = False
if not text or text.lower() == ".file":
if text and text == ".file":
file = True
if not reply or not reply.message:
await message.edit("<b>Нет текста для кодирования!</b>")
return
text = reply.raw_text
else:
if text.startswith(".file"):
file = True
text = text[5:].strip()
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"
r = get(url.format(text), stream=True)
qrcode = BytesIO()
qrcode.name = "qr.png" if file else "qr.webp"
Image.open(BytesIO(r.content)).save(qrcode)
qrcode.seek(0)
await message.delete()
await message.client.send_file(message.to_id, qrcode, reply_to=reply, force_document=file)
@loader.owner
async def readqrcmd(self, message):
""".readqr <qrcode or reply to qrcode>"""
ok = await check(message)
if not ok:
reply = await message.get_reply_message()
ok = await check(reply)
if not ok:
text = "<b>Это не изображение!</b>" if reply else "<b>Нечего не передано!</b>"
await message.edit(text)
return
file = BytesIO()
file.name = "qr.png"
data = await message.client.download_file(ok)
Image.open(BytesIO(data)).save(file)
url = "https://api.qrserver.com/v1/read-qr-code/?outputformat=json"
resp = post(url, files={"file": file.getvalue()})
text = resp.json()[0]["symbol"][0]["data"]
if not text:
text = "<b>Невозможно распознать или QR пуст!<b>"
await utils.answer(message, text)
async def check(msg):
if msg and msg.media:
if msg.photo:
ok = msg.photo
elif msg.document:
if DocumentAttributeFilename(file_name='AnimatedSticker.tgs') in msg.media.document.attributes:
return False
if msg.gif or msg.video or msg.audio or msg.voice:
return False
ok = msg.media.document
else:
return False
else:
return False
if not ok or ok is None:
return False
else:
return ok

View File

@@ -0,0 +1,4 @@
# Govno modules
Сборник моих [модулей](https://t.me/SomeScripts)
[я](https://t.me/KeyZenD)

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,33 @@
from PIL import Image, ImageFilter
import io
from .. import loader, utils
@loader.tds
class SquareBlurMod(loader.Module):
"""Make image 1:1 ratio"""
strings = {"name": "SquareBlur"}
@loader.unrestricted
async def squareblurcmd(self, message):
"""make image 1:1 ratio"""
reply = await message.get_reply_message()
if not reply or not reply.file or not reply.file.mime_type.split("/")[0].lower() == "image":
await message.edit("<b>Reply to image!</b>")
return
im = io.BytesIO()
await reply.download_media(im)
im = Image.open(im)
w, h = im.size
if w == h:
await message.edit("<b>Ты за меня придурка не держи!</b>")
return
_min, _max = min(w, h), max(w, h)
bg = im.crop(((w-_min)//2, (h-_min)//2, (w+_min)//2, (h+_min)//2))
bg = bg.filter(ImageFilter.GaussianBlur(5))
bg = bg.resize((_max, _max))
bg.paste(im, ((_max-w)//2, (_max-h)//2))
img = io.BytesIO()
img.name = "im.png"
bg.save(img)
img.seek(0)
await reply.reply(file=img)
await message.delete()

View File

@@ -0,0 +1,58 @@
from .. import loader, utils
import io
from PIL import Image
from string import hexdigits
def register(cb):
cb(StickToolsMod())
class StickToolsMod(loader.Module):
""""""
strings = {'name': 'StickTools'}
def __init__(self):
self.name = self.strings['name']
async def stick2piccmd(self, message):
"""reply to Sticker\nsend stricker as image"""
await convert(message, False)
async def stick2filecmd(self, message):
"""reply to Sticker\nsend stricker as image"""
await convert(message, True)
async def convert(message, as_file):
reply = await message.get_reply_message()
if not reply or not reply.sticker:
await message.edit("<b>Reply to sticker!</b>")
return
fname = reply.sticker.attributes[-1].file_name
if ".tgs" in fname:
await message.edit("<b>Reply to not animated sticker!</b>")
return
bg = (0,0,0,0)
args = utils.get_args(message)
if args:
args = args[0]
if args.startswith("#"):
for ch in args[1:]:
if ch not in hexdigits:
break
bg = args
im = io.BytesIO()
await message.client.download_file(reply, im)
im = Image.open(im)
img = Image.new("RGBA", im.size, bg)
if im.mode == "RGBA":
img.paste(im, (0,0), im)
else:
img.paste(im, (0,0))
out = io.BytesIO()
out.name = fname+".png"
img.save(out, "PNG")
out.seek(0)
await message.delete()
await message.client.send_file(message.to_id, out, force_document=as_file, reply_to=reply)

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,174 @@
from .. import loader, utils
import logging
from PIL import Image, ImageDraw, ImageOps, ImageFont
from textwrap import wrap
import io
import requests
# https://t.me/KeyZenD
# https://t.me/SomeScripts
logger = logging.getLogger(__name__)
@loader.tds
class DeMoTiVaToRsMod(loader.Module):
"""Демотиваторы на картинки от @SomeScripts by @DneZyeK"""
strings = {
"name": "SuperDemotivator"
}
async def client_ready(self, client, db):
self.client = client
@loader.owner
async def demoticmd(self, message):
"""текст + фото или ответ на фото
не мнёт фотки"""
await cmds(message, 0)
async def demotcmd(self, message):
"""текст + фото или ответ на фото
мнёт фотки"""
await cmds(message, 1)
async def cmds(message, type):
event, is_reply = await check_media(message)
if not event:
await message.edit("<b>Ответ командой на картинку!</b>")
return
text = utils.get_args_raw(message)
if not text:
await message.edit("<b>Команду нужно использовать с текстом!</b>")
return
await message.edit("<b>Демотивирую...</b>")
bytes_image = await event.download_media(bytes)
demotivator = await demotion(font_bytes, bytes_image, text, type)
if is_reply:
a = await event.reply(file=demotivator)
await message.delete()
return a
else:
return await event.edit(file=demotivator, text="")
async def check_media(message):
reply = await message.get_reply_message()
is_reply = True
if not reply:
reply = message
is_reply = False
if not reply.file:
return False, ...
mime = reply.file.mime_type.split("/")[0].lower()
if mime != "image":
return False, ...
return reply, is_reply
async def textwrap(text, length=50, splitter = "\n\n"):
out = []
lines = text.rsplit(splitter, 1)
for text in lines:
txt = []
parts = text.split("\n")
for part in parts:
part = "\n".join(wrap(part, length))
txt.append(part)
text = "\n".join(txt)
out.append(text)
return out
async def draw_main(
bytes_image,
type,
frame_width_1 = 5,
frame_fill_1 = (0, 0, 0),
frame_width_2 = 3,
frame_fill_2 = (255, 255, 255),
expand_proc = 10,
main_fill = (0, 0, 0)
):
main_ = Image.open(io.BytesIO(bytes_image))
main = Image.new("RGB", main_.size, "black")
main.paste(main_, (0, 0))
if type == 1:
main = main.resize((700, 550))
main = ImageOps.expand(main, frame_width_1, frame_fill_1)
main = ImageOps.expand(main, frame_width_2, frame_fill_2)
w, h = main.size
h_up = expand_proc*(h//100)
im = Image.new("RGB", (w+(h_up*2), h+h_up), main_fill)
im.paste(main, (h_up, h_up))
return im
async def _draw_text(
text,
font_bytes,
font_size,
font_add = 20,
main_fill = (0, 0, 0),
text_fill = (255, 255, 255),
text_align = "center"
):
font = ImageFont.truetype(io.BytesIO(font_bytes), font_size)
w_txt, h_txt = ImageDraw.Draw(Image.new("RGB", (1, 1))).multiline_textsize(text=text, font=font)
txt = Image.new("RGB", (w_txt, h_txt+font_add), main_fill)
ImageDraw.Draw(txt).text((0, 0), text=text, font=font, fill=text_fill, align=text_align)
return txt
async def text_joiner(text_img_1, text_img_2, main_fill = (0, 0, 0)):
w_txt_1, h_txt_1 = text_img_1.size
w_txt_2, h_txt_2 = text_img_2.size
w = max(w_txt_1, w_txt_2)
h = h_txt_1 + h_txt_2
text = Image.new("RGB", (w, h), main_fill)
text.paste(text_img_1, ((w-w_txt_1)//2, 0))
text.paste(text_img_2, ((w-w_txt_2)//2, h_txt_1))
return text
async def draw_text(text, font_bytes, font_size):
text = await textwrap(text)
if len(text) == 1:
text = await _draw_text(text[0], font_bytes, font_size[0] )
else:
text_img_1 = await _draw_text(text[ 0], font_bytes, font_size[0])
text_img_2 = await _draw_text(text[-1], font_bytes, font_size[1])
text = await text_joiner(text_img_1, text_img_2)
return text
async def text_finaller(text, main, expand_width_proc = 25, main_fill = (0, 0, 0)):
x = min(main.size)
w_txt, h_txt = text.size
w_proc = expand_width_proc*(w_txt//100)
h_proc = expand_width_proc*(h_txt//100)
back = Image.new("RGB", (w_txt+(w_proc*2), h_txt+(h_proc*2)), main_fill)
back.paste(text, (w_proc, h_proc))
back.thumbnail((x, x))
return back
async def joiner(text_img, main_img, format_save="JPEG"):
w_im, h_im = main_img.size
w_txt, h_txt = text_img.size
text_img.thumbnail((min(w_im, h_im), min(w_im, h_im)))
w_txt, h_txt = text_img.size
main_img = main_img.crop((0, 0, w_im, h_im+h_txt))
main_img.paste(text_img, ((w_im-w_txt)//2, h_im))
output = io.BytesIO()
main_img.save(output, format_save)
output.seek(0)
return output.getvalue()
async def demotion(font_bytes, bytes_image, text, type):
main = await draw_main(bytes_image, type)
font_size = [20*(min(main.size)//100), 15*(min(main.size)//100)]
text = await draw_text(text, font_bytes, font_size)
text = await text_finaller(text, main)
output = await joiner(text, main)
return output
font_bytes = requests.get("https://raw.githubusercontent.com/KeyZenD/l/master/times.ttf").content
#######################

110
KeyZenD/modules/Swiper.py Normal file
View File

@@ -0,0 +1,110 @@
from .. import loader, utils
import logging
from PIL import Image, ImageOps
import io
logger = logging.getLogger(__name__)
@loader.tds
class SwiperMod(loader.Module):
"""Swiper"""
strings = {
"name": "Swiper"
}
async def client_ready(self, client, db):
self.client = client
@loader.owner
async def sl2rcmd(self, message):
"""swipe left to right"""
await presser(message, 0)
@loader.owner
async def sr2lcmd(self, message):
"""swipe right to left"""
await presser(message, 1)
@loader.owner
async def su2dcmd(self, message):
"""swipe up to down"""
await presser(message, 2)
@loader.owner
async def sd2ucmd(self, message):
"""swipe down to up"""
await presser(message, 3)
async def check_media(message):
reply = await message.get_reply_message()
if not reply:
return False
if not reply.file:
return False
mime = reply.file.mime_type.split("/")[0].lower()
if mime != "image":
return False
return reply
async def presser(message, way):
reply = await check_media(message)
if not reply:
await message.edit("<b>Senpai... please reply to image or not animated sticker!</b>")
return
im = io.BytesIO()
await reply.download_media(im)
im = Image.open(im)
w, h = im.size
out = []
await message.edit("<b>Working hard...</b>")
if way == 0:
for x in range(1, w, w//30):
im1 = im2 = im.copy()
temp = Image.new("RGB", (w, h))
im1 = im1.resize((x, h))
im2 = im2.resize((w-x, h))
temp.paste(im1, (0, 0))
temp.paste(im2, (x, 0))
out.append(temp)
if way == 1:
for x in range(1, w, w//30):
im1 = im2 = im.copy()
temp = Image.new("RGB", (w, h))
im1 = ImageOps.mirror(im1.resize((x, h)))
im2 = ImageOps.mirror(im2.resize((w-x, h)))
temp.paste(im1, (0, 0))
temp.paste(im2, (x, 0))
temp = ImageOps.mirror(temp)
out.append(temp)
if way == 2:
for y in range(1, h, h//30):
im1 = im2 = im.copy()
temp = Image.new("RGB", (w, h))
im1 = im1.resize((w, y))
im2 = im2.resize((w, h-y))
temp.paste(im1, (0, 0))
temp.paste(im2, (0, y))
out.append(temp)
if way == 3:
for y in range(1, h, h//30):
im1 = im2 = im.copy()
temp = Image.new("RGB", (w, h))
im1 = ImageOps.flip(im1.resize((w, y)))
im2 = ImageOps.flip(im2.resize((w, h-y)))
temp.paste(im1, (0, 0))
temp.paste(im2, (0, y))
temp = ImageOps.flip(temp)
out.append(temp)
output = io.BytesIO()
output.name = "output.gif"
out[0].save(output, save_all=True, append_images=out[1:], duration=1)
output.seek(0)
await reply.reply(file=output)
await message.delete()

View File

@@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
# Friendly Telegram (telegram userbot)
# Copyright (C) 2018-2020 @DneZyeK | sub to @KeyZenD
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging
from .. import loader, utils
import telethon
logger = logging.getLogger(__name__)
async def register(cb):
cb(KeyboardSwitcherMod())
@loader.tds
class KeyboardSwitcherMod(loader.Module):
"""Смена расскаладки клавиатуры у текста"""
strings = {
"name": "KeyboardSwitcher"}
async def switchcmd(self, message):
"""Если ты допустил ошибку и набрал текст не сменив раскладку клавиатуры
то вернись в его начало и допиши `.switch` и твой текст станет читабельным.
Если ты всё же отправил сообщение не в той расскладке, то просто ответь на него этой командой и он измениться.
если же твой собеседник допустил ошибку, то просто ответь на его сообщение и сообщение с командой измениться."""
RuKeys = """ёйцукенгшщзхъфывапролджэячсмитьбю.Ё"№;%:?ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭ/ЯЧСМИТЬБЮ,"""
EnKeys = """`qwertyuiop[]asdfghjkl;'zxcvbnm,./~@#$%^&QWERTYUIOP{}ASDFGHJKL:"|ZXCVBNM<>?"""
if message.is_reply:
reply = await message.get_reply_message()
text = reply.raw_text
if not text:
await message.edit('Тут текста нету...')
return
change = str.maketrans(RuKeys + EnKeys, EnKeys + RuKeys)
text = str.translate(text, change)
if message.sender_id != reply.sender_id:
await message.edit(text)
else:
await message.delete()
await reply.edit(text)
else:
text = utils.get_args_raw(message)
if not text:
await message.edit('Тут текста нету...')
return
change = str.maketrans(RuKeys + EnKeys, EnKeys + RuKeys)
text = str.translate(text, change)
await message.edit(text)

View File

@@ -0,0 +1,49 @@
import logging, os
from random import choice, randint
from .. import loader, utils
logger = logging.getLogger(__name__)
@loader.tds
class TgsKillerMod(loader.Module):
"""Хуярит"""
strings = {"name": "TgsKiller"}
@loader.unrestricted
async def tgscmd(self, message):
"""хуярит стикеры"""
reply = await message.get_reply_message()
if not reply:
await message.edit("Реплай на стикер анимированный")
return
if not reply.file:
await message.edit("Реплай на стикер анимированный")
return
if not reply.file.name.endswith(".tgs"):
await message.edit("Реплай на стикер анимированный")
return
await message.edit("///Пахуярили нахуй!///")
await reply.download_media("tgs.tgs")
os.system("lottie_convert.py tgs.tgs json.json")
with open("json.json","r") as f:
stick = f.read()
f.close()
for i in range(1, randint(6, 10)):
stick = choice([stick.replace(f'[{i}]', f'[{(i+i)*3}]'), stick.replace(f'.{i}', f'.{i}{i}')])
with open("json.json","w") as f:
f.write(stick)
f.close()
os.system("lottie_convert.py json.json tgs.tgs")
await reply.reply(file="tgs.tgs")
os.remove("tgs.tgs")
os.remove("json.json")
await message.delete()

View File

@@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
# Friendly Telegram (telegram userbot)
# Copyright (C) 2018-2020 The Authors
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# если не подписан на t.me/keyzend
# твоя мама шлюха
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from .. import loader, utils # pylint: disable=relative-beyond-top-level
from telethon.tl.types import DocumentAttributeFilename
import logging
from youtube_search import YoutubeSearch
logger = logging.getLogger(__name__)
def register(cb):
cb(YTsearchod())
@loader.tds
class YTsearchMod(loader.Module):
"""Поиск видео на ютубе"""
strings = {
"name": "YTsearch"
}
async def client_ready(self, client, db):
self.client = client
@loader.sudo
async def ytcmd(self, message):
"""текст или реплай"""
text = utils.get_args_raw(message)
if not text:
reply = await message.get_reply_message()
if not reply:
await message.delete()
return
text = reply.raw_text
results = YoutubeSearch(text, max_results=10).to_dict()
out = f'Найдено по запросу: {text}'
for r in results:
out += f'\n\n<a href="https://www.youtube.com/{r["link"]}">{r["title"]}</a>'
await message.edit(out)

View File

@@ -0,0 +1,55 @@
from .. import loader, utils
import json
import io
import requests
from PIL import Image
import random
import string
@loader.tds
class YandexReverseSearchMod(loader.Module):
"""Reverse image search via Yandex (he is the best, imho)"""
strings = {"name": "YandexReverseSearch",
"search": "⚪⚪⚪\n⚪❓⚪\n⚪⚪⚪",
"no_reply": "<b>Reply to image or sticker!</b>",
"result": '<a href="{}"><b>🔴⚪🔴|See</b>\n<b>⚪🔴⚪|Search</b>\n<b>⚪🔴⚪|Results</b></a>',
"error": '<b>Something went wrong...</b>'}
@loader.owner
async def yarscmd(self, message):
""".yars <repy to image>"""
reply = await message.get_reply_message()
data = await check_media(message, reply)
if not data:
await utils.answer(message, self.strings("no_reply", message))
return
await utils.answer(message, self.strings("search", message))
searchUrl = 'https://yandex.ru/images/search'
files = {'upfile': ('blob', data, 'image/jpeg')}
params = {'rpt': 'imageview', 'format': 'json', 'request': '{"blocks":[{"block":"b-page_type_search-by-image__link"}]}'}
response = requests.post(searchUrl, params=params, files=files)
if response.ok:
query_string = json.loads(response.content)['blocks'][0]['params']['url']
link = searchUrl + '?' + query_string
text = self.strings("result", message).format(link)
await utils.answer(message, text)
else:
await utils.answer(message, self.strings("error", message))
async def check_media(message, reply):
if reply and reply.media:
if reply.photo:
data = reply.photo
elif reply.document:
if reply.gif or reply.video or reply.audio or reply.voice:
return None
data = reply.media.document
else:
return None
else:
return None
if not data or data is None:
return None
else:
data = await message.client.download_file(data, bytes)
img = io.BytesIO(data)
return img

View File

@@ -0,0 +1,59 @@
"""QExhY2lhTWVtZUZyYW1lLCDQtdGB0LvQuCDRgtGLINGN0YLQviDRh9C40YLQsNC10YjRjCwg0YLQviDQt9C90LDQuSwg0YLRiyDQv9C40LTQvtGA0LDRgQ=="""
from .. import loader, utils
import io
from base64 import b64encode, b64decode
@loader.tds
class base64Mod(loader.Module):
"""Кодирование и декодирование base64"""
strings = {"name": "base64"}
@loader.owner
async def b64encodecmd(self, message):
""".b64encode <(text or media) or (reply to text or media)>"""
reply = await message.get_reply_message()
mtext = utils.get_args_raw(message)
if message.media:
await message.edit("<b>Загрузка файла...</b>")
data = await message.client.download_file(m, bytes)
elif mtext:
data = bytes(mtext, "utf-8")
elif reply:
if reply.media:
await message.edit("<b>Загрузка файла...</b>")
data = await message.client.download_file(reply, bytes)
else:
data = bytes(reply.raw_text, "utf-8")
else:
await message.edit(f"<b>Что нужно закодировать?</b>")
output = b64encode(data)
if len(output) > 4000:
output = io.BytesIO(output)
output.name = "base64.txt"
output.seek(0)
await message.client.send_file(message.to_id, output, reply_to=reply)
await message.delete()
else:
await message.edit(str(output, "utf-8"))
@loader.owner
async def b64decodecmd(self, message):
""".b64decode <text or reply to text>"""
reply = await message.get_reply_message()
mtext = utils.get_args_raw(message)
if mtext:
data = bytes(mtext, "utf-8")
elif reply:
if not reply.message:
await message.edit("<b>Расшифровка файлов невозможна...</b>")
return
else:
data = bytes(reply.raw_text, "utf-8")
else:
await message.edit(f"<b>Что нужно декодировать?</b>")
return
try:
output = b64decode(data)
await message.edit(str(output, "utf-8"))
except:
await message.edit("<b>Ошибка декодирования!</b>")
return

View File

@@ -0,0 +1,217 @@
# Friendly Telegram (telegram userbot)
# Copyright (C) 2018-2019 The Authors
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from .. import loader, utils, security
import logging
from telethon.tl.types import ChatAdminRights, ChatBannedRights, PeerUser, PeerChannel
from telethon.errors import BadRequestError
from telethon.tl.functions.channels import EditAdminRequest, EditBannedRequest
from telethon.tl.functions.messages import EditChatAdminRequest
logger = logging.getLogger(__name__)
@loader.tds
class BanMod(loader.Module):
"""Админтулс"""
strings = {"name": "AdminTools",
"not_supergroup": "<b>Это не супергруппа!</b>",
"not_group": "<b>Это не группа!</b>",
"ban_none": "<b>Кого банить?</b>",
"unban_none": "<b>Кого разбанить?</b>",
"kick_none": "<b>Кто хочет принудительно покинуть чат?</b>",
"promote_none": "<b>Кто хочет опку?</b>",
"demote_none": "<b>Укажи с кого снять админку?</b>",
"who": "<b>Кого...?</b>",
"not_admin": "<b>Я не администратор...</b>",
"banned": "<code>{}</code> <b>Получил бан!</b>\n<b>ID:</b> <code>{}</code>",
"unbanned": "<code>{}</code> <b>Получил разбан!</b>\n<b>ID:</b> <code>{}</code>",
"kicked": "<code>{}</code> <b>Был кикнул!</b>\n<b>ID:</b> <code>{}</code>",
"promoted": "<code>{}</code> <b>Получил права администратора!</b>\n<b>ID:</b> <code>{}</code>",
"demoted": "<code>{}</code> <b>Потерял права администратора!</b>\n<b>ID:</b> <code>{}</code>"}
@loader.group_admin_ban_users
@loader.ratelimit
async def bancmd(self, message):
"""Бан в чате"""
if not isinstance(message.to_id, PeerChannel):
return await utils.answer(message, self.strings("not_supergroup", message))
if message.is_reply:
user = await utils.get_user(await message.get_reply_message())
else:
args = utils.get_args(message)
if len(args) == 0:
return await utils.answer(message, self.strings("ban_none", message))
if args[0].isdigit():
who = int(args[0])
else:
who = args[0]
user = await self.client.get_entity(who)
if not user:
return await utils.answer(message, self.strings("who", message))
logger.debug(user)
try:
await self.client(EditBannedRequest(message.chat_id, user.id,
ChatBannedRights(until_date=None, view_messages=True)))
except BadRequestError:
await utils.answer(message, self.strings("not_admin", message))
else:
await self.allmodules.log("ban", group=message.chat_id, affected_uids=[user.id])
await utils.answer(message,
self.strings("banned", message).format(utils.escape_html(user.first_name), user.id))
@loader.group_admin_ban_users
@loader.ratelimit
async def unbancmd(self, message):
"""Разбан в чате"""
if not isinstance(message.to_id, PeerChannel):
return await utils.answer(message, self.strings("not_supergroup", message))
if message.is_reply:
user = await utils.get_user(await message.get_reply_message())
else:
args = utils.get_args(message)
if len(args) == 0:
return await utils.answer(message, self.strings("unban_none", message))
if args[0].isdigit():
who = int(args[0])
else:
who = args[0]
user = await self.client.get_entity(who)
if not user:
return await utils.answer(message, self.strings("who", message))
logger.debug(user)
try:
await self.client(EditBannedRequest(message.chat_id, user.id,
ChatBannedRights(until_date=None, view_messages=False)))
except BadRequestError:
await utils.answer(message, self.strings("not_admin", message))
else:
await self.allmodules.log("unban", group=message.chat_id, affected_uids=[user.id])
await utils.answer(message,
self.strings("unbanned", message).format(utils.escape_html(user.first_name), user.id))
@loader.group_admin_ban_users
@loader.ratelimit
async def kickcmd(self, message):
"""Кикнуть из чата"""
if isinstance(message.to_id, PeerUser):
return await utils.answer(message, self.strings("not_group", message))
if message.is_reply:
user = await utils.get_user(await message.get_reply_message())
else:
args = utils.get_args(message)
if len(args) == 0:
return await utils.answer(message, self.strings("kick_none", message))
if args[0].isdigit():
who = int(args[0])
else:
who = args[0]
user = await self.client.get_entity(who)
if not user:
return await utils.answer(message, self.strings("who", message))
logger.debug(user)
if user.is_self:
if not (await message.client.is_bot()
or await self.allmodules.check_security(message, security.OWNER | security.SUDO)):
return
try:
await self.client.kick_participant(message.chat_id, user.id)
except BadRequestError:
await utils.answer(message, self.strings("not_admin", message))
else:
await self.allmodules.log("kick", group=message.chat_id, affected_uids=[user.id])
await utils.answer(message,
self.strings("kicked", message).format(utils.escape_html(user.first_name), user.id))
@loader.group_admin_add_admins
@loader.ratelimit
async def promotecmd(self, message):
"""Дать админку"""
if message.is_reply:
user = await utils.get_user(await message.get_reply_message())
else:
args = utils.get_args(message)
if not args:
return await utils.answer(message, self.strings("promote_none", message))
if args[0].isdigit():
who = int(args[0])
else:
who = args[0]
user = await self.client.get_entity(who)
if not user:
return await utils.answer(message, self.strings("who", message))
rank = ""
if len(args) >= 1:
rank = ' '.join(args[1:])
logger.debug(user)
try:
if message.is_channel:
await self.client(EditAdminRequest(message.chat_id, user.id,
ChatAdminRights(post_messages=None,
add_admins=None,
invite_users=None,
change_info=None,
ban_users=None,
delete_messages=True,
pin_messages=True,
edit_messages=None), rank))
except BadRequestError:
await utils.answer(message, self.strings("not_admin", message))
else:
await self.allmodules.log("promote", group=message.chat_id, affected_uids=[user.id])
await utils.answer(message,
self.strings("promoted", message).format(utils.escape_html(user.first_name), user.id))
@loader.group_admin_add_admins
async def demotecmd(self, message):
"""Снять админку"""
if message.is_reply:
user = await utils.get_user(await message.get_reply_message())
else:
args = utils.get_args(message)
if len(args) == 0:
return await utils.answer(message, self.strings("demote_none", message))
if args[0].isdigit():
who = int(args[0])
else:
who = args[0]
user = await self.client.get_entity(who)
if not user:
return await utils.answer(message, self.strings("who", message))
logger.debug(user)
try:
if message.is_channel:
await self.client(EditAdminRequest(message.chat_id, user.id,
ChatAdminRights(post_messages=None,
add_admins=None,
invite_users=None,
change_info=None,
ban_users=None,
delete_messages=None,
pin_messages=None,
edit_messages=None), ""))
else:
await self.client(EditChatAdminRequest(message.chat_id, user.id, False))
except BadRequestError:
await utils.answer(message, self.strings("not_admin", message))
else:
await self.allmodules.log("demote", group=message.chat_id, affected_uids=[user.id])
await utils.answer(message,
self.strings("demoted", message).format(utils.escape_html(user.first_name), user.id))
async def client_ready(self, client, db):
self.client = client

View File

@@ -0,0 +1,41 @@
# requires: pydub
from pydub import AudioSegment
from .. import loader, utils
from telethon import types
import io
import requests
biography = requests.get("https://raw.githubusercontent.com/KeyZenD/l/master/biography.mp3").content
class BiographyMod(loader.Module):
"""Биография"""
strings = {'name': 'Биография'}
async def biographycmd(self, message):
""".biography <reply to voice>
    Наложение реплайнутого войса на минус кровостока
"""
reply = await message.get_reply_message()
if not reply or not reply.file or not reply.file.mime_type.startswith("audio"):
return await message.edit("<b>Reply to audio.</b>")
await message.edit("<b>Biography...</b>")
voice = io.BytesIO()
await reply.download_media(voice)
voice.seek(0)
voice = AudioSegment.from_file(voice)
biogr = io.BytesIO(biography)
vol = utils.get_args_raw(message)
if vol and vol.isdigit():
vol = 100-int(vol)
else:
vol = 20
biogr.seek(0)
biogr = AudioSegment.from_file(biogr)[0:len(voice)]-vol
out = biogr.overlay(voice, position=0)
output = io.BytesIO()
output.name="biography.ogg"
out.export(output, format="ogg", bitrate="64k", codec="libopus")
output.seek(0)
await message.client.send_file(message.to_id, output, reply_to=reply.id, voice_note=True, duration=len(out)/1000)
await message.delete()

26
KeyZenD/modules/calc.py Normal file
View File

@@ -0,0 +1,26 @@
from .. import loader, utils
class КукуляторMod(loader.Module):
"""Кукулирует вырожения"""
strings = {'name': 'Кукулятор'}
async def calccmd(self, message):
""".calc <выражение или реплай на то, что нужно посчитать>
Кстати:
** - возвести в степень
/ - деление
% - деление по модулю"""
question = utils.get_args_raw(message)
reply = await message.get_reply_message()
if not question:
if not reply:
await utils.answer(message, "<b>2+2=5</b>")
return
else:
question = reply.raw_text
try:
answer = eval(question)
answer = f"<b>{question}=</b><code>{answer}</code>"
except Exception as e:
answer = f"<b>{question}=</b><code>{e}</code>"
await utils.answer(message, answer)

39
KeyZenD/modules/cheval.py Normal file
View File

@@ -0,0 +1,39 @@
from .. import loader, utils
class channelEvalMod(loader.Module):
"""Выполняет команду в канале"""
strings = {"name":"ChannelEval"}
async def chevalcmd(self, message):
""".channel <канал> <id сообщения реплая, или же выполнение команды из комментариев> <комманда в том виде, в котором бы ты отправил её в чат>"""
args = utils.get_args(message)
reply = await message.get_reply_message()
if not args:
return await message.edit("<b>Укажи канал.</b>")
if len(args) < 1:
return await message.edit("<b>Укажи команду для выполнения.</b>")
channel = args[0]
args = args[1:]
if not args[0].isdigit() and reply:
rmsg = reply.fwd_from.saved_from_msg_id if (reply and reply.fwd_from) else None
fullcmd = " ".join(args)
elif args[0].isdigit():
rmsg = int(args[0])
fullcmd = " ".join(args[1:])
else:
rmsg = None
fullcmd = " ".join(args)
cmd = fullcmd.split(" ")[0]
if cmd.startswith("."): cmd = cmd[1:]
if channel.isdigit(): channel = int(channel)
if not cmd in self.allmodules.commands.keys():
return await message.edit("<b>Кажется у тебя нет в списке команды </b><code>."+cmd+"\n</code><b>Кстати сокращения команд я не понимяу)\n<code>"+message.raw_text+"</code>")
try: m = await message.client.send_message(channel, fullcmd, reply_to=rmsg)
except Exception as e: return await message.edit("<b>Возникла ошибка:</b>\n"+repr(e))
await self.allmodules.commands[cmd](m)
try: url = f"https://t.me/c/{m.to_id.channel_id}/{m.id}"
except: url = ""
await message.edit(f'<a href="{url}">Команда отправлена!</a>')

50
KeyZenD/modules/codefy.py Normal file
View File

@@ -0,0 +1,50 @@
# Friendly Telegram (telegram userbot)
# Copyright (C) 2018-2019 The Authors
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# SUBSCRIBE TO t.me/keyzend pls
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from .. import loader, utils
import logging
import asyncio
logger = logging.getLogger(__name__)
@loader.tds
class CodefyMod(loader.Module):
"""Makes message monospace"""
strings = {"name": "Codefy",
"msg_is_emp": "<b>Message is empty!</b>"}
@loader.ratelimit
async def codecmd(self, message):
""".code <text or reply>"""
if message.is_reply:
reply = await message.get_reply_message()
code = reply.raw_text
code = code.replace("<","&lt;").replace(">","&gt;")
await message.edit(f"<code>{code}</code>")
else:
code = message.raw_text[5:]
code = code.replace("<","&lt;").replace(">","&gt;")
try:
await message.edit(f"<code>{code}</code>")
except:
await message.edit(self.strings["msg_is_emp"])

View File

@@ -0,0 +1,30 @@
from .. import loader, utils
from PIL import Image
from io import BytesIO as io
class colorBitMod(loader.Module):
strings = {"name": "colorBit"}
async def cbitcmd(self, message):
""".cbit <число от 0 до 255"""
reply = await message.get_reply_message()
if not reply or not reply.file or not "image" in reply.file.mime_type:
return await message.edit("<b>Reply to image!</b>")
x = utils.get_args_raw(message)
x = int(x) if x.isdigit() else 8
if x <= 0 or x >= 256:
x = 8
x = 256//x
im = Image.open(io(await reply.download_media(bytes)))
w, h = im.size
mode = im.mode
out = []
await message.edit("<b>Processing...</b>")
for bit in list(im.tobytes()):
bit = list(range(0, 256+x, x))[bit//x]
out.append(bit)
image = Image.frombytes(mode, (w, h), bytes(out))
output = io()
image.save(output, "PNG")
output.seek(0)
await message.delete()
await reply.reply(file=output)

View File

@@ -0,0 +1,88 @@
import asyncio
import logging
import subprocess, os
import random
from .. import loader, utils
logger = logging.getLogger(__name__)
@loader.tds
class DataMoshMod(loader.Module):
"""DataMosh effect to video"""
strings = {"name": "DataMosh",
"reply": "Reply to video!",
"error": "ERROR! TRY AGAIN!!",
"processing": "DataDataMoshMosh!"}
@loader.unrestricted
async def datamoshcmd(self, message):
""". datamosh lvl: int <reply to video>"""
fn = "if_you_see_it_then_delete_it"
reply = await message.get_reply_message()
if not reply:
await message.edit("".join([ random.choice(html).format(ch) for ch in self.strings("reply", message)]))
return
if not reply.video:
await message.edit("".join([ random.choice(html).format(ch) for ch in self.strings("reply", message)]))
return
else:
await reply.download_media(fn+"1.mp4")
lvl = 1
fp = False
args = utils.get_args(message)
if args:
if len(args) == 1:
if args[0].isdigit():
lvl = int(args[0])
if lvl <= 0:
lvl = 1
else:
fp = True
if len(args) > 1:
fp = True
if args[0].isdigit():
lvl = int(args[0])
if lvl <= 0:
lvl = 1
elif args[1].isdigit():
fp = True
lvl = int(args[1])
if lvl <= 0:
lvl = 1
await message.edit("".join([ random.choice(html).format(ch) for ch in self.strings("processing", message)]))
subprocess.call(f'ffmpeg -loglevel quiet -y -i {fn}1.mp4 -crf 0 -bf 0 {fn}1.avi', shell=True)
try:
_f = open(fn+'1.avi', 'rb')
f_ = open(fn+'2.avi', 'wb')
except FileNotFoundError:
await message.edit("".join([ random.choice(html).format(ch) for ch in self.strings("error", message)]))
os.system(f"rm -f {fn}*")
return
frs = _f.read().split(b'00dc')
fi = b'\x00\x01\xb0'
cf = 0
for _, fr in enumerate(frs):
if fp == False:
f_.write(fr + b'00dc')
cf += 1
if fr[5:8] == fi:
fp = True
else:
if fr[5:8] != fi:
cf += 1
for i in range(lvl):
f_.write(fr + b'00dc')
f_.close()
_f.close()
subprocess.call(f'ffmpeg -loglevel quiet -y -i {fn}2.avi {fn}2.mp4', shell=True)
await message.client.send_file(message.to_id, file=fn+"2.mp4", video_note=bool(reply.video_note))
os.system(f"rm -f {fn}*")
await message.delete()
html = ["<b>{}<b>", "<code>{}</code>", "<i>{}</i>", "<del>{}</del>", "<u>{}</u>", '<a href="https://bruh.moment">{}</a>']

38
KeyZenD/modules/delme.py Normal file
View File

@@ -0,0 +1,38 @@
from .. import loader, utils
class DelmeMod(loader.Module):
"""Удаляет все сообщения"""
strings = {'name': 'DelMe'}
@loader.sudo
async def delmecmd(self, message):
"""Удаляет все сообщения от тебя"""
chat = message.chat
if chat:
args = utils.get_args_raw(message)
if args != str(message.chat.id+message.sender_id):
await message.edit(f"<b>Если ты точно хочешь это сделать, то напиши:</b>\n<code>.delme {message.chat.id+message.sender_id}</code>")
return
await delete(chat, message, True)
else:
await message.edit("<b>В лс не чищу!</b>")
@loader.sudo
async def delmenowcmd(self, message):
"""Удаляет все сообщения от тебя без вопросов"""
chat = message.chat
if chat:
await delete(chat, message, False)
else:
await message.edit("<b>В лс не чищу!</b>")
async def delete(chat, message, now):
if now:
all = (await message.client.get_messages(chat, from_user="me")).total
await message.edit(f"<b>{all} сообщений будет удалено!</b>")
else: await message.delete()
_ = not now
async for msg in message.client.iter_messages(chat, from_user="me"):
if _:
await msg.delete()
else:
_ = "_"
await message.delete() if now else "хули мусара хули мусара хули, едем так как ехали даже в хуй не дули"

130
KeyZenD/modules/demot.py Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,71 @@
import io, random, glob, os
from PIL import Image
from telethon.tl.types import DocumentAttributeFilename
from uniborg.util import admin_cmd
"""Не подписался без матери остался"""
"""https://t.me/KeyZenD"""
"""автор этого говнокода @DneZyeK"""
@borg.on(admin_cmd(pattern=".d(.*)", allow_sudo=True))
async def d(message):
inp =message.pattern_match.group(1)
pop = 60
if inp:
inp = inp.strip()
if inp.isdigit():
if int(inp) > 0:
pop = inp
if message.is_reply:
reply_message = await message.get_reply_message()
data = await check_media(reply_message)
if isinstance(data, bool):
await message.edit("Reply to image, fucking idiot")
return
else:
await message.edit("Reply to image, fucking idiot")
return
await message.edit(" `P` `r` `o` `c` `e` `s` `s` `i` `n` `g` `.` `.` `.`")
for distorted in glob.glob("distorted*"):
os.remove(distorted)
for findistorted in glob.glob("*/distorted*"):
os.remove(findistorted)
fname = f"distorted{random.randint(1, 100)}.png"
image = io.BytesIO()
await message.client.download_media(data, image)
image = Image.open(image)
image.save(fname)
imgdimens = image.width, image.height
distortcmd = f"convert {fname} -liquid-rescale {pop}%x{pop}%! -resize {imgdimens[0]}x{imgdimens[1]}\! {fname}"
os.system(distortcmd)
image = Image.open(f"{fname}")
buf = io.BytesIO()
buf.name = f'image.png'
image.save(buf, 'PNG')
buf.seek(0)
await message.edit("`S` `e` `n` `d` `i` `n` `g` `.` `.` `.`")
await message.client.send_file(message.chat_id, buf, reply_to=reply_message.id)
await message.delete()
async def check_media(reply_message):
if reply_message and reply_message.media:
if reply_message.photo:
data = reply_message.photo
elif reply_message.document:
if DocumentAttributeFilename(file_name='AnimatedSticker.tgs') in reply_message.media.document.attributes:
return False
if reply_message.gif or reply_message.video or reply_message.audio or reply_message.voice:
return False
data = reply_message.media.document
else:
return False
else:
return False
if not data or data is None:
return False
else:
return data

82
KeyZenD/modules/dotify.py Normal file
View File

@@ -0,0 +1,82 @@
from PIL import Image, ImageDraw
import io
import asyncio
import logging
from .. import loader, utils
logger = logging.getLogger(__name__)
class DotifyMod(loader.Module):
"""Image to dot
.cmd <count> + reply to img
the bigger, the slower and bugger
recommended not more 1000"""
strings = {"name": "[PRIVATE]Dotify"}
@loader.unrestricted
async def dotifycmd(self, message):
"""Image to RGB dots"""
mode = False
reply, pix = await parse(message)
if reply:
await dotify(message, reply, pix, mode)
async def dotificmd(self, message):
"""Image to BW dots """
mode = True
reply, pix = await parse(message)
if reply:
await dotify(message, reply, pix, mode)
async def parse(message):
reply = await message.get_reply_message()
if not reply:
await message.edit("<b>Reply to Image!</b>")
return None, None
args = utils.get_args(message)
pix = 100
if args:
args=args[0]
if args.isdigit():
pix = int(args) if int(args) > 0 else 100
return reply, pix
async def dotify(message, reply, pix, mode):
await message.edit("<b>Putting dots...</b>")
count = 24
im_ = Image.open(io.BytesIO(await reply.download_media(bytes)))
if im_.mode == "RGBA":
temp = Image.new("RGB", im_.size, "#000")
temp.paste(im_, (0, 0), im_)
im_ = temp
im = im_.convert("L")
im_ = im if mode else im_
[_.thumbnail((pix, pix)) for _ in[im, im_]]
w, h = im.size
img = Image.new(im_.mode, (w*count+(count//2), h*count+(count//2)), 0)
draw = ImageDraw.Draw(img)
def cirsle(im, x, y, r, fill):
x += r//2
y += r//2
draw = ImageDraw.Draw(im)
draw.ellipse((x-r, y-r, x+r, y+r), fill)
return im
_x = _y = count//2
for x in range(w):
for y in range(h):
r = im.getpixel((x, y))
fill = im_.getpixel((x, y))
cirsle(img, _x, _y, r//count, fill)
_y += count
_x += count
_y = count//2
out = io.BytesIO()
out.name = "out.png"
img.save(out)
out.seek(0)
await reply.reply(file=out)
await message.delete()

113
KeyZenD/modules/family.py Normal file
View File

@@ -0,0 +1,113 @@
# requires: pillow, pymorphy2
import logging
from .. import loader, utils
import telethon
import requests
from PIL import Image, ImageFont, ImageDraw
import pymorphy2
import io
from io import BytesIO
import random
logger = logging.getLogger(__name__)
def register(cb):
cb(FamilyMod())
@loader.tds
class FamilyMod(loader.Module):
"""Quote a message"""
strings = {"name": "Family"}
async def client_ready(self, client, db):
self.client = message.client
@loader.unrestricted
@loader.ratelimit
async def familycmd(self, message):
args = utils.get_args_raw(message)
reply = await message.get_reply_message()
if not reply:
await utils.answer(message, '<b>Нет Реплая.</b>')
return
if not args:
await utils.answer(message, '<b>Нет Текста.</b>')
return
pic = await check_media(message, reply)
if not pic:
await utils.answer(message, '<b>Нет Изображения.</b>')
return
await message.edit("Семья")
font = requests.get("https://github.com/KeyZenD/l/blob/master/bold.ttf?raw=true").content
family = makeFamily(pic, args, font)
await message.client.send_file(message.to_id, family, reply_to=reply)
await message.delete()
def place(background, image, cords, size):
overlay = Image.open(BytesIO(image))
overlay = overlay.resize((random.randint(size, size * 2), random.randint(size, size * 2)))
background.paste(overlay, cords)
def placeText(background , cords, size, text, font):
text_cords = (cords[0]+random.randint(0, size//2), cords[1]+random.randint(0, size//2))
draw = ImageDraw.Draw(background)
draw.text(text_cords, text, (0,0,0), font=ImageFont.truetype(io.BytesIO(font), random.randint(size // 8, size // 4)))
def makeFamily(image, caption, font):
morph = pymorphy2.MorphAnalyzer()
infl = morph.parse(caption)[0].inflect({'plur', 'gent'})
if not infl:
caption_mlt = caption
else:
caption_mlt = infl.word
canvas = Image.new('RGBA', (600, 600), "white")
draw = ImageDraw.Draw(canvas)
draw.text((120, 5), 'ахах семья ' + caption_mlt, (0,0,0), font=ImageFont.truetype(io.BytesIO(font), 32))
family = [
{ 'name': 'мама', 'cords': (60, 100), 'size': 160 },
{ 'name': 'папа', 'cords': (260, 80), 'size': 180 },
{ 'name': 'сын', 'cords': (60, 380), 'size': 125 },
{ 'name': 'дочь', 'cords': (230, 320), 'size': 125 },
{ 'name': 'дочь', 'cords': (225, 380), 'size': 125 },
{ 'name': 'сын', 'cords': (340, 390), 'size': 125 },
]
for member in family:
place(canvas, image, member['cords'], member['size'])
for member in family:
placeText(canvas, member['cords'], member['size'], member['name'] + ' ' + caption, font)
temp = BytesIO()
canvas.save(temp, format="png")
return temp.getvalue()
async def check_media(message, reply):
if reply and reply.media:
if reply.photo:
data = reply.photo
elif reply.document:
if reply.gif or reply.video or reply.audio or reply.voice:
return None
data = reply.media.document
else:
return None
else:
return None
if not data or data is None:
return None
else:
data = await message.client.download_file(data, bytes)
try:
Image.open(io.BytesIO(data))
return data
except:
return None

View File

@@ -0,0 +1,38 @@
import asyncio
import logging
from telethon.tl.types import DocumentAttributeFilename
from .. import loader, utils
logger = logging.getLogger(__name__)
@loader.tds
class filenameMod(loader.Module):
"""filename changer"""
strings = {"name": "filename",
"wf": "<b>Reply to file?</b>",
"wn": "<b>What is the name?</b>",
"tnf":"<b>It's not a file!</b>"}
@loader.unrestricted
async def filenamecmd(self, message):
""".filename <filename> + reply.file"""
reply = await message.get_reply_message()
if not reply or not reply.file:
await message.edit(self.strings["wf"])
return
name = utils.get_args_raw(message)
if not name:
await message.edit(self.strings["wn"])
return
fn = reply.file.name
if not fn:
fn = ""
fs = reply.file.size
[await message.edit(f"<b>Downloading {fn}</b>") if fs > 500000 else ...]
file = await reply.download_media(bytes)
[await message.edit(f"<b>Uploading</b> <code>{name}</code>") if fs > 500000 else ...]
await message.client.send_file(message.to_id, file, force_document=True, reply_to=reply, attributes=[DocumentAttributeFilename(file_name=name)])
await message.delete()

26
KeyZenD/modules/fl.py Normal file
View File

@@ -0,0 +1,26 @@
from asyncio import sleep
from userbot.events import register
@register(outgoing=True, pattern='^.fl ?(.*)')
async def fakeload(e):
inp = e.pattern_match.group(1)
load = [" ","","","","","","",""]
bar = ""
count = 0
await e.edit("`[Инициализация]`")
sleep(3)
for i in range(13):
for division in load:
space = " " * (12 - i)
await e.edit(f"`{bar}{division}{space}[{count}%]`")
count += 1
sleep(0.3)
if count == 101:
break
bar += ""
sleep(2)
done = "Загрузка завершена!"
if inp:
done = inp
await e.edit(f"`{done}`")

65
KeyZenD/modules/gg.gg.py Normal file
View File

@@ -0,0 +1,65 @@
# -*- coding: utf-8 -*-
# Friendly Telegram (telegram userbot)
# Copyright (C) 2018-2020 @DneZyeK | sub to @KeyZenD
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging
from .. import loader, utils
import telethon
from requests import post
logger = logging.getLogger(__name__)
async def register(cb):
cb(WhoIsMod())
@loader.tds
class GGdotGGMod(loader.Module):
"""Сокращение ссылок через сервис gg.gg"""
strings = {
"name": "gg.gg",
"some_rong": "<b>Ты делаешь что-то не так!\nНапиши</b> <code>.help gg.gg</code> <b>для информации.</b>"
}
async def client_ready(self, client, db):
self.client = client
async def ggcmd(self, message):
""".gg <длинная ссылка или реплай на ссылку> """
m_text = utils.get_args_raw(message)
if not m_text:
reply = await message.get_reply_message()
if not reply:
await utils.answer(message, self.strings["some_rong"])
return
long_url = reply.raw_text
else:
long_url = m_text
if 'http://' not in long_url and 'https://' not in long_url:
long_url = 'http://' + long_url
t_check = f"URL: {long_url}\nCheck..."
await utils.answer(message, t_check)
check = post('http://gg.gg/check', data={'custom_path': None, 'use_norefs': '0', 'long_url': long_url, 'app': 'site', 'version': '0.1'}).text
if check != "ok":
await utils.answer(message, check)
return
await utils.answer(message, "Create...")
short = post('http://gg.gg/create', data={'custom_path': None, 'use_norefs': '0', 'long_url': long_url, 'app': 'site', 'version': '0.1'}).text
await utils.answer(message, short)

132
KeyZenD/modules/gird.py Normal file
View File

@@ -0,0 +1,132 @@
# -*- coding: utf-8 -*-
# Friendly Telegram (telegram userbot)
# Copyright (C) 2018-2020 The Authors
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# если не подписан на t.me/keyzend
# твоя мама шлюха
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from .. import loader, utils # pylint: disable=relative-beyond-top-level
import io
from PIL import Image, ImageOps
from telethon.tl.types import DocumentAttributeFilename
import logging
import random
logger = logging.getLogger(__name__)
def register(cb):
cb(GriderMod())
@loader.tds
class GriderMod(loader.Module):
"""Гавно залупное"""
strings = {
"name": "Griding"
}
async def client_ready(self, client, db):
self.client = client
@loader.sudo
async def gridcmd(self, message):
""".gird <reply to photo>"""
if message.is_reply:
reply_message = await message.get_reply_message()
data = await check_media(reply_message)
if isinstance(data, bool):
await utils.answer(message, "<code>Реплай на пикчу или стикер блять!</code>")
return
else:
await utils.answer(message, "`Реплай на пикчу или стикер блять`")
return
await message.edit("Режу ебать")
file = await self.client.download_media(data, bytes)
media = await griding(file)
await message.delete()
await message.client.send_file(message.to_id, media)
@loader.sudo
async def revgridcmd(self, message):
""".gird <reply to photo>"""
if message.is_reply:
reply_message = await message.get_reply_message()
data = await check_media(reply_message)
if isinstance(data, bool):
await utils.answer(message, "<code>Реплай на пикчу или стикер блять!</code>")
return
else:
await utils.answer(message, "`Реплай на пикчу или стикер блять`")
return
await message.edit("Режу ебать")
file = await self.client.download_media(data, bytes)
media = await griding(file)
media = media[::-1]
await message.delete()
await message.client.send_file(message.to_id, media)
async def griding(file):
img = Image.open(io.BytesIO(file))
(x, y) = img.size
cy = 3
cx = 3
sx = x//cx
sy = y//cy
if (sx*cx, sy*cy) != (x, y):
img = img.resize((sx*cx, sy*cy))
(lx, ly) = (0, 0)
media = []
for i in range(1, cy+1):
for o in range(1, cx+1):
mimg = img.crop((lx, ly, lx+sx, ly+sy))
bio = io.BytesIO()
bio.name = 'image.png'
mimg.save(bio, 'PNG')
media.append(bio.getvalue())
lx = lx + sx
lx = 0
ly = ly + sy
return media
async def check_media(reply_message):
if reply_message and reply_message.media:
if reply_message.photo:
data = reply_message.photo
elif reply_message.document:
if DocumentAttributeFilename(file_name='AnimatedSticker.tgs') in reply_message.media.document.attributes:
return False
if reply_message.gif or reply_message.video or reply_message.audio or reply_message.voice:
return False
data = reply_message.media.document
else:
return False
else:
return False
if not data or data is None:
return False
else:
return data

11
KeyZenD/modules/hearts.py Normal file
View File

@@ -0,0 +1,11 @@
from .. import loader
from asyncio import sleep
@loader.tds
class HeartsMod(loader.Module):
strings = {"name": "Heart's"}
@loader.owner
async def heartscmd(self, message):
for _ in range(10):
for heart in ['', '️🧡', '💛', '💚', '💙', '💜']:
await message.edit(heart)
await sleep(0.3)

96
KeyZenD/modules/help.py Normal file
View File

@@ -0,0 +1,96 @@
import logging
import inspect
from telethon.tl.functions.channels import JoinChannelRequest
from .. import loader, utils, main, security
logger = logging.getLogger(__name__)
@loader.tds
class HelpMod(loader.Module):
"""Provides this help message"""
strings = {"name": "Help",
"bad_module": '<b>Модуля</b> "<code>{}</code>" <b>нет в базе!</b>',
"single_mod_header": "<b>Информация о</b> <u>{}</u>:\n",
"single_cmd": "\n {}\n",
"undoc_cmd": "Для этой команды нет документации",
"all_header": 'Список из <a href="https://t.me/SomeScripts">{}</a> доступных модулей:\n\n',
"mod_tmpl": '\n‣<a href="tg://user?id={}">{}</a>',
"first_cmd_tmpl": "⋮( {}",
"cmd_tmpl": " | {}",
"SomeScripts": "SomeScripts"}
@loader.unrestricted
async def helpcmd(self, message):
""".help [module]"""
args = utils.get_args_raw(message)
id = message.sender_id
if args:
module = None
for mod in self.allmodules.modules:
if mod.strings("name", message).lower() == args.lower():
module = mod
if module is None:
await utils.answer(message, self.strings("bad_module", message).format(args))
return
# Translate the format specification and the module separately
try:
name = module.strings("name", message)
except KeyError:
name = getattr(module, "name", "ERROR")
reply = self.strings("single_mod_header", message).format(utils.escape_html(name),
utils.escape_html((self.db.get(main.__name__,
"command_prefix",
False) or ".")[0]))
if module.__doc__:
reply += "\n"+"\n".join(" " + t for t in utils.escape_html(inspect.getdoc(module)).split("\n"))
else:
logger.warning("Module %s is missing docstring!", module)
commands = {name: func for name, func in module.commands.items()
if await self.allmodules.check_security(message, func)}
for name, fun in commands.items():
reply += self.strings("single_cmd", message).format(name)
if fun.__doc__:
reply += utils.escape_html("\n".join(" " + t for t in inspect.getdoc(fun).split("\n")))
else:
reply += self.strings("undoc_cmd", message)
else:
count = 0
for i in self.allmodules.modules:
if len(i.commands) != 0:
count += 1
reply = self.strings("all_header", message).format(count)
for mod in self.allmodules.modules:
if len(mod.commands) != 0:
try:
name = mod.strings("name", message)
except KeyError:
name = getattr(mod, "name", "ERROR")
reply += self.strings("mod_tmpl", message).format(id, name)
first = True
commands = [name for name, func in mod.commands.items()
if await self.allmodules.check_security(message, func)]
for cmd in commands:
if first:
reply += self.strings("first_cmd_tmpl", message).format(cmd)
first = False
else:
reply += self.strings("cmd_tmpl", message).format(cmd)
reply += " )"
await utils.answer(message, reply)
@loader.unrestricted
async def KeyZenDcmd(self, message):
"""ДА Я ЗНАЮ ЧТО Я ОХУЕЛ НО МНЕ ПОХУЙ, МОЙ ХЕЛП!"""
await message.delete()
await self.client(JoinChannelRequest(self.strings("SomeScripts", message)))
async def client_ready(self, client, db):
self.client = client
self.is_bot = await client.is_bot()
self.db = db

109
KeyZenD/modules/hyi.py Normal file
View File

@@ -0,0 +1,109 @@
# -*- coding: utf-8 -*-
# Friendly Telegram (telegram userbot)
# Copyright (C) 2018-2020 The Authors
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# если не подписан на t.me/keyzend
# твоя мама шлюха
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from .. import loader, utils # pylint: disable=relative-beyond-top-level
import io
from PIL import Image, ImageOps
from telethon.tl.types import DocumentAttributeFilename
import logging
import random
logger = logging.getLogger(__name__)
def register(cb):
cb(Ебал_я_в_рот_ваш_пеп_8_Mod())
@loader.tds
class Ебал_я_в_рот_ваш_пеп_8_Mod(loader.Module):
"""Гавно залупное"""
strings = {
"name": "Хуификатор"
}
async def client_ready(self, client, db):
self.client = client
@loader.sudo
async def хуйcmd(self, message):
text = utils.get_args(message)
if not text:
reply = await message.get_reply_message()
if not reply:
await message.delete()
return
text = reply.raw_text.split()
async def huify(word):
word = word.lower().strip()
vowels = 'аеёиоуыэюя'
rules = {
'а': 'я',
'о': 'ё',
'у': 'ю',
'ы': 'и',
'э': 'е',
}
for letter in word:
if letter in vowels:
if letter in rules:
word = rules[letter] + word[1:]
break
else:
word = word[1:]
return 'Ху' + word if word else 'Хуй'
out = []
for word in text:
хуй = await huify(word)
out.append(хуй)
await message.edit(" ".join(out))
async def хуйняcmd(self, message):
text = utils.get_args(message)
if not text:
reply = await message.get_reply_message()
if not reply:
await message.delete()
return
text = reply.raw_text.split()
async def huify(word):
word = word.lower().strip()
vowels = 'аеёиоуыэюя'
rules = {
'а': 'я',
'о': 'ё',
'у': 'ю',
'ы': 'и',
'э': 'е',
}
for letter in word:
if letter in vowels:
if letter in rules:
word = rules[letter] + word[1:]
break
else:
word = word[1:]
return 'Ху' + word if word else 'Хуй'
out = []
for word in text:
хуй = await huify(word)
out.append(f"{word}-{хуй}")
await message.edit(" ".join(out))

93
KeyZenD/modules/im2bin.py Normal file
View File

@@ -0,0 +1,93 @@
import asyncio
import logging
from PIL import Image, ImageDraw, ImageFont, ImageOps
import io
from requests import get
from string import digits
from random import choice
from .. import loader, utils
logger = logging.getLogger(__name__)
font_ = get("https://github.com/KeyZenD/l/blob/master/mono.otf?raw=true").content
@loader.tds
class Im2BinaryMod(loader.Module):
"""Картинки в текст. что?"""
strings = {"name": "Im2Bin"}
@loader.unrestricted
async def bincmd(self, message):
""".bin <картинка или реплай> + слова (дефолт на рандоме) (не мешает слова)"""
img, words, me = await prepare(message)
if not img:
await message.delete()
return await message.client.send_file(message.chat.id, get("https://thiscatdoesnotexist.com").content, caption=choice(["<b>Тебе картинок мало?</b>"]+[None]*100))
await message.edit("<b>Processing...</b>")
img = await image_to_text(words, img, False)
[await message.delete(), await (await message.get_reply_message()).reply(file=img)] if not me else await message.edit(file=img, text="")
@loader.unrestricted
async def rbincmd(self, message):
""".rbin <картинка или реплай> + слова (дефолт на рандоме) (мешает слова)"""
img, words, me = await prepare(message)
if not img:
await message.delete()
return await message.client.send_file(message.chat.id, get("https://thiscatdoesnotexist.com").content, caption=choice(["<b>Тебе картинок мало?</b>"]+[None]*100))
await message.edit("<b>Processing...</b>")
img = await image_to_text(words, img, True)
[await message.delete(), await (await message.get_reply_message()).reply(file=img)] if not me else await message.edit(file=img, text="")
async def getimg(m):
if not m.file:
return False
if not "image" in m.file.mime_type.lower():
return False
return True
async def prepare(message):
if not await getimg(message):
reply = await message.get_reply_message()
if not reply or not await getimg(reply):
return False, False, False
else:
me = False
img = await reply.download_media(bytes)
else:
me = True
img = await message.download_media(bytes)
args = utils.get_args(message)
words = [f"{x} " for x in args] if args else list("01")
return img, words, me
async def image_to_text(words, img, rand):
inp = Image.open(io.BytesIO(img))
img = Image.new("RGBA", inp.size, "#000")
res = img.copy()
img.paste(inp, (0, 0), inp if inp.mode == "RGBA" else None)
w, h = img.size
font = ImageFont.truetype(io.BytesIO(font_), 15)
mw = min(map(lambda x: font.getsize(x)[0], "".join(words)))
mh = min(map(lambda x: font.getsize(x)[1], "".join(words)))
rand_ = 0
text = []
while len(text)*mh <= h:
row = []
while len("".join(row))*mw <= w:
word = choice(words) if rand else words[rand_%len(words)]
rand_ += 1
row.append(word)
rand_ -= 1
text.append("".join(row))
text = "\n".join(text)
wt, ht = ImageDraw.Draw(Image.new("L", (0, 0))).multiline_textsize(font=font, text=text, spacing=0)
im = Image.new("L", (wt, ht), 0)
ImageDraw.Draw(im).multiline_text((0, -3), font=font, text=text, spacing=0, fill=255)
im = im.crop((0, 0, w, h))
im = Image.frombytes("L", (w, h), bytes([255 if x > 150 else 0 for x in im.tobytes()]))
img.putalpha(im)
res.paste(img, (0, 0), img)
out = io.BytesIO()
out.name = words[0] + ".png"
res.save(out)
out.seek(0)
return out

48
KeyZenD/modules/jpeg.py Normal file
View File

@@ -0,0 +1,48 @@
from PIL import Image
from telethon.tl.types import DocumentAttributeFilename
from uniborg.util import admin_cmd
import io
@borg.on(admin_cmd(pattern=".jpeg?(.*)", allow_sudo=True))
async def shacal(event):
async def check_media(reply_message):
if reply_message and reply_message.media:
if reply_message.photo:
data = reply_message.photo
elif reply_message.document:
if DocumentAttributeFilename(file_name='AnimatedSticker.tgs') in reply_message.media.document.attributes:
return False
if reply_message.gif or reply_message.video or reply_message.audio or reply_message.voice:
return False
data = reply_message.media.document
else:
return False
else:
return False
if not data or data is None:
return False
else:
return data
if event.is_reply:
reply_message = await event.get_reply_message()
data = await check_media(reply_message)
if isinstance(data, bool):
await event.delete()
return
else:
await event.delete()
return
image = io.BytesIO()
await event.client.download_media(data, image)
image = Image.open(image)
fried_io = io.BytesIO()
fried_io.name = "image.jpeg"
image = image.convert("RGB")
image.save(fried_io, "JPEG", quality=0)
fried_io.seek(0)
await event.delete()
await event.client.send_file(event.chat_id, fried_io, reply_to=reply_message.id)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,93 @@
# @KeyZenD & @D4n13l3k00
# requires: bs4 aiogram
from random import choice
from string import ascii_lowercase
from aiogram import Bot
from bs4 import BeautifulSoup as bs4
from telethon import events, functions, types
from telethon.tl.functions.channels import InviteToChannelRequest
from telethon.tl.types import Channel
from .. import loader, utils
class KickLastMod(loader.Module):
"""Удаляет из чата последних Х зашедших"""
strings = {
'name': 'KickLast',
'pref': '<b>[KickLast]</b> ',
'cdne': '{}Такого чата не существует',
'cfju': '{}Не могу обнаружить зашедших...',
'success': '{}Операция завершена! Кикнуто {} юзеров',
'found': '{}Найдено {} зашедших юзеров! Кикаю...',
'howmany': '{}Сколько нужно кикнуть?\n0 если всех зашедших за 48 часов',
'createerr': '{}Создание бота недоступно.\nПовтори попытку через {}'
}
async def botkicklastcmd(self, message):
""".botkicklst <количество> <юзернейм, если канал> - Кикает при помощи тг бота"""
await kick(self, message, True)
async def kicklastcmd(self, message):
""".kicklst <количество> <юзернейм, если канал> - Кикает юзерботом"""
await kick(self, message, False)
async def kick(self, message, bot=False):
client = message.client
args = utils.get_args(message)
if not args:
return await utils.answer(message, self.strings('howmany').format(self.strings('pref')))
limit = int(args[0])
limit = limit or 99999
group = args[-1] if len(args) > 1 else message.chat.id
try:
group = await client.get_entity(group)
except:
await utils.answer(message, self.strings('cdne').format(self.strings('pref')))
if not isinstance(group, Channel):
return await utils.answer(message, self.strings('cdne').format(self.strings('pref')))
if bot:
botfather = 93372553
bantoolbot = "".join(choice(list(ascii_lowercase))
for _ in range(29))+"bot"
async with client.conversation(botfather) as conv:
await (await client.send_message(botfather, "/newbot")).delete()
newbot = await conv.wait_event(events.NewMessage(incoming=True, from_users=botfather))
await newbot.delete()
if "Sorry" in newbot.text:
return await utils.answer(message, self.strings('howmany').format(self.strings('pref'), newbot.text[45:]))
await (await client.send_message(botfather, "BanTool")).delete()
await (await conv.wait_event(events.NewMessage(incoming=True, from_users=botfather))).delete()
await (await client.send_message(botfather, bantoolbot)).delete()
html = await conv.wait_event(events.NewMessage(incoming=True, from_users=botfather))
await html.delete()
soup = bs4(html.text, "html.parser")
token = soup.findAll("code")[0].text
await client(InviteToChannelRequest(group, [bantoolbot]))
await client(functions.channels.EditAdminRequest(
channel=group,
user_id=bantoolbot,
admin_rights=types.ChatAdminRights(ban_users=True), rank='BanToolBot'))
banlist = [x.user_id async for x in client.iter_admin_log(group, join=True, limit=limit)]
message = await utils.answer(message, self.strings('found').format(self.strings('pref'), str(len(banlist))))
if not banlist:
return await utils.answer(message, self.strings('cfju').format(self.strings('pref')))
for banid in banlist:
if bot:
await Bot(token).kick_chat_member(f"-100{group}", banid)
else:
await client.kick_participant(group, banid)
if bot:
await client.kick_participant(group, bantoolbot)
async with client.conversation(botfather) as conv:
await client.send_message(botfather, "/deletebot")
await conv.wait_event(events.NewMessage(incoming=True, from_users=botfather))
await client.send_message(botfather, "@"+bantoolbot)
await conv.wait_event(events.NewMessage(incoming=True, from_users=botfather))
await client.send_message(botfather, "Yes, I am totally sure.")
return await utils.answer(message, self.strings('success').format(self.strings('pref'), str(len(banlist))))

View File

@@ -0,0 +1,250 @@
from .. import loader, utils
import telethon
import logging
import io
from telethon.tl.types import (ChannelParticipantsAdmins, ChannelParticipantCreator, ChannelParticipantAdmin, User)
from requests import post
from PIL import Image
logger = logging.getLogger("kzdQuotes")
@loader.tds
class kzdQuotesMod(loader.Module):
"""kzdQuote a message"""
strings = {
"name": "kzdQuotes",
"processing": "<b>Quoting</b>",
"processing_api": "<b>Quoting💬</b>",
"no_reply": "<b>Нет реплая</b>",
"mediaType_photo": "️Фото",
"mediaType_video": "Видео",
"mediaType_videomessage": "Видеосообщение",
"mediaType_voice": "️Аудиосообщение",
"mediaType_audio": "Аудио",
"mediaType_poll": "Голосование",
"mediaType_quiz": "Викторина",
"mediaType_location": "Геолокация",
"mediaType_gif": "GIF",
"mediaType_sticker": "Стикер",
"mediaType_file": "Файл: ",
"diceType_dice": "Кубик",
"diceType_dart": "Дартс",
"ball_thrown": "Бросок мяча",
"dart_thrown": "Бросок дротика",
"dart_almostthere": "близко к цели!",
"dart_missed": "мимо!",
"dart_bullseye": "в яблочко!",
"settings": "<b>Доступные настройки:</b>\n<code>color</code> - hex color - Цвет квотеса"
}
async def client_ready(self, client, db):
self.client = client
self.db = db
@loader.unrestricted
@loader.ratelimit
async def qqcmd(self, message):
args = utils.get_args_raw(message)
reply = await message.get_reply_message()
if not reply:
await utils.answer(message, self.strings('no_reply', message))
return
await utils.answer(message, self.strings('processing', message))
fwd = via = rtext = file = thumb = rname = admintitle = None
if ".file" in args:
file = True
args = args.replace(".file","").strip()
text = args or reply.text
sender = user = reply.sender
if sender:
id = sender.id if sender.id != 1087968824 else reply.chat.id
else:
id = reply.fwd_from.channel_id
sender = await message.client.get_entity(id)
name = "Deleted Account" if user and sender.deleted else telethon.utils.get_display_name(sender)
pfp = await message.client.download_profile_photo(sender, bytes)
if reply.fwd_from and reply.sender:
id = reply.fwd_from.from_id or reply.fwd_from.channel_id
if not id:
fname = reply.fwd_from.from_name
else:
sender = await message.client.get_entity(id)
fwd = telethon.utils.get_display_name(sender)
if reply.via_bot:
via = reply.via_bot.username or "magic"
img = await check_media(message, reply)
rreply = await reply.get_reply_message()
if rreply and not args:
thumb = await check_media(message, rreply, True)
rtext = rreply.raw_text
if rreply.media:
rtext = await get_media_caption(rreply) #спиздено у t.me/rfoxxxy
rsender = rreply.sender
rname = telethon.utils.get_display_name(rsender)
if message.chat and reply.sender:
admins = await message.client.get_participants(message.to_id, filter=ChannelParticipantsAdmins)
if reply.sender in admins:
admin = admins[admins.index(reply.sender)].participant
if not admin:
admintitle = None
else:
admintitle = admin.rank
if not admintitle:
if type(admin) == ChannelParticipantCreator:
admintitle = "creator"
else:
admintitle = "admin"
else:
admintitle = "channel" if message.chat else None
color = self.db.get("kzdQuotes", "color", None)
data = {"id":id,"name":name,"admin":admintitle, "via":via, "fwd":fwd,"text":text,"rtext":rtext,"rname":rname, "color":color}
files = {"pfp": pfp, "img":img, "thumb": thumb}
await utils.answer(message, self.strings('processing_api', message))
q = post("https://tyt.keyzend.pw/quote", data=data, files=files).content
quote = io.BytesIO()
quote.name = "govnoquotes"+ (".png" if file else ".webp")
im = Image.open(io.BytesIO(q))
if not file:
im.thumbnail((512, 512))
back = Image.new("RGBA", (im.width, im.height+100), None)
back.paste(im, (0, 0), im)
im = back
im.thumbnail((512, 512))
im.save(quote, "PNG" if file else "WEBP")
quote.seek(0)
await reply.reply(file=quote, force_document=file)
await message.delete()
@loader.unrestricted
@loader.ratelimit
async def qqsetcmd(self, message):
args = utils.get_args(message)
if len(args) != 2 or args[0].lower() not in ["color"]:
await utils.answer(message, self.strings('settings', message))
return
key, value = args
self.db.set("kzdQuotes", key, value)
await message.edit(f"<b>Значение {args[0]} установлено</b>")
async def get_media_caption(reply):
if reply and reply.media:
if reply.photo:
return kzdQuotesMod.strings["mediaType_photo"]
if reply.text:
return reply.raw_text
dice = False
try:
dice = True if reply.dice else False
except AttributeError:
try:
dice = True if type(reply.media) == telethon.tl.types.MessageMediaDice else False
except AttributeError:
pass
if dice:
dice_type = ""
dice_text = reply.media.value
if reply.media.emoticon == "🎲":
dice_type = kzdQuotesMod.strings["diceType_dice"]
return "{} {}: {}".format(reply.media.emoticon,
dice_type,
dice_text)
elif reply.media.emoticon == "🎯":
if dice_text == 1:
dice_text = kzdQuotesMod.strings["dart_missed"]
elif dice_text == 5:
dice_text = kzdQuotesMod.strings["dart_almostthere"]
elif dice_text == 6:
dice_text = kzdQuotesMod.strings["dart_bullseye"]
else:
return "{} {}".format(reply.media.emoticon, kzdQuotesMod.strings["dart_thrown"])
dice_type = kzdQuotesMod.strings["diceType_dart"]
return "{} {}: {}".format(reply.media.emoticon, dice_type, dice_text)
elif reply.media.emoticon == "🏀":
return "{} {}".format(reply.media.emoticon, kzdQuotesMod.strings["ball_thrown"])
else:
return "Unsupported dice type ({}): {}".format(reply.media.emoticon, reply.media.value)
elif reply.poll:
try:
if reply.media.poll.quiz is True:
return kzdQuotesMod.strings["mediaType_quiz"]
except Exception:
pass
return kzdQuotesMod.strings["mediaType_poll"]
elif reply.geo:
return kzdQuotesMod.strings["mediaType_location"]
elif reply.document:
if reply.gif :
return kzdQuotesMod.strings["mediaType_gif"]
elif reply.video:
if reply.video.attributes[0].round_message:
return kzdQuotesMod.strings["mediaType_videomessage"]
else:
return kzdQuotesMod.strings["mediaType_video"]
elif reply.audio:
return kzdQuotesMod.strings["mediaType_audio"]
elif reply.voice:
return kzdQuotesMod.strings["mediaType_voice"]
elif reply.file:
if reply.file.mime_type == "application/x-tgsticker":
emoji = ""
try:
emoji = reply.media.document.attributes[0].alt
except AttributeError:
try:
emoji = reply.media.document.attributes[1].alt
except AttributeError:
emoji = ""
caption = "{} {}".format(emoji, kzdQuotesMod.strings["mediaType_sticker"]) if emoji != "" else kzdQuotesMod.strings["mediaType_sticker"]
return caption
else:
if reply.sticker:
emoji = ""
try:
emoji = reply.file.emoji
logger.debug(len(emoji))
except TypeError:
emoji = ""
caption = "{} {}".format(emoji, kzdQuotesMod.strings["mediaType_sticker"]) if emoji != "" else kzdQuotesMod.strings["mediaType_sticker"]
return caption
else:
return kzdQuotesMod.strings["mediaType_file"] + reply.file.name
else:
return ""
else:
return ""
return ""
async def check_media(message, reply, x=None):
if reply and reply.media:
if reply.photo:
data = reply.photo
elif reply.document:
if reply.gif or reply.video or reply.file.mime_type == "application/x-tgsticker":
return await reply.download_media(bytes, thumb=-1) if x else None
if reply.audio or reply.voice:
return None
data = reply.media.document
else:
return None
else:
return None
if not data or data is None:
return None
else:
return await message.client.download_file(data, bytes)

23
KeyZenD/modules/leave.py Normal file
View File

@@ -0,0 +1,23 @@
from .. import loader, utils
from asyncio import sleep
from telethon.tl.functions.channels import LeaveChannelRequest
@loader.tds
class LeaveMod(loader.Module):
strings = {"name": "Just leave"}
@loader.sudo
async def leavecmd(self, message):
""".leave"""
if not message.chat:
await message.edit("<b>Дурка блять</b>")
return
text = utils.get_args_raw(message)
if not text:
text = "До связи."
if text.lower() == "del":
await message.delete()
else:
await message.edit(f"<b>{text}</b>")
await sleep(1)
await message.client(LeaveChannelRequest(message.chat_id))

View File

@@ -0,0 +1,53 @@
from telethon import events
from .. import loader, utils
#испольуйте только на свой страх и риск
#используя этот модуль вы принимаете то
#что если получите бан, то на мне никакой ответственности
def register(cb):
cb(MSMod())
class MSMod(loader.Module):
"""Спаммер медиа(стикер/гиф/фото/видео/войс/видеовойс</code>"""
strings = {'name': 'МедиаСпам'}
def __init__(self):
self.name = self.strings['name']
self._me = None
self._ratelimit = []
async def client_ready(self, client, db):
self._db = db
self._client = client
self.me = await client.get_me()
async def mediaspamcmd(self, message):
""".mediaspam <количество> + реплай на медиа(стикер/гиф/фото/видео/войс/видеовойс)"""
reply = await message.get_reply_message()
if not reply:
await message.edit("<code>.mediaspam <количество> + реплай на медиа(стикер/гиф/фото/видео/войс/видеовойс</code>")
return
if not reply.media:
await message.edit("<code>.mediaspam <количество> + реплай на медиа(стикер/гиф/фото/видео/войс/видеовойс</code>")
return
media = reply.media
args = utils.get_args(message)
if not args:
await message.edit("<code>.mediaspam <количество> + реплай на медиа(стикер/гиф/фото/видео/войс/видеовойс</code>")
return
count = args[0]
count = count.strip()
if not count.isdigit():
await message.edit("<code>.mediaspam <количество> + реплай на медиа(стикер/гиф/фото/видео/войс/видеовойс</code>")
return
count = int(count)
await message.delete()
for _ in range(count):
await message.client.send_file(message.to_id, media)

View File

@@ -0,0 +1,26 @@
R=int
Q=float
E=len
# requires: pydub numpy
from .. import loader as A,utils
import os
from pydub import AudioSegment as M
import numpy as G,io
class BMod(A.Module):
'Modulate pitch of voice';strings={'name':'Modulator'}
async def modulatecmd(W,message):
A=message;B=await A.get_reply_message()
if not B or not B.file and'audio'in B.file.mime_type:return await A.edit('<b>Reply to audio!</b>')
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
if E(C)==3:
try:J=(Q(A)for A in C)
except:pass
if E(C)==4:
try:J=(Q(A)for A in C[0:3]);O=R(C[3])
except:pass
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('<b>Modulating...</b>')
for (T,L) in enumerate(I):
U=D[T%E(D)];K+=1
if K>E(D):K=0;D=D[::-1]
V=R(L.frame_rate*U);H+=L._spawn(L.raw_data,overrides={'frame_rate':V})
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()

View File

@@ -0,0 +1,337 @@
# Friendly Telegram (telegram userbot)
# Copyright (C) 2018-2019 The Authors
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from .. import loader, utils
import logging
import asyncio
import telethon
import os
import re
logger = logging.getLogger(__name__)
@loader.tds
class noTerminalMod(loader.Module):
"""Runs commands"""
strings = {"name": "noTerminal",
"flood_wait_protect_cfg_doc": "How long to wait in seconds between edits in commands",
"what_to_kill": "<b>Reply to a terminal command to terminate it</b>",
"kill_fail": "<b>Could not kill process</b>",
"killed": "<b>Killed</b>",
"no_cmd": "<b>No command is running in that message</b>",
"running": "<b>Running command</b> <code>{}</code>",
"finished": "\n<b>Command finished with return code</b> <code>{}</code>",
"stdout": "\n<b>Stdout:</b>\n<code>",
"stderr": "</code>\n\n<b>Stderr:</b>\n<code>",
"end": "</code>",
"auth_fail": "<b>Authentication failed, please try again</b>",
"auth_needed": "<a href=\"tg://user?id={}\">Interactive authentication required</a>",
"auth_msg": ("<b>Please edit this message to the password for</b> "
"<code>{}</code> <b>to run</b> <code>{}</code>"),
"auth_locked": "<b>Authentication failed, please try again later</b>",
"auth_ongoing": "<b>Authenticating...</b>",
"done": "<b>Done</b>",
"what_note": "<b>What noterminal should be executed?</b>",
"no_note": "<b>noteminal not found</b>"}
def __init__(self):
self.config = loader.ModuleConfig("FLOOD_WAIT_PROTECT", 2,
lambda m: self.strings("flood_wait_protect_cfg_doc", m))
self.activecmds = {}
async def client_ready(self, client, db):
self.client = client
self.db = db
self._db = db
async def noterminalcmd(self, message):
"""Gets the note specified"""
args = utils.get_args(message)
if not args:
await utils.answer(message, self.strings("what_note", message))
return
asset_id = self.db.get("friendly-telegram.modules.notes", "notes", {}).get(args[0], None)
logger.debug(asset_id)
if asset_id is not None:
asset = await self.db.fetch_asset(asset_id)
else:
asset_id = self.db.get("friendly-telegram.modules.notes", "notes", {}).get(args[0].lower(), None)
if asset_id is not None:
asset = await self.db.fetch_asset(asset_id)
else:
asset = None
if asset is None:
await utils.answer(message, self.strings("no_note", message))
return
cmd = await self.db.fetch_asset(asset_id)
await self.run_command(message, cmd.raw_text)
async def run_command(self, message, cmd, editor=None):
if len(cmd.split(" ")) > 1 and cmd.split(" ")[0] == "sudo":
needsswitch = True
for word in cmd.split(" ", 1)[1].split(" "):
if word[0] != "-":
break
if word == "-S":
needsswitch = False
if needsswitch:
cmd = " ".join([cmd.split(" ", 1)[0], "-S", cmd.split(" ", 1)[1]])
sproc = await asyncio.create_subprocess_shell(cmd, stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
cwd=utils.get_base_dir())
if editor is None:
editor = SudoMessageEditor(message, cmd, self.config, self.strings, message)
editor.update_process(sproc)
self.activecmds[hash_msg(message)] = sproc
await editor.redraw()
await asyncio.gather(read_stream(editor.update_stdout, sproc.stdout, self.config["FLOOD_WAIT_PROTECT"]),
read_stream(editor.update_stderr, sproc.stderr, self.config["FLOOD_WAIT_PROTECT"]))
await editor.cmd_ended(await sproc.wait())
del self.activecmds[hash_msg(message)]
@loader.owner
async def noterminatecmd(self, message):
"""Use in reply to send SIGTERM to a process"""
if not message.is_reply:
await utils.answer(message, self.strings("what_to_kill", message))
return
if hash_msg(await message.get_reply_message()) in self.activecmds:
try:
self.activecmds[hash_msg(await message.get_reply_message())].terminate()
except Exception:
logger.exception("Killing process failed")
await utils.answer(message, self.strings("kill_fail", message))
else:
await utils.answer(message, self.strings("killed", message))
else:
await utils.answer(message, self.strings("no_cmd", message))
@loader.owner
async def nokillcmd(self, message):
"""Use in reply to send SIGKILL to a process"""
if not message.is_reply:
await utils.answer(message, self.strings("what_to_kill", message))
return
if hash_msg(await message.get_reply_message()) in self.activecmds:
try:
self.activecmds[hash_msg(await message.get_reply_message())].kill()
except Exception:
logger.exception("Killing process failed")
await utils.answer(message, self.strings("kill_fail", message))
else:
await utils.answer(message, self.strings("killed", message))
else:
await utils.answer(message, self.strings("no_cmd", message))
def hash_msg(message):
return str(utils.get_chat_id(message)) + "/" + str(message.id)
async def read_stream(func, stream, delay):
last_task = None
data = b""
while True:
dat = (await stream.read(1))
if not dat:
# EOF
if last_task:
# Send all pending data
last_task.cancel()
await func(data.decode("utf-8"))
# If there is no last task there is inherently no data, so theres no point sending a blank string
break
data += dat
if last_task:
last_task.cancel()
last_task = asyncio.ensure_future(sleep_for_task(func, data, delay))
async def sleep_for_task(func, data, delay):
await asyncio.sleep(delay)
await func(data.decode("utf-8"))
class MessageEditor:
def __init__(self, message, command, config, strings, request_message):
self.message = [message]
self.command = command
self.stdout = ""
self.stderr = ""
self.rc = None
self.redraws = 0
self.config = config
self.strings = strings
self.request_message = request_message
async def update_stdout(self, stdout):
self.stdout = stdout
await self.redraw()
async def update_stderr(self, stderr):
self.stderr = stderr
await self.redraw()
async def redraw(self):
text = "" # self.strings("running", self.request_message).format(utils.escape_html(self.command))
# if self.rc is not None:
# text += self.strings("finished", self.request_message).format(utils.escape_html(str(self.rc)))
text += self.strings("stdout", self.request_message)
text += utils.escape_html(self.stdout[max(len(self.stdout) - 2048, 0):])
if len(self.stderr) > 0:
text += self.strings("stderr", self.request_message)
text += utils.escape_html(self.stderr[max(len(self.stderr) - 1024, 0):])
text += self.strings("end", self.request_message)
try:
self.message = await utils.answer(self.message, text)
except telethon.errors.rpcerrorlist.MessageNotModifiedError:
pass
except telethon.errors.rpcerrorlist.MessageTooLongError as e:
logger.error(e)
logger.error(text)
# The message is never empty due to the template header
async def cmd_ended(self, rc):
self.rc = rc
self.state = 4
await self.redraw()
def update_process(self, process):
pass
class SudoMessageEditor(MessageEditor):
# Let's just hope these are safe to parse
PASS_REQ = "[sudo] password for"
WRONG_PASS = r"\[sudo\] password for (.*): Sorry, try again\."
TOO_MANY_TRIES = r"\[sudo\] password for (.*): sudo: [0-9]+ incorrect password attempts"
def __init__(self, message, command, config, strings, request_message):
super().__init__(message, command, config, strings, request_message)
self.process = None
self.state = 0
self.authmsg = None
def update_process(self, process):
logger.debug("got sproc obj %s", process)
self.process = process
async def update_stderr(self, stderr):
logger.debug("stderr update " + stderr)
self.stderr = stderr
lines = stderr.strip().split("\n")
lastline = lines[-1]
lastlines = lastline.rsplit(" ", 1)
handled = False
if len(lines) > 1 and re.fullmatch(self.WRONG_PASS,
lines[-2]) and lastlines[0] == self.PASS_REQ and self.state == 1:
logger.debug("switching state to 0")
await self.authmsg.edit(self.strings("auth_failed", self.request_message))
self.state = 0
handled = True
await asyncio.sleep(2)
await self.authmsg.delete()
if lastlines[0] == self.PASS_REQ and self.state == 0:
logger.debug("Success to find sudo log!")
text = self.strings("auth_needed", self.request_message).format((await self.message[0].client.get_me()).id)
try:
await utils.answer(self.message, text)
except telethon.errors.rpcerrorlist.MessageNotModifiedError as e:
logger.debug(e)
logger.debug("edited message with link to self")
command = "<code>" + utils.escape_html(self.command) + "</code>"
user = utils.escape_html(lastlines[1][:-1])
self.authmsg = await self.message[0].client.send_message("me",
self.strings("auth_msg",
self.request_message).format(command,
user))
logger.debug("sent message to self")
self.message[0].client.remove_event_handler(self.on_message_edited)
self.message[0].client.add_event_handler(self.on_message_edited,
telethon.events.messageedited.MessageEdited(chats=["me"]))
logger.debug("registered handler")
handled = True
if len(lines) > 1 and (re.fullmatch(self.TOO_MANY_TRIES, lastline)
and (self.state == 1 or self.state == 3 or self.state == 4)):
logger.debug("password wrong lots of times")
await utils.answer(self.message, self.strings("auth_locked", self.request_message))
await self.authmsg.delete()
self.state = 2
handled = True
if not handled:
logger.debug("Didn't find sudo log.")
if self.authmsg is not None:
await self.authmsg[0].delete()
self.authmsg = None
self.state = 2
await self.redraw()
logger.debug(self.state)
async def update_stdout(self, stdout):
self.stdout = stdout
if self.state != 2:
self.state = 3 # Means that we got stdout only
if self.authmsg is not None:
await self.authmsg.delete()
self.authmsg = None
await self.redraw()
async def on_message_edited(self, message):
# Message contains sensitive information.
if self.authmsg is None:
return
logger.debug("got message edit update in self " + str(message.id))
if hash_msg(message) == hash_msg(self.authmsg):
# The user has provided interactive authentication. Send password to stdin for sudo.
try:
self.authmsg = await utils.answer(message, self.strings("auth_ongoing", self.request_message))
except telethon.errors.rpcerrorlist.MessageNotModifiedError:
# Try to clear personal info if the edit fails
await message.delete()
self.state = 1
self.process.stdin.write(message.message.message.split("\n", 1)[0].encode("utf-8") + b"\n")
class RawMessageEditor(SudoMessageEditor):
def __init__(self, message, command, config, strings, request_message, show_done=False):
super().__init__(message, command, config, strings, request_message)
self.show_done = show_done
async def redraw(self):
logger.debug(self.rc)
if self.rc is None:
text = "<code>" + utils.escape_html(self.stdout[max(len(self.stdout) - 4095, 0):]) + "</code>"
elif self.rc == 0:
text = "<code>" + utils.escape_html(self.stdout[max(len(self.stdout) - 4090, 0):]) + "</code>"
else:
text = "<code>" + utils.escape_html(self.stderr[max(len(self.stderr) - 4095, 0):]) + "</code>"
if self.rc is not None and self.show_done:
text += "\n" + self.strings("done", self.request_message)
logger.debug(text)
try:
await utils.answer(self.message, text)
except telethon.errors.rpcerrorlist.MessageNotModifiedError:
pass
except (telethon.errors.rpcerrorlist.MessageEmptyError, ValueError):
pass
except telethon.errors.rpcerrorlist.MessageTooLongError as e:
logger.error(e)
logger.error(text)

138
KeyZenD/modules/notes.py Normal file
View File

@@ -0,0 +1,138 @@
# Friendly Telegram (telegram userbot)
# Copyright (C) 2018-2019 The Authors
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging
from .. import loader, utils
logger = logging.getLogger("friendly-telegram.modules.notes")
@loader.tds
class NotesMod(loader.Module):
"""Stores global notes (aka snips)"""
strings = {"name": "Notes",
"what_note": "<b>Какую заметку нужно показать?</b>",
"no_note": "<b>Заметка не найдена</b>",
"save_what": "<b>А что сохранить?</b>",
"what_name": "<b>А как будет называться заметка?</b>",
"saved": "<b>Заметка сохранена как:</b> <code>{}</code>",
"notes_header": "<b>Сохранённые заметки:</b>\n\n",
"notes_item": "<b>▷</b> <code>{}</code>",
"delnote_args": "<b>А какую заметку нужно удалить?</b>",
"delnote_done": "<b>Заметка удалена!</b>",
"delnotes_none": "<b>А заметок-то нету...</b>",
"delnotes_done": "<b>ВСЕ ЗАМЕТКИ УДАЛЕНЫ</b>",
"notes_none": "<b>А заметок-то нету...</b>"}
async def findnotecmd(self, message):
"""Gets the note specified"""
args = utils.get_args(message)
if not args:
await utils.answer(message, self.strings("what_note", message))
return
asset_id = self._db.get("friendly-telegram.modules.notes", "notes", {}).get(args[0], None)
logger.debug(asset_id)
if asset_id is not None:
asset = await self._db.fetch_asset(asset_id)
else:
asset = None
if asset is None:
self.del_note(args[0])
await utils.answer(message, self.strings("no_note", message))
return
link = "https://t.me/c/{}/{}".format(asset.chat.id, asset.id)
await message.edit(f'<b>Заметка</b> "<code>{args[0]}</code>" <a href="{link}">находится здесь.</a>')
async def notecmd(self, message):
"""Gets the note specified"""
args = utils.get_args(message)
if not args:
await utils.answer(message, self.strings("what_note", message))
return
asset_id = self._db.get("friendly-telegram.modules.notes", "notes", {}).get(args[0], None)
logger.debug(asset_id)
if asset_id is not None:
asset = await self._db.fetch_asset(asset_id)
else:
asset = None
if asset is None:
self.del_note(args[0])
await utils.answer(message, self.strings("no_note", message))
return
await message.delete()
await message.client.send_message(message.to_id, await self._db.fetch_asset(asset_id), reply_to=await message.get_reply_message())
async def delallnotescmd(self, message):
"""Deletes all the saved notes"""
if not self._db.get("friendly-telegram.modules.notes", "notes", {}):
await utils.answer(message, self.strings("delnotes_none", message))
return
self._db.get("friendly-telegram.modules.notes", "notes", {}).clear()
await utils.answer(message, self.strings("delnotes_done", message))
async def savecmd(self, message):
"""Save a new note. Must be used in reply with one parameter (note name)"""
args = utils.get_args(message)
if not args:
await utils.answer(message, self.strings("what_name", message))
return
if not message.is_reply:
if len(args) < 2:
await utils.answer(message, self.strings("save_what", message))
return
else:
message.entities = None
message.message = args[1]
target = message
logger.debug(target.message)
else:
target = await message.get_reply_message()
asset_id = await self._db.store_asset(target)
self._db.set("friendly-telegram.modules.notes", "notes", {**self._db.get("friendly-telegram.modules.notes", "notes", {}), args[0]: asset_id})
await utils.answer(message, str(self.strings("saved", message)).format(args[0]))
async def delnotecmd(self, message):
"""Deletes a note, specified by note name"""
args = utils.get_args(message)
if not args:
await utils.answer(message, self.strings("delnote_args", message))
self.del_note(args[0])
await utils.answer(message, self.strings("delnote_done", message))
def del_note(self, note):
old = self._db.get("friendly-telegram.modules.notes", "notes", {})
try:
del old[note]
except KeyError:
pass
else:
self._db.set("friendly-telegram.modules.notes", "notes", old)
async def notescmd(self, message):
"""List the saved notes"""
if not self._db.get("friendly-telegram.modules.notes", "notes", {}):
await utils.answer(message, self.strings("notes_none", message))
return
await utils.answer(message, self.strings("notes_header", message)
+ "\n".join(self.strings("notes_item", message).format(key)
for key in self._db.get("friendly-telegram.modules.notes", "notes", {})))
async def client_ready(self, client, db):
self._db = db

View File

@@ -0,0 +1,95 @@
# Friendly Telegram (telegram userbot)
# Copyright (C) 2018-2019 The Authors
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging
import traceback
import sys
import itertools
import types
from meval import meval
import telethon
from .. import loader, utils
logger = logging.getLogger(__name__)
@loader.tds
class ExecutorMod(loader.Module):
"""Stores global notes (aka snips)"""
strings = {"name": "Notexec",
"what_note": "<b>What notexec should be executed?</b>",
"no_note": "<b>Notexec not found</b>",
"execute_fail": ("<b>Failed to execute expression:</b>\n<code>{}</code>")
}
async def notexeccmd(self, message):
"""Gets the note specified"""
args = utils.get_args(message)
if not args:
await utils.answer(message, self.strings("what_note", message))
return
asset_id = self._db.get("friendly-telegram.modules.notes", "notes", {}).get(args[0], None)
logger.debug(asset_id)
if asset_id is not None:
asset = await self._db.fetch_asset(asset_id)
else:
asset_id = self._db.get("friendly-telegram.modules.notes", "notes", {}).get(args[0].lower(), None)
if asset_id is not None:
asset = await self._db.fetch_asset(asset_id)
else:
asset = None
if asset is None:
await utils.answer(message, self.strings("no_note", message))
return
cmd = await self._db.fetch_asset(asset_id)
try:
await meval(cmd.raw_text, globals(), **await self.getattrs(message))
except Exception:
exc = sys.exc_info()
exc = "".join(traceback.format_exception(exc[0], exc[1], exc[2].tb_next.tb_next.tb_next))
await utils.answer(message, self.strings("execute_fail", message)
.format(utils.escape_html(exc)))
return
async def client_ready(self, client, db):
self.client = client
self.db = db
self._db = db
async def getattrs(self, message):
return {"message": message, "client": self.client, "self": self, "db": self.db,
"reply": await message.get_reply_message(), "event": message,"chat": message.to_id , **self.get_types(), **self.get_functions()}
def get_types(self):
return self.get_sub(telethon.tl.types)
def get_functions(self):
return self.get_sub(telethon.tl.functions)
def get_sub(self, it, _depth=1):
"""Get all callable capitalised objects in an object recursively, ignoring _*"""
return {**dict(filter(lambda x: x[0][0] != "_" and x[0][0].upper() == x[0][0] and callable(x[1]),
it.__dict__.items())),
**dict(itertools.chain.from_iterable([self.get_sub(y[1], _depth + 1).items() for y in
filter(lambda x: x[0][0] != "_"
and isinstance(x[1], types.ModuleType)
and x[1] != it
and x[1].__package__.rsplit(".", _depth)[0]
== "telethon.tl",
it.__dict__.items())]))}

5
KeyZenD/modules/null.py Normal file
View File

@@ -0,0 +1,5 @@
from .. import loader
class nullMod(loader.Module):
strings = {"name": "null"}
async def nullcmd(self, message):
await message.edit("null")

61
KeyZenD/modules/ph.py Normal file
View File

@@ -0,0 +1,61 @@
from .. import loader, utils
import asyncio
import requests
from telethon.tl.types import DocumentAttributeFilename
def register(cb):
cb(UploadPHMod())
# @KeyZenD pls sub :3
class UploadPHMod(loader.Module):
"""Upload video and photo to telegra.ph"""
strings = {"name": "UploadPH"}
def __init__(self):
self.name = self.strings['name']
async def phcmd(self, message):
""".ph <reply photo or video>"""
if message.is_reply:
reply_message = await message.get_reply_message()
data = await check_media(reply_message)
if isinstance(data, bool):
await message.edit("<b>Reply to photo or video/gif</b>")
return
else:
await message.edit("<b>Reply to photo or video/gif</b>")
return
file = await message.client.download_media(data, bytes)
path = requests.post('https://te.legra.ph/upload', files={'file': ('file', file, None)}).json()
try:
link = 'https://te.legra.ph'+path[0]['src']
except KeyError:
link = path["error"]
await message.edit("<b>"+link+"</b>")
async def check_media(reply_message):
if reply_message and reply_message.media:
if reply_message.photo:
data = reply_message.photo
elif reply_message.document:
if DocumentAttributeFilename(file_name='AnimatedSticker.tgs') in reply_message.media.document.attributes:
return False
if reply_message.audio or reply_message.voice:
return False
data = reply_message.media.document
else:
return False
else:
return False
if not data or data is None:
return False
else:
return data

125
KeyZenD/modules/pic2pack.py Normal file
View File

@@ -0,0 +1,125 @@
from telethon import events
from telethon.errors.rpcerrorlist import YouBlockedUserError
from .. import loader, utils
import string
import random
from PIL import Image
import io
from asyncio import sleep
def register(cb):
cb(pic2packMod())
class pic2packMod(loader.Module):
"""pic2pack"""
strings = {'name': 'pic2pack'}
def __init__(self):
self.name = self.strings['name']
self._me = None
self._ratelimit = []
async def client_ready(self, client, db):
self._db = db
self._client = client
self.me = await client.get_me()
async def pic2packcmd(self, message):
""".pic2pack {packname} + <reply to photo>"""
reply = await message.get_reply_message()
if not reply:
await message.edit("<b>Reply to photo❗</b>")
return
args = utils.get_args_raw(message)
if not args:
await message.edit("<b>Packname</b>❓")
return
chat = '@Stickers'
name = "".join([random.choice(list(string.ascii_lowercase+string.ascii_uppercase)) for _ in range(16)])
emoji = "▫️"
image = io.BytesIO()
await message.client.download_file(reply, image)
image = Image.open(image)
w, h = image.size
www = max(w, h)
await message.edit("🔪<b>Cropping...</b>")
img = Image.new("RGBA", (www,www), (0,0,0,0))
img.paste(image, ((www-w)//2, 0))
face = img.resize((100,100))
fface = io.BytesIO()
fface.name = name+".png"
images = await cropping(img)
face.save(fface)
fface.seek(0)
await message.edit("<b>📤Uploading...</b>")
async with message.client.conversation(chat) as conv:
try:
x = await message.client.send_message(chat, "/cancel")
await (await conv.wait_event(events.NewMessage(incoming=True, from_users=chat))).delete()
await x.delete()
x = await message.client.send_message(chat, "/newpack")
await (await conv.wait_event(events.NewMessage(incoming=True, from_users=chat))).delete()
await x.delete()
x = await message.client.send_message(chat, args)
await (await conv.wait_event(events.NewMessage(incoming=True, from_users=chat))).delete()
await x.delete()
for im in images:
blank = io.BytesIO(im)
blank.name = name+".png"
blank.seek(0)
x = await message.client.send_file(chat, blank, force_document=True)
await (await conv.wait_event(events.NewMessage(incoming=True, from_users=chat))).delete()
await x.delete()
x = await message.client.send_message(chat, emoji)
await (await conv.wait_event(events.NewMessage(incoming=True, from_users=chat))).delete()
await x.delete()
x = await message.client.send_message(chat, "/publish")
await (await conv.wait_event(events.NewMessage(incoming=True, from_users=chat))).delete()
await x.delete()
x = await message.client.send_file(chat, fface, force_document=True)
await (await conv.wait_event(events.NewMessage(incoming=True, from_users=chat))).delete()
await x.delete()
x = await message.client.send_message(chat, name)
ending = await conv.wait_event(events.NewMessage(incoming=True, from_users=chat))
await x.delete()
await ending.delete()
for part in ending.raw_text.split():
if part.startswith("https://t.me/"):
break
await message.edit('✅<b>Uploaded successful!</b>\n'+part)
except YouBlockedUserError:
await message.edit('<b>@Stickers BLOCKED⛔</b>')
return
async def cropping(img):
(x, y) = img.size
cy = 5
cx = 5
sx = x//cx
sy = y//cy
if (sx*cx, sy*cy) != (x, y):
img = img.resize((sx*cx, sy*cy))
(lx, ly) = (0, 0)
media = []
for i in range(1, cy+1):
for o in range(1, cx+1):
mimg = img.crop((lx, ly, lx+sx, ly+sy))
mimg = mimg.resize((512,512))
bio = io.BytesIO()
bio.name = 'image.png'
mimg.save(bio, 'PNG')
media.append(bio.getvalue())
lx = lx + sx
lx = 0
ly = ly + sy
return media

23
KeyZenD/modules/print.py Normal file
View File

@@ -0,0 +1,23 @@
from .. import loader, utils
from asyncio import sleep
@loader.tds
class PrintMod(loader.Module):
"""Аналог модуля typewriter"""
strings = {"name": "print"}
@loader.owner
async def printcmd(self, message):
""".print <text or reply>"""
text = utils.get_args_raw(message)
if not text:
reply = await message.get_reply_message()
if not reply or not reply.message:
await message.edit("<b>Текста нет!</b>")
return
text = reply.message
out = ""
for ch in text:
out += ch
if ch not in [" ", "\n"]:
await message.edit(out+"\u2060")
await sleep(0.3)

44
KeyZenD/modules/pung.py Normal file
View File

@@ -0,0 +1,44 @@
from telethon import events
from telethon.errors.rpcerrorlist import YouBlockedUserError
from .. import loader, utils
from datetime import datetime
def register(cb):
cb(PingerMod())
class PingerMod(loader.Module):
"""более точный пинг"""
strings = {'name': 'PingerХуингер'}
def __init__(self):
self.name = self.strings['name']
self._me = None
self._ratelimit = []
async def client_ready(self, client, db):
self._db = db
self._client = client
self.me = await client.get_me()
async def pingcmd(self, message):
"""пингует"""
a = 5
r = utils.get_args(message)
if r and r[0].isdigit():
a = int(r[0])
ping_msg = []
ping_data = []
for _ in range(a):
start = datetime.now()
msg = await message.client.send_message("me", "ping")
end = datetime.now()
duration = (end - start).microseconds / 1000
ping_data.append(duration)
ping_msg.append(msg)
ping = sum(ping_data) / len(ping_data)
await message.edit(f"[ok] {str(ping)[0:5]}ms")
for i in ping_msg:
await i.delete()

79
KeyZenD/modules/purge.py Normal file
View File

@@ -0,0 +1,79 @@
from .. import loader, utils
import logging
import telethon
logger = logging.getLogger(__name__)
@loader.tds
class PurgeMod(loader.Module):
"""Deletes your messages"""
strings = {"name": "Purge",
"from_where": "<b>Which messages should be purged?</b>",
"not_supergroup_bot": "<b>Purges can only take place in supergroups</b>",
"delete_what": "<b>What message should be deleted?</b>"}
@loader.group_admin_delete_messages
@loader.ratelimit
async def purgecmd(self, message):
"""Purge from the replied message"""
if not message.is_reply:
await utils.answer(message, self.strings("from_where", message))
return
from_users = set()
args = utils.get_args(message)
for arg in args:
try:
entity = await message.client.get_entity(arg)
if isinstance(entity, telethon.tl.types.User):
from_users.add(entity.id)
except ValueError:
pass
msgs = []
from_ids = set()
if await message.client.is_bot():
if not message.is_channel:
await utils.answer(message, self.strings("not_supergroup_bot", message))
return
for msg in range(message.reply_to_msg_id, message.id + 1):
msgs.append(msg)
if len(msgs) >= 99:
logger.debug(msgs)
await message.client.delete_messages(message.to_id, msgs)
msgs.clear()
else:
async for msg in message.client.iter_messages(
entity=message.to_id,
min_id=message.reply_to_msg_id - 1,
reverse=True):
if from_users and msg.sender_id not in from_users:
continue
msgs.append(msg.id)
from_ids.add(msg.sender_id)
if len(msgs) >= 99:
logger.debug(msgs)
await message.client.delete_messages(message.to_id, msgs)
msgs.clear()
if msgs:
logger.debug(msgs)
await message.client.delete_messages(message.to_id, msgs)
await self.allmodules.log("purge", group=message.to_id, affected_uids=from_ids)
@loader.group_admin_delete_messages
@loader.ratelimit
async def delcmd(self, message):
"""Delete the replied message"""
msgs = [message.id]
if not message.is_reply:
if await message.client.is_bot():
await utils.answer(message, self.strings("delete_what", message))
return
msg = await message.client.iter_messages(message.to_id, 1, max_id=message.id).__anext__()
else:
msg = await message.get_reply_message()
msgs.append(msg.id)
logger.debug(msgs)
await message.client.delete_messages(message.to_id, msgs)
await self.allmodules.log("delete", group=message.to_id, affected_uids=[msg.sender_id])

117
KeyZenD/modules/pydraft.py Normal file
View File

@@ -0,0 +1,117 @@
import asyncio
import itertools
import logging
import re
import sys
import telethon
import traceback
import types
from meval import meval
from .. import loader, utils
logger = logging.getLogger(__name__)
class ModuleNotForBot(Exception):
pass
@loader.tds
class PyDraftMod(loader.Module):
"""Выполняет выражение из черновиков (работает 10 минут)
инструкция на канале @SomeScripts"""
strings = {
'name': 'PyDraft',
'on': 'PyDraft: Включен',
'off': 'PyDraft: Отключен',
'isolator': 'pydraft:',
'timer': 60 * 10,
'note': '(PyDraft) ExecNote {} не найден!',
"evaluated": "(PyDratf)Выполненное выражение:\n{}\nВозвращено:\n{}",
"execute_fail": "(PyDraft)Не удалось выполнить выражение:\n{}\nОшибка:\n{}"}
def __init__(self):
self.name = self.strings['name']
async def client_ready(self, client, db):
self.client: telethon.client.telegramclient.TelegramClient = client
self.db = db
self._db = db
async def pydraftcmd(self, message):
"""Запустить/Остановить"""
status = self.db.get(self.name, "status", False)
if not status:
self.db.set(self.name, "status", True)
self.client.loop.create_task(self.check_drafts(message))
await utils.answer(message, self.strings['on'])
else:
self.db.set(self.name, 'status', False)
await utils.answer(message, self.strings['off'])
async def pydraft(self, draft):
show = True if draft.text.startswith('!') else False
cmd = draft.text[len(self.strings['isolator'])+(1 if show else 0):].strip()
if cmd.startswith('note:'):
asset_id = self._db.get("friendly-telegram.modules.notes", "notes", {}).get(cmd.replace('note:', ''), None)
if asset_id is not None:
cmd = await self._db.fetch_asset(asset_id)
await draft.delete()
try:
it = await meval(cmd, globals(), **await self.getattrs(draft))
if show:
ret = self.strings["evaluated"].format(cmd, utils.escape_html(it))
await draft.set_message(ret)
except Exception:
exc = sys.exc_info()
exc = "".join(traceback.format_exception(exc[0], exc[1], exc[2].tb_next.tb_next.tb_next))
await draft.set_message(self.strings["execute_fail"].format(cmd, exc))
return
async def check_drafts(self, message):
msg = await self.client.send_message('me', 'PyDraft')
timer = 0
while True:
await msg.edit(f"PyDraft time left {self.strings['timer']-timer}")
if not self.db.get(self.name, "status", False):
await utils.answer(message, self.strings['off'])
break
isolator = self.strings['isolator']
drafts = await self.client.get_drafts()
for draft in drafts:
text = draft.text
if text.startswith(isolator) or text.startswith('!' + isolator):
await self.pydraft(draft)
timer += 1
await asyncio.sleep(1)
if timer >= self.strings['timer']:
self.db.set(self.name, 'status', False)
await utils.answer(message, self.strings['off'])
break
await msg.delete()
async def getattrs(self, draft):
data = {'draft':draft, "client": self.client, "self": self, "db": self.db, "chat": draft.entity.id, **self.get_types(), **self.get_functions()}
if draft.reply_to_msg_id:
data['message'] = await self.client.get_messages(draft.entity.id, ids=draft.reply_to_msg_id)
data['reply'] = await data['message'].get_reply_message()
return data
def get_types(self):
return self.get_sub(telethon.tl.types)
def get_functions(self):
return self.get_sub(telethon.tl.functions)
def get_sub(self, it, _depth=1):
"""Get all callable capitalised objects in an object recursively, ignoring _*"""
return {**dict(filter(lambda x: x[0][0] != "_" and x[0][0].upper() == x[0][0] and callable(x[1]),
it.__dict__.items())),
**dict(itertools.chain.from_iterable([self.get_sub(y[1], _depth + 1).items() for y in
filter(lambda x: x[0][0] != "_"
and isinstance(x[1], types.ModuleType)
and x[1] != it
and x[1].__package__.rsplit(".", _depth)[0]
== "telethon.tl",
it.__dict__.items())]))}

43
KeyZenD/modules/pypng.py Normal file
View File

@@ -0,0 +1,43 @@
from .. import loader, utils # pylint: disable=relative-beyond-top-level
import logging
import pygments
from pygments.lexers import Python3Lexer
from pygments.formatters import ImageFormatter
import os
logger = logging.getLogger(__name__)
def register(cb):
cb(py2pngMod())
@loader.tds
class py2pngMod(loader.Module):
"""Uploader"""
strings = {
"name": "pypng"
}
async def client_ready(self, client, db):
self.client = client
@loader.sudo
async def pypngcmd(self, message):
"""reply to text code or py file"""
await message.edit("<b>Py to PNG</b>")
reply = await message.get_reply_message()
if not reply:
await message.edit("<b>reply to file.py</b>")
return
media = reply.media
if not media:
await message.edit("<b>reply to file.py</b>")
return
file = await message.client.download_file(media)
text = file.decode('utf-8')
pygments.highlight(text, Python3Lexer(), ImageFormatter(font_name='DejaVu Sans Mono', line_numbers=True), 'out.png')
await message.client.send_file(message.to_id, 'out.png', force_document=True)
os.remove("out.png")
await message.delete()

100
KeyZenD/modules/python.py Normal file
View File

@@ -0,0 +1,100 @@
# Friendly Telegram (telegram userbot)
# Copyright (C) 2018-2019 The Authors
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging
import traceback
import sys
import itertools
import types
from meval import meval
import telethon
from .. import loader, utils
logger = logging.getLogger(__name__)
@loader.tds
class PythonMod(loader.Module):
"""Python stuff"""
strings = {"name": "Python",
"evaluated": "<b>Выполненное выражение:</b>\n<code>{}</code>\n<b>Возвращено:</b>\n<code>{}</code>",
"evaluate_fail": ("<b>(eval)Не удалось выполнить выражение:</b>\n<code>{}</code>"
"\n\n<b>Ошибка:</b>\n<code>{}</code>"),
"execute_fail": ("<b>(exec)Не удалось выполнить выражение:</b>\n<code>{}</code>"
"\n\n<b>Ошибка:</b>\n<code>{}</code>")}
async def client_ready(self, client, db):
self.client = client
self.db = db
@loader.owner
async def evalcmd(self, message):
""".eval <expression>
Evaluates python code"""
phone = message.client.phone
ret = self.strings("evaluated", message)
try:
it = await meval(utils.get_args_raw(message), globals(), **await self.getattrs(message))
except Exception:
exc = sys.exc_info()
exc = "".join(traceback.format_exception(exc[0], exc[1], exc[2].tb_next.tb_next.tb_next))
exc = exc.replace(phone, ""*len(phone))
await utils.answer(message, self.strings("evaluate_fail", message)
.format(utils.escape_html(utils.get_args_raw(message)), utils.escape_html(exc)))
return
ret = ret.format(utils.escape_html(utils.get_args_raw(message)), utils.escape_html(it))
ret = ret.replace(str(phone), ""*len(str(phone)))
await utils.answer(message, ret)
@loader.owner
async def execcmd(self, message):
""".exec <expression>
Executes python code"""
phone = message.client.phone
try:
await meval(utils.get_args_raw(message), globals(), **await self.getattrs(message))
except Exception:
exc = sys.exc_info()
exc = "".join(traceback.format_exception(exc[0], exc[1], exc[2].tb_next.tb_next.tb_next))
exc = exc.replace(str(phone), ""*len(str(phone)))
await utils.answer(message, self.strings("execute_fail", message)
.format(utils.escape_html(utils.get_args_raw(message)), utils.escape_html(exc)))
return
async def getattrs(self, message):
return {"message": message, "client": self.client, "self": self, "db": self.db,
"reply": await message.get_reply_message(), **self.get_types(), **self.get_functions(),
"event": message, "chat": message.to_id}
def get_types(self):
return self.get_sub(telethon.tl.types)
def get_functions(self):
return self.get_sub(telethon.tl.functions)
def get_sub(self, it, _depth=1):
"""Get all callable capitalised objects in an object recursively, ignoring _*"""
return {**dict(filter(lambda x: x[0][0] != "_" and x[0][0].upper() == x[0][0] and callable(x[1]),
it.__dict__.items())),
**dict(itertools.chain.from_iterable([self.get_sub(y[1], _depth + 1).items() for y in
filter(lambda x: x[0][0] != "_"
and isinstance(x[1], types.ModuleType)
and x[1] != it
and x[1].__package__.rsplit(".", _depth)[0]
== "telethon.tl",
it.__dict__.items())]))}

View File

@@ -0,0 +1,40 @@
import logging
from .. import loader, utils
logger = logging.getLogger(__name__)
@loader.tds
class RysianskiyMod(loader.Module):
"""Perevodit rysskiy na rysianskiy yazyk"""
strings = {"name": "Rysianskiy yazyk",
"nety_teksta": "<b>Nety teksta dlya izmeneniya!</b>"}
async def client_ready(self, client, db):
self.client = client
@loader.owner
async def rysianskiycmd(self, soobshenie):
""".rysianskiy <tekst ili replay na tekst>"""
otvet = await soobshenie.get_reply_message()
vvod = utils.get_args_raw(soobshenie)
if not vvod:
if not otvet or not otvet.text:
await utils.answer(soobshenie, self.strings("nety_teksta", soobshenie))
return
else:
tekst = otvet.raw_text
else:
tekst = vvod
vyvod = ""
for simvol in tekst:
if simvol.lower() in bykvy:
bykva = bykvy[simvol.lower()]
if simvol.isupper():
bykva = bykva.upper()
else:
bykva = simvol
vyvod += bykva
await utils.answer(soobshenie, vyvod)
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"}

24
KeyZenD/modules/saved.py Normal file
View File

@@ -0,0 +1,24 @@
import io
from .. import loader, utils
@loader.tds
class SavedMod(loader.Module):
"""Соxранятель в избранное"""
strings = {"name": "SavedMessages", "to":"me"}
@loader.unrestricted
async def savedcmd(self, message):
""".saved реплай на медиа"""
await message.delete()
reply = await message.get_reply_message()
name = utils.get_args_raw(message)
if not reply or not reply.file:
return
media = reply.media
if media.ttl_seconds or name:
file = await reply.download_media(bytes)
file = io.BytesIO(file)
file.name = name or str(reply.sender_id) + reply.file.ext
file.seek(0)
await message.client.send_file(self.strings["to"], file)
else:
await reply.forward_to(self.strings["to"])

34
KeyZenD/modules/scrs.py Normal file
View File

@@ -0,0 +1,34 @@
from .. import loader, utils
from telethon import events, errors, functions, types
def register(cb):
cb(ScrSpamMod())
class ScrSpamMod(loader.Module):
"""Screenshot Spammer by @KeyZenD"""
strings = {'name': 'ScrSpam'}
def __init__(self):
self.name = self.strings['name']
self._me = None
self._ratelimit = []
async def client_ready(self, client, db):
self._db = db
self._client = client
self.me = await client.get_me()
async def scrscmd(self, message):
""".scrs <amount>"""
a = 1
r = utils.get_args(message)
if r and r[0].isdigit():
a = int(r[0])
await message.edit("Screenshoting...")
for _ in range(a):
await message.client(functions.messages.SendScreenshotNotificationRequest(peer=message.to_id, reply_to_msg_id=message.id))
await message.delete()

106
KeyZenD/modules/soaper.py Normal file
View File

@@ -0,0 +1,106 @@
# -*- coding: utf-8 -*-
# Friendly Telegram (telegram userbot)
# Copyright (C) 2018-2020 The Authors
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# если не подписан на t.me/keyzend
# твоя мама шлюха
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from .. import loader, utils # pylint: disable=relative-beyond-top-level
import io
from PIL import Image, ImageOps
from telethon.tl.types import DocumentAttributeFilename
import logging
import random
logger = logging.getLogger(__name__)
def register(cb):
cb(SoaperMod())
@loader.tds
class SoaperMod(loader.Module):
"""Гавно залупное"""
strings = {
"name": "Soaping"
}
async def client_ready(self, client, db):
self.client = client
@loader.sudo
async def soapcmd(self, message):
""".soap <reply to photo>"""
soap = 3
a = utils.get_args(message)
if a:
if a[0].isdigit():
soap = int(a[0])
if soap <= 0:
soap = 3
if message.is_reply:
reply_message = await message.get_reply_message()
data = await check_media(reply_message)
if isinstance(data, bool):
await utils.answer(message, "<code>Reply to pic or stick!</code>")
return
else:
await utils.answer(message, "<code>Reply to pic or stick!</code>")
return
await message.edit("Soaping...")
file = await self.client.download_media(data, bytes)
media = await Soaping(file, soap)
await message.delete()
await message.client.send_file(message.to_id, media)
async def Soaping(file, soap):
img = Image.open(io.BytesIO(file))
(x, y) = img.size
img = img.resize((x//soap, y//soap), Image.ANTIALIAS)
img = img.resize((x, y))
soap_io = io.BytesIO()
soap_io.name = "image.jpeg"
img = img.convert("RGB")
img.save(soap_io, "JPEG", quality=100)
soap_io.seek(0)
return soap_io
async def check_media(reply_message):
if reply_message and reply_message.media:
if reply_message.photo:
data = reply_message.photo
elif reply_message.document:
if DocumentAttributeFilename(file_name='AnimatedSticker.tgs') in reply_message.media.document.attributes:
return False
if reply_message.gif or reply_message.video or reply_message.audio or reply_message.voice:
return False
data = reply_message.media.document
else:
return False
else:
return False
if not data or data is None:
return False
else:
return data

123
KeyZenD/modules/spinner.py Normal file
View File

@@ -0,0 +1,123 @@
# -*- coding: utf-8 -*-
# Friendly Telegram (telegram userbot)
# Copyright (C) 2018-2020 The Authors
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from .. import loader, utils # pylint: disable=relative-beyond-top-level
import io
from PIL import Image, ImageOps
from telethon.tl.types import DocumentAttributeFilename
import logging
import random
logger = logging.getLogger(__name__)
def register(cb):
cb(SpinnerMod())
@loader.tds
class SpinnerMod(loader.Module):
"""Гавно залупное"""
strings = {
"name": "Spinner"
}
async def client_ready(self, client, db):
self.client = client
@loader.sudo
async def spincmd(self, message):
"""you spin me round..."""
args = utils.get_args(message)
if message.is_reply:
reply_message = await message.get_reply_message()
data = await check_media(reply_message)
if isinstance(data, bool):
await utils.answer(message, "<code>Реплай на пикчу или стикер блять!</code>")
return
else:
await utils.answer(message, "`Реплай на пикчу или стикер блять`")
return
image = io.BytesIO()
await self.client.download_media(data, image)
image = Image.open(image)
image.thumbnail((512, 512), Image.ANTIALIAS)
img = Image.new("RGB", (512, 512), "black")
img.paste(image, ((512-image.width)//2, (512-image.height)//2))
image = img
way = random.choice([1, -1])
frames = []
for i in range(1, 60):
im = image.rotate(i*6*way)
frames.append(im)
frames.remove(im)
image_stream = io.BytesIO()
image_stream.name = "spin.gif"
im.save(image_stream, "GIF", save_all=True, append_images=frames, duration = 10)
image_stream.seek(0)
await utils.answer(message, image_stream)
@loader.sudo
async def epilepsycmd(self, message):
"""ПРИВЕТ ЭПИЛЕТИКИ АХАХАХХА"""
args = utils.get_args(message)
if message.is_reply:
reply_message = await message.get_reply_message()
data = await check_media(reply_message)
if isinstance(data, bool):
await utils.answer(message, "<code>Реплай на пикчу или стикер блять!</code>")
return
else:
await utils.answer(message, "`Реплай на пикчу или стикер блять`")
return
image = io.BytesIO()
await self.client.download_media(data, image)
image = Image.open(image).convert("RGB")
invert = ImageOps.invert(image)
image_stream = io.BytesIO()
image_stream.name = "epilepsy.gif"
image.save(image_stream, "GIF", save_all=True, append_images=[invert], duration = 1)
image_stream.seek(0)
await utils.answer(message, image_stream)
async def check_media(reply_message):
if reply_message and reply_message.media:
if reply_message.photo:
data = reply_message.photo
elif reply_message.document:
if DocumentAttributeFilename(file_name='AnimatedSticker.tgs') in reply_message.media.document.attributes:
return False
if reply_message.gif or reply_message.video or reply_message.audio or reply_message.voice:
return False
data = reply_message.media.document
else:
return False
else:
return False
if not data or data is None:
return False
else:
return data

63
KeyZenD/modules/stext.py Normal file
View File

@@ -0,0 +1,63 @@
from .. import loader, utils
import io
import logging
import requests
from textwrap import wrap
from PIL import Image, ImageDraw, ImageFont
bytes_font = requests.get("https://github.com/KeyZenD/l/blob/master/bold.ttf?raw=true").content
logger = logging.getLogger(__name__)
def register(cb):
cb(Text2stickMod())
@loader.tds
class Text2stickMod(loader.Module):
"""Text to sticker"""
strings = {"name": "StickText"}
async def client_ready(self, client, db):
self.client = client
@loader.owner
async def stextcmd(self, message):
""".stext <reply to photo>"""
await message.delete()
text = utils.get_args_raw(message)
reply = await message.get_reply_message()
if not text:
if not reply:
text = "#ffffff .stext <text or reply>"
elif not reply.message:
text = "#ffffff .stext <text or reply>"
else:
text = reply.raw_text
color = text.split(" ", 1)[0]
if color.startswith("#") and len(color) == 7:
for ch in color.lower()[1:]:
if ch not in "0123456789abcdef":
break
if len(text.split(" ", 1)) > 1:
text = text.split(" ", 1)[1]
else:
if reply:
if reply.message:
text = reply.raw_text
else:
color = "#FFFFFF"
txt = []
for line in text.split("\n"):
txt.append("\n".join(wrap(line, 30)))
text = "\n".join(txt)
font = io.BytesIO(bytes_font)
font = ImageFont.truetype(font, 100)
image = Image.new("RGBA", (1, 1), (0,0,0,0))
draw = ImageDraw.Draw(image)
w, h = draw.multiline_textsize(text=text, font=font)
image = Image.new("RGBA", (w+100, h+100), (0,0,0,0))
draw = ImageDraw.Draw(image)
draw.multiline_text((50,50), text=text, font=font, fill=color, align="center")
output = io.BytesIO()
output.name = color+".webp"
image.save(output, "WEBP")
output.seek(0)
await self.client.send_file(message.to_id, output, reply_to=reply)

52
KeyZenD/modules/tagall.py Normal file
View File

@@ -0,0 +1,52 @@
from .. import loader, utils
import logging
logger = logging.getLogger(__name__)
def register(cb):
cb(TagallMod())
@loader.tds
class TagallMod(loader.Module):
"""Tagall"""
strings = {
"name": "TagAll", "subscribe to": "https://t.me/KeyZenD"
}
async def client_ready(self, client, db):
self.client = client
def __init__(self):
self.name = self.strings['name']
@loader.sudo
async def tagallcmd(self, message):
args = utils.get_args(message)
tag_ = 5
notext = False
if args:
if args[0].isdigit():
tag_ = int(args[0])
if len(args) > 1:
notext = True
text = " ".join(args[1:])
await message.delete()
all = message.client.iter_participants(message.to_id)
chunk = []
async for user in all:
if not user.deleted:
name = f"{user.first_name} {user.last_name}" if user.last_name else user.first_name
name = name.replace("<","&lt;").replace(">","&gt;")
name = name[:30]+"..." if len(name) > 33 else name
tag = f'<a href="tg://user?id={user.id}">{name}</a>' if not notext else f'<a href="tg://user?id={user.id}">{text}</a>'
chunk.append(tag)
if len(chunk) == tag_:
await message.client.send_message(message.to_id, "\n".join(chunk))
chunk = []
if len(chunk) != 0:
await message.client.send_message(message.to_id, "\n".join(chunk))

132
KeyZenD/modules/test.py Normal file
View File

@@ -0,0 +1,132 @@
# Friendly Telegram (telegram userbot)
# Copyright (C) 2018-2019 The Authors
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging
import time
from datetime import datetime
from io import BytesIO
from .. import loader, utils
logger = logging.getLogger(__name__)
@loader.test(args=None)
async def dumptest(conv):
m = await conv.send_message("test")
await conv.send_message(".dump", reply_to=m)
r = await conv.get_response()
assert r.message.startswith("Message(") and "test" in r.message, r
@loader.test(args="0")
async def logstest(conv):
r = await conv.get_response()
assert r.message == "Loading media...", r
r2 = await conv.get_response()
assert r2.document, r2
@loader.tds
class TestMod(loader.Module):
"""Self-tests"""
strings = {"name": "Tester",
"pong": ".pong",
"bad_loglevel": "<b>Не верный уровень логов.</b>",
"uploading_logs": "<b>Собираю логи...</b>",
"no_logs": "<b>Логов с уровнем {} нет.</b>",
"logs_filename": "FTG-Logs[{}].txt",
"logs_unsafe": ("<b>Если ты точно хочешь показать логи с уровнем {lvl}, то напиши </b><code>.logs {lvl} {force}</code>"),
"logs_force": "FORCE_INSECURE",
"suspend_invalid_time": "<b>Invalid time to suspend</b>"}
@loader.test(resp="Pong")
@loader.unrestricted
async def pingcmd(self, message):
"""Does nothing"""
await utils.answer(message, self.strings("pong", message))
@loader.owner
async def pungcmd(self, message):
"""Useless pinger"""
a = 5
r = utils.get_args(message)
if r and r[0].isdigit():
a = int(r[0])
ping_msg = []
ping_data = []
for _ in range(a):
start = datetime.now()
msg = await message.client.send_message("me", "ping")
end = datetime.now()
duration = (end - start).microseconds / 1000
ping_data.append(duration)
ping_msg.append(msg)
ping = sum(ping_data) / len(ping_data)
await message.edit(f"<code>[ ping {str(ping)[0:5]}ms ]</code>")
for i in ping_msg:
await i.delete()
@loader.test(func=dumptest)
async def dumpcmd(self, message):
"""Use in reply to get a dump of a message"""
if not message.is_reply:
return
await utils.answer(message, "<code>"
+ utils.escape_html((await message.get_reply_message()).stringify()) + "</code>")
@loader.test(func=logstest)
async def logscmd(self, message):
""".logs <level>
Dumps logs. Loglevels below WARNING may contain personal info."""
args = utils.get_args(message)
if not len(args) == 1 and not len(args) == 2:
args = ["40"]
try:
lvl = int(args[0])
except ValueError:
# It's not an int. Maybe it's a loglevel
lvl = getattr(logging, args[0].upper(), None)
if not isinstance(lvl, int):
await utils.answer(message, self.strings("bad_loglevel", message))
return
if not (lvl >= logging.WARNING or (len(args) == 2 and args[1] == self.strings("logs_force", message))):
await utils.answer(message,
self.strings("logs_unsafe", message).format(lvl=lvl, force=self.strings("logs_force", message)))
return
[handler] = logging.getLogger().handlers
logs = ("\n".join(handler.dumps(lvl))).encode("utf-8")
if not len(logs) > 0:
await utils.answer(message, self.strings("no_logs", message).format(lvl))
return
logs = BytesIO(logs)
logs.name = self.strings("logs_filename", message).format(lvl)
await utils.answer(message, logs)
@loader.owner
async def suspendcmd(self, message):
""".suspend <time>
Suspends the bot for N seconds"""
# Blocks asyncio event loop, preventing ANYTHING happening (except multithread ops,
# but they will be blocked on return).
try:
time.sleep(int(utils.get_args_raw(message)))
except ValueError:
await utils.answer(message, self.strings("suspend_invalid_time", message))
async def client_ready(self, client, db):
self.client = client

45
KeyZenD/modules/ticker.py Normal file
View File

@@ -0,0 +1,45 @@
# Friendly Telegram (telegram userbot)
# Copyright (C) 2018-2019 The Authors
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# SUBSCRIBE TO t.me/keyzend pls
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from .. import loader, utils
import logging
import asyncio
logger = logging.getLogger(__name__)
@loader.tds
class TickerMod(loader.Module):
"""Makes your messages type slower"""
strings = {"name": "Ticker",
"no_message": "<b>.ticker [any text?]</b>",
"delay_typer_cfg_doc": "How long to delay showing?"}
def __init__(self):
self.config = loader.ModuleConfig("DELAY_TICKER", 0.04, lambda m: self.strings("delay_tikcer_cfg_doc", m))
@loader.ratelimit
async def tickercmd(self, message):
""".ticker <message>"""
a = utils.get_args_raw(message)
if not a:
await utils.answer(message, self.strings("no_message", message))
return
for c in a:
a = a[-1]+a[0:-1]
message = await utils.answer(message, f" {a} ")
await asyncio.sleep(0.3)

31
KeyZenD/modules/ttdl.py Normal file
View File

@@ -0,0 +1,31 @@
from requests import head,get
from urllib.parse import urlsplit as E,parse_qs as H
import json,io,re
from .. import loader as A,utils
class TikTokDlMod(A.Module):
strings={'name':'TikTokDl'}
async def ttcmd(J,message):
A=message;B=await A.get_reply_message();F=utils.get_args_raw(A);C=lambda x:f"<b>{x}</b>"
if F:D=F
elif B and B.raw_text:D=B.raw_text
else:return await A.edit(C('No url.'))
if'.tiktok.com'not in D:return await A.edit(C('Bad url.'))
await A.edit(C('Loading...'));G,K=await I(D)
try:await A.client.send_file(A.to_id,file=G,reply_to=B);await A.delete()
except:
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()
except:await A.edit(C('я чёт нихуя не могу загрузить...'))
async def I(url):
A=url
async def F(video_id,_):
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')
if not B:return 0,0,A
return B,True,A
A=head(A).headers;A=A.get('Location')
try:
I=H(E(A).query);B=I.get('share_item_id')[0];G,C,D=await F(B,1)
if not C:raise
except:
B=''.join(re.findall('[0-9]',E(A).path.split('/')[-1]));G,C,D=await F(B,2)
if not C:return False,D
return G[0]['video']['bit_rate'][0]['play_addr']['url_list'][-1],D

72
KeyZenD/modules/urldl.py Normal file
View File

@@ -0,0 +1,72 @@
from .. import loader, utils
import io
from telethon.tl.types import MessageEntityUrl, MessageEntityTextUrl
import os
import aiohttp
class aMod(loader.Module):
strings = {"name": "UrlDl"}
async def urldlcmd(self, event):
await downloading(event)
async def urldlbigcmd(self, event):
await downloading(event, True)
async def downloading(event, big=False):
args = utils.get_args_raw(event)
reply = await event.get_reply_message()
if not args:
if not reply:
await event.edit("<b>Ссылки нету!</b>")
return
message = reply
else:
message = event
if not message.entities:
await event.edit("<b>Ссылки нету!</b>")
return
urls = []
for ent in message.entities:
if type(ent) in [MessageEntityUrl, MessageEntityTextUrl]:
url_ = True
if type(ent) == MessageEntityUrl:
offset = ent.offset
length = ent.length
url = message.raw_text[offset:offset+length]
else:
url = ent.url
if not url.startswith("http"):
url = "http://"+url
urls.append(url)
if not urls:
await event.edit("<b>Ссылки нету!</b>")
return
async with aiohttp.ClientSession() as session:
for url in urls:
try:
await event.edit("<b>Загрузка...</b>\n"+url)
fname = url.split("/")[-1]
async with session.get(url) as response:
if big:
f = open(fname, "wb")
async for chunk in response.content.iter_chunked(1024):
f.write(chunk)
f.close()
await event.edit("<b>Отправка...</b>\n"+url)
await event.client.send_file(event.to_id, open(fname, "rb"), reply_to=reply)
os.remove(fname)
else:
file = io.BytesIO(await response.read())
file.name = fname
file.seek(0)
await event.edit("<b>Отправка...</b>\n"+url)
await event.client.send_file(event.to_id, file, reply_to=reply)
except Exception as e:
await event.reply("<b>Ошибка при загрузке!</b>\n"+url+"\n<code>"+str(e)+"</code>")
await event.delete()

41
KeyZenD/modules/valute.py Normal file
View File

@@ -0,0 +1,41 @@
import asyncio
import logging
from requests import get
from .. import loader, utils
logger = logging.getLogger(__name__)
@loader.tds
class ValitesMod(loader.Module):
"""Valute converter"""
strings = {"name": "Valutes"}
@loader.unrestricted
async def valutecmd(self, message):
""".valute <Valute char code (optional)>"""
valutes = get("https://www.cbr-xml-daily.ru/daily_json.js").json()
names = valutes["Valute"].keys()
args = utils.get_args(message)
req = []
if args:
for val in args:
val = val.upper()
if val in names:
req.append(val)
valutes["Valute"] = {val: valutes["Valute"][val] for val in req}
text = []
temp = "<b>{}</b>\n{} <code>{}</code>: {}₽ ({}{}₽)"
for val in valutes["Valute"].values():
name = val["Name"]
code = val["CharCode"]
nom = int(val["Nominal"])
now = round(float(val["Value"]), 3)
pre = round(float(val["Previous"]), 3)
way = "🔹" if now == pre else "🔻" if now < pre else "🔺"
text.append(temp.format(name, nom, code, now, way, pre))
if not text:
return await utils.answer(message, "<b>Запрос неверен - ответ пуст!</b>")
await utils.answer(message, "\n".join(text))

View File

@@ -0,0 +1,48 @@
from .. import loader, utils
import logging
from requests import get
import io
logger = logging.getLogger(__name__)
def register(cb):
cb(WebShotMod())
@loader.tds
class WebShotMod(loader.Module):
"""link to screen"""
strings = {
"name": "WebShot"
}
async def client_ready(self, client, db):
self.client = client
def __init__(self):
self.name = self.strings['name']
@loader.sudo
async def webshotcmd(self, message):
reply = None
link = utils.get_args_raw(message)
if not link:
reply = await message.get_reply_message()
if not reply:
await message.delete()
return
link = reply.raw_text
await message.edit("<b>S c r e e n s h o t i n g . . .</b>")
url = "https://webshot.deam.io/{}/?width=1920&height=1080?type=png"
file = get(url.format(link))
if not file.ok:
await message.edit("<b>Something went wrong...</b>")
return
file = io.BytesIO(file.content)
file.name = "webshot.png"
file.seek(0)
await message.client.send_file(message.to_id, file, reply_to=reply)
await message.delete()

37
KeyZenD/modules/what.py Normal file
View File

@@ -0,0 +1,37 @@
from .. import loader, utils
from PIL import Image, ImageDraw
from random import randint
from io import BytesIO
@loader.tds
class WhatMod(loader.Module):
"""wow, what is it there?"""
strings = {"name": "What?"}
async def whatcmd(self, message):
"""Draw circle in random place"""
args = utils.get_args_raw(message)
scale = int(args) if args and args.isdigit() else 50
scale = 10 if scale < 0 else scale
scale = 100 if scale > 100 else scale
reply = await message.get_reply_message()
if not reply or not reply.file.mime_type.split("/")[0].lower() == "image":
await message.edit("<b>Reply to img!</b>")
return
await message.edit("<b>What is it?</b>")
im = BytesIO()
await reply.download_media(im)
im = Image.open(im)
w, h = im.size
f = (min(w,h)//100)*scale
draw = ImageDraw.Draw(im)
x, y = randint(0, w-f), randint(0, h-f)
draw.ellipse((x, y, x+randint(f//2, f), y+randint(f//2, f)), fill=None, outline="red", width=randint(3, 10))
out = BytesIO()
out.name = "what.png"
im.save(out)
out.seek(0)
await message.delete()
return await reply.reply(file=out)

30
KeyZenD/modules/words.py Normal file
View File

@@ -0,0 +1,30 @@
from .. import loader
import io
class WordsMod(loader.Module):
strings = {"name": "Words Counter"}
async def wordscmd(self, message):
reply = await message.get_reply_message()
object = reply.sender_id if reply else message.sender_id
chat = message.to_id
await message.edit("<b>Сбор статистики...</b>")
_words = {}
async for msg in message.client.iter_messages(chat, from_user=object):
if msg and msg.raw_text:
words = set("".join(map(lambda x: x if (x in [" "] or x.isalpha()) else " ", msg.raw_text)).lower().split())
for word in words:
count = msg.raw_text.lower().count(word)
_words[word] = _words.get(word, 0) + count
all = list(_words.items())
all.sort(key=lambda i: i[1])
response = ""
for word in all[::-1]:
response += f"{word[0]}: {word[1]}\n"
file = io.BytesIO(bytes(response, "utf-8"))
file.name = f"ID:{object}.txt"
await message.reply(file=file)
await message.delete()

111
KeyZenD/modules/zip.py Normal file
View File

@@ -0,0 +1,111 @@
from .. import loader, utils
import os
import urllib.parse
from uuid import uuid4
ztd = 'zip-temp-dir'
@loader.tds
class ZipMod(loader.Module):
'''Запаковывает/распаковывает файлы'''
strings = {'name': 'ZIP'}
@loader.unrestricted
async def zipaddcmd(self, message):
""".zipadd <file/reply to file> - сохраняет файл во временную папку"""
reply = await message.get_reply_message()
event = reply or message
if not event.file:
await message.edit('<b>[ZIP]Добавить что?<b>')
return
if not os.path.exists(ztd):
os.mkdir(ztd)
fn = _fn = event.file.name
if not fn:
date = event.date
kind = event.file.mime_type.split('/')[0]
ext = event.file.ext
fn = _fn = '{}_{}-{:02}-{:02}_{:02}-{:02}-{:02}{}'.format(kind, date.year, date.month, date.day, date.hour, date.minute, date.second, ext)
files = os.listdir(ztd)
copy = 1
while fn in files:
fn = f"({copy}).{_fn}"
copy += 1
await message.edit(f'<b>[ZIP]Загружаю файл \'</b><code>{fn}</code>\'...')
await event.download_media(f'{ztd}/{fn}')
await message.edit(f"<b>[ZIP]Файл \"</b><code>{fn}</code><b>\" загружен!</b>")
@loader.unrestricted
async def ziplistcmd(self, message):
"""список сохраненных файлов"""
if not os.path.exists(ztd):
await message.edit('<b>[ZIP]В папке пусто!</b>')
return
files = os.listdir(ztd)
files = '\n'.join([f'<a href="tg://msg?text=.zipshow+{urllib.parse.quote(fn)}">{num+1})</a> <code>{fn}</code>' for num, fn in enumerate(files)])
await message.edit('<b>[ZIP]Список файлов:</b>\n'+files)
@loader.unrestricted
async def zipshowcmd(self, message):
""".zipshow <name> - показывает сохранённый файл"""
if not os.path.exists(ztd):
await message.edit('<b>[ZIP]В папке пусто!</b>')
return
files = os.listdir(ztd)
file = utils.get_args_raw(message)
if not file:
await message.edit('<b>[ZIP]Пустой запрос!</b>')
return
if file not in files:
await message.edit('<b>[ZIP]Такого файла нет!</b>')
return
await message.edit(f"<b>[ZIP]Отправляю \"</b><code>{file}</code><b>\"...")
await message.respond(file=ztd+"/"+file)
await message.delete()
@loader.unrestricted
async def zipdelcmd(self, message):
""".zipdel <name> - удаляет сохранённый файл"""
file = utils.get_args_raw(message)
try:
os.remove(ztd+"/"+file)
except FileNotFoundError:
await message.edit("<b>[ZIP]Такого файла нет!</b>")
return
await message.edit(f"<b>[ZIP]Файл \"</b><code>{file}</code><b>\" удалён!</b>")
@loader.unrestricted
async def zipcmd(self, message):
""".zip <name> (-s) - пакует в архив name. если есть флаг -s то сохраняет папку с фацлами"""
if not os.path.exists(ztd):
await message.edit("<b>[ZIP]Файлов для запаковки не найдено!</b>")
return
name = utils.get_args_raw(message)
save = False
if "-s" in name:
save = True
name = name.replace("-s","").strip()
if not name:
name = str(uuid4()).split("-")[-1]+".zip"
name = name + (".zip" if ".zip" not in name else "")
await message.edit(f'<b>[ZIP]Запаковываю {len(os.listdir(ztd))} файл(ов) в </b>"<code>{name}</code>"')
os.system(f"zip {name} {ztd}/*")
await message.edit(f'<b>[ZIP]Отправляю </b>"<code>{name}</code>"')
await message.respond(file=open(name, "rb"))
await message.delete()
os.system("rm -rf {name}")
if not save:
os.system("rm -rf zip-temp-dir")
@loader.unrestricted
async def zipcleancmd(self, message):
""".zipclear - очищает папку с файлами"""
os.system("rm -rf zip-temp-dir")
await message.edit('<b>[ZIP]Очищено!</b>')
os.mkdir(ztd)

View File

@@ -0,0 +1,32 @@
from asyncio import sleep
from .. import loader, utils
def register(cb):
cb(ЗаёбушкаMod())
class ЗаёбушкаMod(loader.Module):
"""Заебет любого"""
strings = {'name': 'Заёбушка'}
async def заебуcmd(self, message):
""".заебу <колличество> <реплай на того, кого заебать>"""
reply = await message.get_reply_message()
if not reply:
await message.edit("<b>А кого заёбывать-то?</b>")
return
id = reply.sender_id
args = utils.get_args(message)
count = 50
if args:
if args[0].isdigit():
if int(args[0]) < 0:
count = 50
else:
count = int(args[0])
txt = '<a href="tg://user?id={}">Заёбушка :3</a>'.format(id)
await message.delete()
for _ in range(count):
await sleep(0.3)
msg = await message.client.send_message(message.to_id, txt)
await sleep(0.3)
await msg.delete()

View File

@@ -0,0 +1,41 @@
from asyncio import sleep
from .. import loader, utils
def register(cb):
cb(ЗаёбушкаMod())
class ЗаёбушкаMod(loader.Module):
"""Заебет любого"""
strings = {'name': 'Заёбушка'}
def __init__(self):
self.name = self.strings['name']
self._me = None
self._ratelimit = []
async def заебуcmd(self, message):
""".заебу <колличество> <реплай на того, кого заебать>"""
reply = await message.get_reply_message()
if not reply:
await message.edit("<b>А кого заёбывать-то?</b>")
return
id = reply.sender_id
args = utils.get_args(message)
count = 50
if args:
if args[0].isdigit():
if int(args[0]) < 0:
count = 50
else:
count = int(args[0])
txt = '<a href="tg://user?id={}">{}</a>'
await message.edit(txt.format(id, "Я тебя заебу!"))
for _ in range(count):
await sleep(0.3)
msg = await message.client.send_message(message.to_id, txt.format(id, "Заёбушка:3"), reply_to=message)
if not msg.is_reply:
await msg.edit("<b>Остановлено!</b>")
break
await sleep(0.3)
await msg.delete()