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

62
D4n13l3k00/FTG-Modules/.gitignore vendored Normal file
View File

@@ -0,0 +1,62 @@
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
.env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
stuf

View File

@@ -0,0 +1,4 @@
{
"python.pythonPath": "C:\\Users\\D4n13l3k00\\AppData\\Local\\Programs\\Python\\Python39\\python.exe",
"python.analysis.typeCheckingMode": "off"
}

View File

@@ -0,0 +1,346 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
# requires: pydub numpy requests
import io
import math
import re
import aiohttp
import numpy as np
from pydub import AudioSegment, effects
from telethon import types
from .. import loader, utils # type: ignore
@loader.tds
class AudioEditorMod(loader.Module):
"""Module for working with sound"""
strings = {
"name": "AudioEditor",
"downloading": "<b>[{}]</b> Downloading...",
"working": "<b>[{}]</b> Working...",
"exporting": "<b>[{}]</b> Exporting...",
"set_value": "<b>[{}]</b> Specify the level from {} to {}...",
"reply": "<b>[{}]</b> reply to audio...",
"set_fmt": "<b>[{}]</b> Specify the format of output audio...",
"set_time": "<b>[{}]</b> Specify the time in the format start(ms):end(ms)",
}
@loader.owner
async def basscmd(self, m):
""".bass [level bass'а 2-100 (Default 2)] <reply to audio>
BassBoost"""
args = utils.get_args_raw(m)
if not args:
lvl = 2.0
elif re.match(r"^\d+(\.\d+)?$", args) and (1.0 < float(args) < 100.1):
lvl = float(args)
else:
return await utils.answer(
m, self.strings("set_value", m).format("BassBoost", 2.0, 100.0)
)
audio = await self.get_audio(m, "BassBoost")
if not audio:
return
sample_track = list(audio.audio.get_array_of_samples())
out = (audio.audio - 0).overlay(
audio.audio.low_pass_filter(
int(
round(
(
3 * np.std(sample_track) / (math.sqrt(2))
- np.mean(sample_track)
)
* 0.005
)
)
)
+ lvl
)
await self.send_audio(m, audio, out, audio.pref, f"{audio.pref} {lvl}lvl")
@loader.owner
async def fvcmd(self, m):
""".fv [level 2-100 (Default 25)] <reply to audio>
Distort"""
args = utils.get_args_raw(m)
if not args:
lvl = 25.0
elif re.match(r"^\d+(\.\d+)?$", args) and (1.0 < float(args) < 100.1):
lvl = float(args)
else:
return await utils.answer(
m, self.strings("set_value", m).format("Distort", 2.0, 100.0)
)
audio = await self.get_audio(m, "Distort")
if not audio:
return
out = audio.audio + lvl
await self.send_audio(m, audio, out, audio.pref, f"{audio.pref} {lvl}lvl")
@loader.owner
async def echoscmd(self, m):
""".echos <reply to audio>
Echo effect"""
audio = await self.get_audio(m, "Echo")
if not audio:
return
out = AudioSegment.empty()
n = 200
none = io.BytesIO()
out += audio.audio + AudioSegment.from_file(none)
for _ in range(5):
audio.audio - 10
out = out.overlay(audio.audio, n)
n += 200
await self.send_audio(audio.message, audio, out, audio.pref, audio.pref)
@loader.owner
async def volupcmd(self, m):
""".volup <reply to audio>
VolUp 10dB"""
audio = await self.get_audio(m, "+10dB")
if not audio:
return
out = audio.audio + 10
await self.send_audio(audio.message, audio, out, audio.pref, audio.pref)
@loader.owner
async def voldwcmd(self, m):
""".voldw <reply to audio>
VolDw 10dB"""
audio = await self.get_audio(m, "-10dB")
if not audio:
return
out = audio.audio - 10
await self.send_audio(audio.message, audio, out, audio.pref, audio.pref)
@loader.owner
async def revscmd(self, m):
""".revs <reply to audio>
Reverse audio"""
audio = await self.get_audio(m, "Reverse")
if not audio:
return
out = audio.audio.reverse()
await self.send_audio(audio.message, audio, out, audio.pref, audio.pref)
@loader.owner
async def repscmd(self, m):
""".reps <reply to audio>
Repeat audio 2 times"""
audio = await self.get_audio(m, "Repeat")
if not audio:
return
out = audio.audio * 2
await self.send_audio(audio.message, audio, out, audio.pref, audio.pref)
@loader.owner
async def slowscmd(self, m):
""".slows <reply to audio>
SlowDown 0.5x"""
audio = await self.get_audio(m, "SlowDown")
if not audio:
return
s2 = audio.audio._spawn(
audio.audio.raw_data,
overrides={"frame_rate": int(audio.audio.frame_rate * 0.5)},
)
out = s2.set_frame_rate(audio.audio.frame_rate)
await self.send_audio(
audio.message, audio, out, audio.pref, audio.pref, audio.duration * 2
)
@loader.owner
async def fastscmd(self, m):
""".fasts <reply to audio>
SpeedUp 1.5x"""
audio = await self.get_audio(m, "SpeedUp")
if not audio:
return
s2 = audio.audio._spawn(
audio.audio.raw_data,
overrides={"frame_rate": int(audio.audio.frame_rate * 1.5)},
)
out = s2.set_frame_rate(audio.audio.frame_rate)
await self.send_audio(
audio.message,
audio,
out,
audio.pref,
audio.pref,
round(audio.duration / 2),
)
@loader.owner
async def rightscmd(self, m):
""".rights <reply to audio>
Push sound to right channel"""
audio = await self.get_audio(m, "Right channel")
if not audio:
return
out = effects.pan(audio.audio, +1.0)
await self.send_audio(audio.message, audio, out, audio.pref, audio.pref)
@loader.owner
async def leftscmd(self, m):
""".lefts <reply to audio>
Push sound to left channel"""
audio = await self.get_audio(m, "Left channel")
if not audio:
return
out = effects.pan(audio.audio, -1.0)
await self.send_audio(audio.message, audio, out, audio.pref, audio.pref)
@loader.owner
async def normscmd(self, m):
""".norms <reply to audio>
Normalize sound (from quiet to normal)"""
audio = await self.get_audio(m, "Normalization")
if not audio:
return
out = effects.normalize(audio.audio)
await self.send_audio(audio.message, audio, out, audio.pref, audio.pref)
@loader.owner
async def tovscmd(self, m):
""".tovs <reply to audio>
Convert to voice message"""
audio = await self.get_audio(m, "Voice")
if not audio:
return
audio.voice = True
await self.send_audio(audio.message, audio, audio.audio, audio.pref, audio.pref)
@loader.owner
async def convscmd(self, m):
""".convs <reply to audio> [audio_format (ex. `mp3`)]
Convert audio to some format"""
f = utils.get_args(m)
if not f:
return await utils.answer(m, self.strings("set_fmt", m).format("Converter"))
audio = await self.get_audio(m, "Converter")
if not audio:
return
await self.send_audio(
audio.message,
audio,
audio.audio,
audio.pref,
f"Converted to {f[0].lower()}",
fmt=f[0].lower(),
)
@loader.owner
async def byrobertscmd(self, m):
'''.byroberts <reply to audio>
Add at the end "Directed by Robert B Weide"'''
audio = await self.get_audio(m, "Directed by...")
if not audio:
return
async with aiohttp.ClientSession() as s, s.get(
"https://raw.githubusercontent.com/D4n13l3k00/files-for-modules/master/directed.mp3"
) as r:
out = audio.audio + AudioSegment.from_file(
io.BytesIO(await r.read())
).apply_gain(+8)
await self.send_audio(audio.message, audio, out, audio.pref, audio.pref)
@loader.owner
async def cutscmd(self, m):
""".cuts <start(ms):end(ms)> <reply to audio>
Cut audio"""
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings("set_time", m).format("Cut"))
r = re.compile(r"^(?P<start>\d+){0,1}:(?P<end>\d+){0,1}$")
ee = r.match(args)
if not ee:
return await utils.answer(m, self.strings("set_time", m).format("Cut"))
start = int(ee["start"]) if ee["start"] else 0
end = int(ee["end"]) if ee["end"] else 0
audio = await self.get_audio(m, "Cut")
if not audio:
return
out = audio.audio[start : end or len(audio.audio) - 1]
await self.send_audio(audio.message, audio, out, audio.pref, audio.pref)
class AudioEditorClass:
audio = None
message = None
duration = None
voice = None
pref = None
reply = None
async def get_audio(self, m, pref):
r = await m.get_reply_message()
if r and r.file and r.file.mime_type.split("/")[0] in ["audio", "video"]:
ae = self.AudioEditorClass()
ae.pref = pref
ae.reply = r
ae.voice = (
r.document.attributes[0].voice
if r.file.mime_type.split("/")[0] == "audio"
else False
)
ae.duration = r.document.attributes[0].duration
ae.message = await utils.answer(
m, self.strings("downloading", m).format(pref)
)
ae.audio = AudioSegment.from_file(io.BytesIO(await r.download_media(bytes)))
ae.message = await utils.answer(
ae.message, self.strings("working", m).format(pref)
)
return ae
await utils.answer(m, self.strings("reply", m).format(pref))
return None
async def send_audio(self, message, audio, out, pref, title, fs=None, fmt="mp3"):
out_file = io.BytesIO()
out_file.name = "audio." + ("ogg" if audio.voice else "mp3")
if audio.voice:
out.split_to_mono()
message = await utils.answer(message, self.strings("exporting").format(pref))
out.export(
out_file,
format="ogg" if audio.voice else fmt,
bitrate="64k" if audio.voice else None,
codec="libopus" if audio.voice else None,
)
out_file.seek(0)
await utils.answer(
message,
out_file,
reply_to=audio.reply.id,
voice_note=audio.voice,
attributes=None
if audio.voice
else [
types.DocumentAttributeAudio(
duration=fs or audio.duration,
title=title,
performer="AudioEditor",
)
],
)

View File

@@ -0,0 +1,80 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import os
from telethon import functions, types
from .. import loader, utils # type: ignore
@loader.tds
class AvaMod(loader.Module):
"""Установка/удаление аватарок через команды"""
strings = {
"name": "AvatarMod",
"need_pic": "<b>[Avatar]</b> Нужно фото",
"downloading": "<b>[Avatar]</b> Скачиваю",
"installing": "<b>[Avatar]</b> Устанавливаю",
"deleting": "<b>[Avatar]</b> Удаляю",
"ok": "<b>[Avatar]</b> Готово",
"no_avatar": "<b>[Avatar]</b> Нету аватарки/ок",
}
async def avacmd(self, m: types.Message):
".ava <reply_to_photo> - Установить аватар"
client = m.client
reply = await m.get_reply_message()
if not reply and not reply.photo:
return await utils.answer(m, self.strings("need_pic"))
m = await utils.answer(m, self.strings("downloading"))
photo = await client.download_media(message=reply.photo)
up = await client.upload_file(photo)
m = await utils.answer(m, self.strings("installing"))
await client(functions.photos.UploadProfilePhotoRequest(up))
await utils.answer(m, self.strings("ok"))
os.remove(photo)
async def delavacmd(self, m: types.Message):
"Удалить текущую аватарку"
client = m.client
ava = await client.get_profile_photos("me", limit=1)
if len(ava) > 0:
m = await utils.answer(m, self.strings("deleting"))
await client(functions.photos.DeletePhotosRequest(ava))
await utils.answer(m, self.strings("ok"))
else:
await utils.answer(m, self.strings("no_avatar"))
async def delavascmd(self, m: types.Message):
"Удалить все аватарки"
client = m.client
ava = await client.get_profile_photos("me")
if len(ava) > 0:
m = await utils.answer(m, self.strings("deleting"))
await client(
functions.photos.DeletePhotosRequest(
await m.client.get_profile_photos("me")
)
)
await utils.answer(m, self.strings("ok"))
else:
await utils.answer(m, self.strings("no_avatar"))

View File

@@ -0,0 +1,118 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import ast
import io
from .. import loader, utils # type: ignore
@loader.tds
class BackupManMod(loader.Module):
"""BackupMan"""
strings = {"name": "BackupMan"}
async def client_ready(self, _, db):
self._db = db
@loader.owner
async def restmcmd(self, m):
"Установить все модули из *.bkm файла"
reply = await m.get_reply_message()
if not reply or not reply.file or reply.file.name.split(".")[-1] != "bkm":
return await m.edit("<b>[BackupMan]</b> Reply to <code>*.bkm</code> file")
modules = self._db.get("friendly-telegram.modules.loader", "loaded_modules", [])
txt = io.BytesIO(await reply.download_media(bytes))
valid, already_loaded = 0, 0
for i in txt.read().decode("utf-8").split("\n"):
if i not in modules:
valid += 1
modules.append(i)
else:
already_loaded += 1
self._db.set("friendly-telegram.modules.loader", "loaded_modules", modules)
await m.edit(
"<b>[BackupMan]</b>\n\n"
"<i>Загружено модулей:</i> <code>{valid}</code>\n"
"<i>Загружены ранее:</i> <code>{already_loaded}</code>\n\n"
+ (
"<b>> Юзербот автоматически перезагрузится</b>"
if valid != 0
else "<b>> Ничего не загружено</b>"
)
)
if valid != 0:
await self.allmodules.commands["restart"](await m.respond("_"))
@loader.owner
async def backmcmd(self, m):
"Сделать бэкап модулей в *.bkm файл"
modules = self._db.get("friendly-telegram.modules.loader", "loaded_modules", [])
txt = io.BytesIO("\n".join(modules).encode("utf-8"))
txt.name = f"BackupMan-{(await m.client.get_me()).id}.bkm"
await m.client.send_file(
m.to_id,
txt,
caption="<b>[BackupMan]</b> <i>Бэкап модулей</i>\n"
f"<i>Модулей:</i> <code>{len(modules)}</code>\n"
"<i>Для загрузки бэкапа используй модуль:</i>\n"
"<code>.dlmod https://d4n13l3k00.ru/modules/BackupMan.py</code>",
)
await m.delete()
@loader.owner
async def restncmd(self, m):
"Установить все заметки из *.bkn файла\n<f> - Заменять уже существующие заметки"
args: list or None = utils.get_args_raw(m)
force = "f" in args.lower()
reply = await m.get_reply_message()
if not reply or not reply.file or reply.file.name.split(".")[-1] != "bkn":
return await m.edit("<b>[BackupMan]</b> Reply to <code>*.bkn</code> file")
notes = self._db.get("friendly-telegram.modules.notes", "notes", {})
txt = io.BytesIO(await reply.download_media(bytes))
valid, already_loaded = 0, 0
for k, v in ast.literal_eval(txt.read().decode("utf-8")).items():
if k not in notes or force:
notes[k] = v
valid += 1
else:
already_loaded += 1
self._db.set("friendly-telegram.modules.notes", "notes", notes)
await m.edit(
"<b>[BackupMan]</b>\n\n"
f"<i>Загружено/заменено заметок:</i> <code>{valid}</code>\n"
f"<i>Загружены ранее:</i> <code>{already_loaded}</code>"
)
@loader.owner
async def backncmd(self, m):
"Сделать бэкап заметок в *.bkn файл"
modules = self._db.get("friendly-telegram.modules.notes", "notes", {})
txt = io.BytesIO(str(modules).encode("utf-8"))
txt.name = f"BackupMan-{(await m.client.get_me()).id}.bkn"
await m.client.send_file(
m.to_id,
txt,
caption=f"<b>[BackupMan]</b> <i>Бэкап заметок</i>\n"
f"<i>Заметок:</i> <code>{len(modules)}</code>\n"
"<i>Для загрузки бэкапа используй модуль:</i>\n"
"<code>.dlmod https://d4n13l3k00.ru/modules/BackupMan.py</code>",
)
await m.delete()

View File

@@ -0,0 +1,151 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import asyncio
import io
import logging
from typing import List
import aiohttp
import pydantic
import telethon
from telethon import types
from telethon.events import ChatAction
from telethon.tl.functions.channels import EditBannedRequest
from telethon.tl.types import ChatBannedRights
from .. import loader, utils # type: ignore
@loader.tds
class CaptchaMod(loader.Module):
"Captcha for chats"
strings = {
"name": "Captcha",
"pls_pass_captcha": '<a href="tg://user?id={}">Хэй</a>, пройди капчу! У тебя одна попытка\n'
"Иначе получишь бан навсегда!",
"captcha_status": "<b>[Captcha]</b> {}",
}
class CUserModel(pydantic.BaseModel):
chat: int
user: int
message: int
answer: str
async def client_ready(self, _, db):
self.db = db
self.log = logging.getLogger(__name__)
self._db = "CaptchaMod"
self.locked_users: List[self.CUserModel] = []
async def watcher(self, m):
"Watcher"
client: telethon.TelegramClient = m.client
if isinstance(m, ChatAction.Event):
if m.chat_id not in self.db.get(self._db, "chats", []):
return
if m.user_added or m.user_joined:
users = [i.id for i in m.users]
for u in users:
_u = await client.get_entity(u)
if _u.bot:
continue
async with aiohttp.ClientSession() as s, s.get(
"https://api.d4n13l3k00.ru/captcha/generate"
) as r:
answer = r.headers["Captcha-Code"]
im = io.BytesIO(await r.read())
im.name = "@DekFTGModules_captcha.png"
m = await client.send_file(
m.chat,
im,
caption=self.strings("pls_pass_captcha").format(u),
)
self.locked_users.append(
self.CUserModel(
chat=m.chat_id, user=u, message=m.id, answer=answer
)
)
await asyncio.sleep(60)
l: List[self.CUserModel] = list(
filter(
lambda x: x.chat == m.chat_id and x.user in users,
self.locked_users,
)
)
if l:
for u in l:
self.locked_users.remove(u)
await (
await client.get_messages(u.chat, ids=u.message)
).delete()
await client(
EditBannedRequest(
u.chat,
u.user,
ChatBannedRights(until_date=None, view_messages=True),
)
)
elif m.user_kicked or m.user_left:
users = [i.id for i in m.users]
for u in users:
l: List[self.CUserModel] = list(
filter(
lambda x: x.chat == m.chat_id and x.user == u,
self.locked_users,
)
)
if l:
ntt = l[0]
self.locked_users.remove(ntt)
return
if isinstance(m, types.Message):
client: telethon.TelegramClient = m.client
l: List[self.CUserModel] = list(
filter(
lambda x: x.chat == m.chat_id and x.user == m.sender_id,
self.locked_users,
)
)
if l:
ntt = l[0]
self.locked_users.remove(ntt)
await (await client.get_messages(ntt.chat, ids=ntt.message)).delete()
await m.delete()
if ntt.answer.lower() != m.raw_text.lower():
await client(
EditBannedRequest(
ntt.chat,
ntt.user,
ChatBannedRights(until_date=None, view_messages=True),
)
)
async def swcaptchacmd(self, m: types.Message):
"Turn on/off captcha in chat"
l: list = self.db.get(self._db, "chats", [])
if m.chat_id in l:
l.remove(m.chat_id)
self.db.set(self._db, "chats", l)
return await utils.answer(m, self.strings("captcha_status").format("OFF"))
l.append(m.chat_id)
self.db.set(self._db, "chats", l)
await utils.answer(m, self.strings("captcha_status").format("ON"))

View File

@@ -0,0 +1,129 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
from telethon.tl.types import (
InputMessagesFilterPhotos,
InputMessagesFilterVideo,
InputMessagesFilterVoice,
InputMessagesFilterMusic,
InputMessagesFilterDocument,
InputMessagesFilterContacts,
InputMessagesFilterGeo,
InputMessagesFilterRoundVideo,
InputMessagesFilterUrl,
InputMessagesFilterGif,
)
from .. import loader # type: ignore
@loader.tds
class ChatStatisticMod(loader.Module):
"Статистика чата"
strings = {"name": "ChatStatistic"}
@loader.owner
async def statacmd(self, m):
await m.edit("<b>Считаем...</b>")
al = str((await m.client.get_messages(m.to_id, limit=0)).total)
ph = str(
(
await m.client.get_messages(
m.to_id, limit=0, filter=InputMessagesFilterPhotos()
)
).total
)
vi = str(
(
await m.client.get_messages(
m.to_id, limit=0, filter=InputMessagesFilterVideo()
)
).total
)
mu = str(
(
await m.client.get_messages(
m.to_id, limit=0, filter=InputMessagesFilterMusic()
)
).total
)
vo = str(
(
await m.client.get_messages(
m.to_id, limit=0, filter=InputMessagesFilterVoice()
)
).total
)
vv = str(
(
await m.client.get_messages(
m.to_id, limit=0, filter=InputMessagesFilterRoundVideo()
)
).total
)
do = str(
(
await m.client.get_messages(
m.to_id, limit=0, filter=InputMessagesFilterDocument()
)
).total
)
urls = str(
(
await m.client.get_messages(
m.to_id, limit=0, filter=InputMessagesFilterUrl()
)
).total
)
gifs = str(
(
await m.client.get_messages(
m.to_id, limit=0, filter=InputMessagesFilterGif()
)
).total
)
geos = str(
(
await m.client.get_messages(
m.to_id, limit=0, filter=InputMessagesFilterGeo()
)
).total
)
cont = str(
(
await m.client.get_messages(
m.to_id, limit=0, filter=InputMessagesFilterContacts()
)
).total
)
await m.edit(
(
"<b>Всего сoообщений</b> {}\n"
+ "<b>Фоток:</b> {}\n"
+ "<b>Видосов:</b> {}\n"
+ "<b>Попсы:</b> {}\n"
+ "<b>Голосовых:</b> {}\n"
+ "<b>Кругляшков:</b> {}\n"
+ "<b>Файлов:</b> {}\n"
+ "<b>Ссылок:</b> {}\n"
+ "<b>Гифок:</b> {}\n"
+ "<b>Координат:</b> {}\n"
+ "<b>Контактов:</b> {}"
).format(al, ph, vi, mu, vo, vv, do, urls, gifs, geos, cont)
)

View File

@@ -0,0 +1,223 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
import contextlib
import os
import re
from typing import *
import pytgcalls
import youtube_dl
from pytgcalls import PyTgCalls, StreamType
from pytgcalls.types.input_stream import AudioPiped, AudioVideoPiped
from pytgcalls.types.input_stream.quality import HighQualityAudio, HighQualityVideo
from telethon import types
from .. import loader, utils # type: ignore
# meta developer: @D4n13l3k00
# requires: py-tgcalls youtube-dl
@loader.tds
class ChatVoiceMod(loader.Module):
"""Module for working with voicechat"""
strings = {
"name": "ChatVoiceMod",
"downloading": "<b>[ChatVoiceMod]</b> Downloading...",
"playing": "<b>[ChatVoiceMod]</b> Playing...",
"notjoined": "<b>[ChatVoiceMod]</b> You are not joined",
"stop": "<b>[ChatVoiceMod]</b> Playing stopped!",
"leave": "<b>[ChatVoiceMod]</b> Leaved!",
"pause": "<b>[ChatVoiceMod]</b> Paused!",
"resume": "<b>[ChatVoiceMod]</b> Resumed!",
"mute": "<b>[ChatVoiceMod]</b> Muted!",
"unmute": "<b>[ChatVoiceMod]</b> Unmuted!",
"error": "<b>[ChatVoiceMod]</b> Error: <code>{}</code>",
"noargs": "<b>[ChatVoiceMod]</b> No args",
"noreply": "<b>[ChatVoiceMod]</b> No reply",
"nofile": "<b>[ChatVoiceMod]</b> No file",
"nofiles": "<b>[ChatVoiceMod]</b> No files",
"deleted": "<b>[ChatVoiceMod]</b> <code>{}</code> successfully deleted",
"downloaded": "<b>[ChatVoiceMod]</b> Downloaded to <code>dl/{0}</code>. For playing use:\n<code>.cplaya dl/{0}</code>\n<code>.cplayv dl/{0}</code>",
}
async def client_ready(self, client, _):
self.client = client
self.call = PyTgCalls(client)
@self.call.on_stream_end()
async def _(_, update):
with contextlib.suppress(Exception):
await self.call.leave_group_call(update.chat_id)
await self.call.start()
async def parse_args(self, args):
if not args or not re.match(
r"http(?:s?):\/\/(?:www\.)?youtu(?:be\.com\/watch\?v=|\.be\/)([\w\-\_]*)(&(amp;)?[\w\?=]*)?",
args,
):
return args
with youtube_dl.YoutubeDL({"format": "best"}) as ydl:
info = ydl.extract_info(args, download=False)
return info["formats"][0]["url"]
async def cdlcmd(self, m: types.Message):
"<reply_to_media> <name: optional> - Download media to server in `dl` folder"
args = utils.get_args_raw(m)
reply = await m.get_reply_message()
if not reply:
return await utils.answer(m, self.strings("noreply"))
name = args or reply.file.name
try:
m = await utils.answer(m, self.strings("downloading"))
await reply.download_media(f"dl/{name}")
await utils.answer(m, self.strings("downloaded").format(name))
except Exception as e:
await utils.answer(m, self.strings("error").format(str(e)))
async def clscmd(self, m: types.Message):
"List all files in `dl` folder"
if not os.path.isdir("dl") or not os.listdir("dl"):
return await utils.answer(m, self.strings("nofiles"))
files = [f"<code>dl/{f}</code>" for f in os.listdir("dl")]
await utils.answer(m, "\n".join(files))
# command for deleting file from dl folder
async def cdelcmd(self, m: types.Message):
"<name> - Delete file from `dl` folder"
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings("noargs"))
if not args.startswith("dl/"):
args = f"dl/{args}"
if not os.path.isfile(f"{args}"):
return await utils.answer(m, self.strings("nofile"))
try:
os.remove(f"{args}")
await utils.answer(m, self.strings("deleted").format(args))
except Exception as e:
await utils.answer(m, self.strings("error").format(str(e)))
async def cplayvcmd(self, m: types.Message):
"<link/path/reply_to_video> - Play video in voice chat"
try:
reply = await m.get_reply_message()
path = await self.parse_args(utils.get_args_raw(m))
chat = m.chat.id
if not path:
if not reply:
return await utils.answer(m, self.strings("noargs"))
m = await utils.answer(m, self.strings("downloading"))
path = await reply.download_media()
with contextlib.suppress(pytgcalls.exceptions.GroupCallNotFound):
self.call.get_active_call(chat)
await self.call.leave_group_call(chat)
await self.call.join_group_call(
chat,
AudioVideoPiped(
path,
HighQualityAudio(),
HighQualityVideo(),
),
stream_type=StreamType().pulse_stream,
)
await utils.answer(m, self.strings("playing"))
except Exception as e:
await utils.answer(m, self.strings("error").format(str(e)))
async def cplayacmd(self, m: types.Message):
"<link/path/reply_to_audio> - Play audio in voice chat"
try:
reply = await m.get_reply_message()
path = await self.parse_args(utils.get_args_raw(m))
chat = m.chat.id
if not path:
if not reply:
return await utils.answer(m, self.strings("noargs"))
m = await utils.answer(m, self.strings("downloading"))
path = await reply.download_media()
with contextlib.suppress(pytgcalls.exceptions.GroupCallNotFound):
self.call.get_active_call(chat)
await self.call.leave_group_call(chat)
await self.call.join_group_call(
chat,
AudioPiped(
path,
HighQualityAudio(),
),
stream_type=StreamType().pulse_stream,
)
await utils.answer(m, self.strings("playing"))
except Exception as e:
await utils.answer(m, self.strings("error").format(str(e)))
async def cleavecmd(self, m: types.Message):
"Leave"
try:
self.call.get_active_call(m.chat.id)
await self.call.leave_group_call(m.chat.id)
await utils.answer(m, self.strings("leave"))
except pytgcalls.exceptions.GroupCallNotFound:
await utils.answer(m, self.strings("notjoined"))
except Exception as e:
await utils.answer(m, self.strings("error").format(str(e)))
async def cmutecmd(self, m: types.Message):
"Mute"
try:
self.call.get_active_call(m.chat.id)
await self.call.mute_stream(m.chat.id)
await utils.answer(m, self.strings("mute"))
except pytgcalls.exceptions.GroupCallNotFound:
await utils.answer(m, self.strings("notjoined"))
except Exception as e:
await utils.answer(m, self.strings("error").format(str(e)))
async def cunmutecmd(self, m: types.Message):
"Unmute"
try:
self.call.get_active_call(m.chat.id)
await self.call.unmute_stream(m.chat.id)
await utils.answer(m, self.strings("unmute"))
except pytgcalls.exceptions.GroupCallNotFound:
await utils.answer(m, self.strings("notjoined"))
except Exception as e:
await utils.answer(m, self.strings("error").format(str(e)))
async def cpausecmd(self, m: types.Message):
"Pause"
try:
self.call.get_active_call(m.chat.id)
await self.call.pause_stream(m.chat.id)
await utils.answer(m, self.strings("pause"))
except pytgcalls.exceptions.GroupCallNotFound:
await utils.answer(m, self.strings("notjoined"))
except Exception as e:
await utils.answer(m, self.strings("error").format(str(e)))
async def cresumecmd(self, m: types.Message):
"Resume"
try:
self.call.get_active_call(m.chat.id)
await self.call.resume_stream(m.chat.id)
await utils.answer(m, self.strings("resume"))
except pytgcalls.exceptions.GroupCallNotFound:
await utils.answer(m, self.strings("notjoined"))
except Exception as e:
await utils.answer(m, self.strings("error").format(str(e)))

View File

@@ -0,0 +1,85 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import aiohttp
from .. import loader, utils # type: ignore
@loader.tds
class CheckerTGMod(loader.Module):
"""CheckerTG"""
strings = {
"name": "CheckerTG",
"check": "<b>[CheckerAPI]</b> Делаем запрос к API...",
"response": "<b>[CheckerAPI]</b> Ответ API: <code>{}</code>\nВремя выполнения: <code>{}</code>",
}
@loader.owner
async def checkcmd(self, m):
"""Проверить id на слитый номер
Жуёт либо <reply> либо <uid>
"""
reply = await m.get_reply_message()
if utils.get_args_raw(m):
user = utils.get_args_raw(m)
elif reply:
try:
user = str(reply.sender.id)
except Exception:
return await m.edit("<b>Err</b>")
else:
return await m.edit("[CheckerAPI] А кого чекать?")
await m.edit(self.strings["check"])
async with aiohttp.ClientSession() as s, s.get(
f"https://api.d4n13l3k00.ru/tg/leaked/check?uid={user}"
) as r:
r = await r.json()
await m.edit(
self.strings["response"].format(
r["data"], str(round(r["time"], 3)) + "ms"
)
)
@loader.owner
async def rcheckcmd(self, m):
"""Обратный поиск
Жуёт <phone number>
"""
reply = await m.get_reply_message()
if utils.get_args_raw(m):
phone = utils.get_args_raw(m)
elif reply:
try:
phone = reply.raw_text
except Exception:
return await m.edit("<b>Err</b>")
else:
return await m.edit("[CheckerAPI] А кого чекать?")
await m.edit(self.strings["check"])
async with aiohttp.ClientSession() as s, s.get(
f"https://api.d4n13l3k00.ru/tg/leaked/check?r=1?uid={phone}"
) as r:
r = await r.json()
await m.edit(
self.strings["response"].format(
r["data"], str(round(r["time"], 3)) + "ms"
)
)

View File

@@ -0,0 +1,106 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
from asyncio import sleep
from telethon import functions
from telethon.tl.functions.account import UpdateProfileRequest
from telethon.tl.functions.users import GetFullUserRequest
from .. import loader, utils # type: ignore
@loader.tds
class CuMod(loader.Module):
"""Полное копирование юзера(ава, имя|фамилия, био)"""
strings = {"name": "CopyUser"}
@loader.owner
async def cucmd(self, message):
""".cu <s> <a> <reply/@username>
<s> - Скрытый режим
<a> - Удалить ваши аватарки
Аргументы после юзера не указывайте, не скушает
Примеры:
.cu s @user/reply
.cu a @user/reply
.cu s a @user/reply"""
reply = await message.get_reply_message()
user = None
s = False
a = False
if utils.get_args_raw(message):
args = utils.get_args_raw(message).split(" ")
for i in args:
if i.lower() == "s":
s = True
elif i.lower() in ["а", "a"]:
a = True
else:
try:
user = await message.client.get_entity(i)
break
except Exception:
continue
if user is None and reply is not None:
user = reply.sender
if user is None and reply is None:
if not s:
await message.edit("Кого?")
return
if s:
await message.delete()
if not s:
for i in range(11):
await message.edit(
f"Получаем доступ к аккаунту пользователя [{i*10}%]\n[{(i*'#').ljust(10, '')}]"
)
await sleep(0.3)
if a:
avs = await message.client.get_profile_photos("me")
if len(avs) > 0:
await message.client(
functions.photos.DeletePhotosRequest(
await message.client.get_profile_photos("me")
)
)
full = await message.client(GetFullUserRequest(user.id))
if not s:
await message.edit("Получаем аватарку... [35%]\n[###]")
if full.profile_photo:
up = await message.client.upload_file(
await message.client.download_profile_photo(user, bytes)
)
if not s:
await message.edit("Ставим аватарку... [50%]\n[#####]")
await message.client(functions.photos.UploadProfilePhotoRequest(up))
if not s:
await message.edit("Получаем данные... [99%]\n[#########]")
await message.client(
UpdateProfileRequest(
user.first_name if user.first_name is not None else "",
user.last_name if user.last_name is not None else "",
full.about[:70] if full.about is not None else "",
)
)
if not s:
await message.edit("Аккаунт клонирован! [100%]\n[##########]")
await sleep(5)
await message.edit("Аккаунт клонирован!")

View File

@@ -0,0 +1,181 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import base64
import io
from typing import List
import aiohttp
from PIL import Image
from telethon import types
from .. import loader, utils # type: ignore
@loader.tds
class CraiyonMod(loader.Module):
"Craiyon - Mini DALL-E for FTG"
strings = {
"name": "Craiyon",
"preparing": "<b>[Craiyon] 📥 Preparing...</b>",
"generating": "<b>[Craiyon] ✨ Generating images...</b>",
"uploading": "<b>[Craiyon] 📤 Uploading images...</b>",
"result_with_url": "<b>[Craiyon] 🎉 Generated images:</b>\n{}",
"error": "<b>[Craiyon]\n❌ Python error:</b>\n<code>{}</code>\n<b> 📜 Response of server:</b>\n<code>{}</code>",
}
async def client_ready(self, client, db):
self.me = await client.get_me()
self.telegraph_short_name = "Craiyon-FTG"
self.telegraph_author_name = (
f"@{self.me.username or self.me.id} via Craiyon-FTG by @DekFTGModules"
)
self.telegraph_author_url = "https://t.me/DekFTGModules"
self.db = db
class NullResponseError(Exception):
"""Raised when the response is null or has no 'images' key"""
pass
@loader.owner
async def craiyoncmd(self, m: types.Message):
".craiyon <text> - Generate images with text using Craiyon (Mini DALL-E)"
args = utils.get_args_raw(m)
async with aiohttp.ClientSession() as session:
m = await utils.answer(m, self.strings("preparing", m))
async with session.post(
"https://api.telegra.ph/createAccount",
json={
"short_name": self.telegraph_short_name,
"author_name": self.telegraph_author_name,
"author_url": self.telegraph_author_url,
},
) as resp:
try:
data = await resp.json(content_type=None)
if "error" in data:
raise self.NullResponseError(
"No images in response (has no 'images' key)"
)
except Exception as e:
err_json = await resp.text()
await utils.answer(
m, self.strings("error", m).format(str(e), err_json)
)
return
try:
self.author_name = data["result"]["author_name"]
self.author_url = data["result"]["author_url"]
self.access_token = data["result"]["access_token"]
except KeyError:
await utils.answer(
m,
self.strings("error", m).format(
"No author_name, author_url or access_token in response",
data,
),
)
return
m = await utils.answer(m, self.strings("generating", m))
async with session.post(
"https://backend.craiyon.com/generate",
json={
"prompt": args,
},
headers={
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:92.0) Gecko/20100101 Firefox/92.0",
},
) as resp:
try:
data = await resp.json(content_type=None)
if "images" not in data:
raise self.NullResponseError(
"No images in response (has no 'images' key)"
)
except Exception as e:
err_json = await resp.text()
await utils.answer(
m, self.strings("error", m).format(str(e), err_json)
)
return
imgs: List[io.BytesIO] = []
uploaded_imgs = []
await utils.answer(m, self.strings("uploading", m))
for i in data["images"]:
image_data = base64.b64decode(i.encode())
image = Image.open(io.BytesIO(image_data))
image_buffer = io.BytesIO()
image.save(image_buffer, format="JPEG")
imgs.append(image_buffer)
for i, img in enumerate(imgs, 1):
img.name = f"craiyon-{i}.jpg"
file = aiohttp.FormData()
file.add_field("file", img.getvalue(), content_type="image/jpeg")
async with session.post(
"https://telegra.ph/upload", data=file
) as resp:
try:
data = await resp.json(content_type=None)
if "error" in data:
raise self.NullResponseError(
"Error API: {}".format(data)
)
uploaded_imgs.append(data[0]["src"])
except Exception as e:
err_json = await resp.text()
await utils.answer(
m, self.strings("error", m).format(str(e), err_json)
)
return
async with session.post(
"https://api.telegra.ph/createPage",
json={
"title": "Craiyon-FTG",
"content": [
{
"tag": "img",
"attrs": {"src": i},
}
for i in uploaded_imgs
],
"access_token": self.access_token,
},
) as resp:
if resp.status != 200:
await utils.answer(
self.strings("error", m).format(
f"Status code: {resp.status}", await resp.text()
)
)
return
try:
data: dict = await resp.json(content_type=None)
except Exception as e:
err_json = await resp.text()
await utils.answer(
m, self.strings("error", m).format(str(e), err_json)
)
return
page_url = data["result"]["url"]
await utils.answer(m, self.strings("result_with_url", m).format(page_url))

View File

@@ -0,0 +1,78 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import io
import requests
from .. import loader # type: ignore
def register(cb):
cb(DeepAIMod())
class DeepAIMod(loader.Module):
strings = {"name": "DeepAI"}
def __init__(self):
self.name = self.strings["name"]
async def client_ready(self, client, db):
self._db = db
async def dai_set_tokencmd(self, m):
self._db.set("deepai", "token", str(m.raw_text.split(" ", 1)[1]))
await m.edit("[DeepAI] Токен установлен")
async def cnsfwcmd(self, m):
""".cnsfw <reply to photo/sticker> - Check on nsfw content by DeepAI"""
reply = await m.get_reply_message()
if not reply:
await m.edit("<b>Reply to media</b>")
return
try:
media = reply.media
except Exception:
await m.edit("<b>Only media</b>")
return
if token := self._db.get("deepai", "token", None):
await m.edit("[DeepAI] Детектим nsfw...")
photo = io.BytesIO()
await m.client.download_media(media, photo)
photo.seek(0)
r = requests.post(
"https://api.deepai.org/api/nsfw-detector",
files={
"image": photo.read(),
},
headers={"api-key": token},
)
try:
await m.edit(
"[DeepAI] Тут Nsfw на "
+ str(round(r.json()["output"]["nsfw_score"] * 100, 1))
+ "%"
)
except Exception:
await m.edit(f"[DeepAI] {str(r.json())}")
else:
await m.edit(
"[DeepAI] Укажите токен для работы с API\n<code>.dai_set_token TOKEN</code>"
)

View File

@@ -0,0 +1,44 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import re
from asyncio import sleep
from .. import loader, utils # type: ignore
@loader.tds
class DelTmMod(loader.Module):
strings = {"name": "Delete Timer"}
@loader.owner
async def deltmcmd(self, m):
"<реплай> <секунды>\nУдалить сообщение в реплае через указанное время"
reply = await m.get_reply_message()
if not reply:
return await m.edit("reply...")
r = re.compile(r"^\d+$")
time = utils.get_args_raw(m)
if r.match(time):
await m.delete()
await sleep(int(time))
await reply.delete()
else:
await m.edit("shit...")
return

View File

@@ -0,0 +1,63 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
from telethon import events
from telethon.errors.rpcerrorlist import YouBlockedUserError
from .. import loader, utils # type: ignore
@loader.tds
class dmt228Mod(loader.Module):
"""Демотиватор 228 @super_rjaka_demotivator_bot"""
strings = {"name": "Демотиватор 228"}
@loader.owner
async def dmtcmd(self, message):
""".dmt [текст по желанию] <reply to video, photo or gif>"""
args = utils.get_args_raw(message)
reply = await message.get_reply_message()
if not reply:
return await message.edit("<b>Reply to media</b>")
try:
media = reply.media
except Exception:
return await message.edit("<b>Only media</b>")
chat = "@super_rjaka_demotivator_bot"
await message.edit("<b>Демотивируем...</b>")
async with message.client.conversation(chat) as conv:
try:
response = conv.wait_event(
events.NewMessage(incoming=True, from_users=1016409811)
)
mm = await message.client.send_file(chat, media, caption=args)
response = await response
await mm.delete()
except YouBlockedUserError:
return await message.reply(
"<b>Разблокируй @super_rjaka_demotivator_bot</b>"
)
await message.delete()
await response.delete()
await message.client.send_file(
message.to_id,
response.media,
reply_to=await message.get_reply_message(),
)

View File

@@ -0,0 +1,98 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import io
from .. import loader, utils # type: ignore
def register(cb):
cb(DUsersMod())
class DUsersMod(loader.Module):
"""DUsers"""
strings = {"name": "DUsers"}
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
async def ducmd(self, message):
""".du <n> <m> <s>
Дамп юзеров чата
<n> - Получить только пользователей с открытыми номерами
<m> - Отправить дамп в избранное
<s> - Тихий дамп
"""
if not message.chat:
await message.edit("<b>Это не чат</b>")
return
chat = message.chat
num = False
silent = False
tome = False
if utils.get_args_raw(message):
a = utils.get_args_raw(message)
if "n" in a:
num = True
if "s" in a:
silent = True
if "m" in a:
tome = True
if not silent:
await message.edit("🖤Дампим чат...🖤")
else:
await message.delete()
f = io.BytesIO()
f.name = f"Dump by {chat.id}.csv"
f.write("FNAME;LNAME;USER;ID;NUMBER\n".encode())
me = await message.client.get_me()
for i in await message.client.get_participants(message.to_id):
if i.id == me.id:
continue
if (num) and i.phone or not (num):
f.write(
f"{str(i.first_name)};{str(i.last_name)};{str(i.username)};{str(i.id)};{str(i.phone)}\n".encode()
)
f.seek(0)
if tome:
await message.client.send_file("me", f, caption="Дамп чата " + str(chat.id))
else:
await message.client.send_file(
message.to_id, f, caption=f"Дамп чата {str(chat.id)}"
)
if not silent:
if tome:
if num:
await message.edit("🖤Дамп юзеров чата сохранён в избранных!🖤")
else:
await message.edit(
"🖤Дамп юзеров чата с открытыми номерами сохранён в избранных!🖤"
)
else:
await message.delete()
f.close()

View File

@@ -0,0 +1,183 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import base64
import io
import requests
import telethon
from telethon.tl.types import *
from .. import loader, utils # type: ignore
@loader.tds
class FDQuoteMod(loader.Module):
strings = {
"name": "FDQuote",
"processing": "<b>[FDQ]</b> Processing...",
"processing_api": "<b>[FDQ]</b> </code>API Processing...</code>",
"photo": "Фото{}",
"video": "Видео{}",
"audio": "Аудио{}",
"gif": "GIF{}",
"voice": "Голосовое сообщение{}",
"videonote": "Видеосообщение",
"poll": "Опрос",
"quiz": "Викторина",
"sticker": "{}Стикер",
"file": "Файл {}",
"api_error": "<b>[FDQ]</b> API Error: <code>{}</code>",
"error": "<b>[FDQ]</b> Err...",
"deleted_acc": "Удалённый аккаунт",
"need_reply": "<b>[FDQ]</b> Reply to message...",
}
def __init__(self):
self.name = self.strings["name"]
self.api_url = "https://api.d4n13l3k00.ru/quotes/generate"
self.debug = False
@loader.owner
async def fdqcmd(self, m: Message):
".fdq <реплай на юзера и текст> или <@username и текст> или <реплай и @username> или <реплай> - Создать квотес"
message = await m.get_reply_message()
args = m.text.split(maxsplit=2)
args.pop(0)
catch_reply = reply = viabot = pic = None
if message:
if args:
if args[0].startswith("@"):
user_id = args[0][1:]
text = message.text
else:
user_id = message.from_id or message.fwd_from.channel_id
text = " ".join(args)
else:
user_id = message.from_id or message.fwd_from.channel_id
text = message.text
catch_reply = True
elif len(args) == 2 and args[0].startswith("@"):
user_id = args[0][1:]
text = args[1]
else:
return await utils.answer(m, self.strings["need_reply"])
try:
user = await m.client.get_entity(user_id)
except ValueError:
return await utils.answer(m, self.strings["error"])
await utils.answer(m, self.strings["processing"])
name = (
telethon.utils.get_display_name(user)
if type(user) == Channel
else (
self.strings["deleted_acc"]
if user and user.deleted
else telethon.utils.get_display_name(user)
)
)
id = user.id
avatar = await m.client.download_profile_photo(user, bytes)
reply = await message.get_reply_message()
### / Message / ###
if message.file and "image" in message.file.mime_type:
pic = await message.download_media(bytes)
elif message.video or message.gif:
pic = await message.download_media(bytes, thumb=-1)
if message.via_bot_id:
viabot = str((await m.client.get_entity(message.via_bot_id)).username)
### / Reply / ###
if reply and catch_reply:
r = await m.client.get_entity(reply.from_id or reply.fwd_from.channel_id)
if reply.photo:
replText = self.strings["photo"].format(
f", {reply.raw_text}" if reply.raw_text else ""
)
elif reply.gif:
replText = self.strings["gif"].format(
f", {reply.raw_text}" if reply.raw_text else ""
)
elif reply.video:
if reply.video.attributes[0].round_message:
replText = self.strings["videonote"]
else:
replText = self.strings["video"].format(
f", {reply.raw_text}" if reply.raw_text else ""
)
elif reply.audio:
replText = self.strings["audio"].format(
f", {reply.raw_text}" if reply.raw_text else ""
)
elif reply.voice:
replText = self.strings["voice"].format(
f", {reply.raw_text}" if reply.raw_text else ""
)
elif reply.poll:
replText = (
self.strings["quiz"]
if reply.media.poll.quiz
else self.strings["poll"]
)
elif reply.sticker:
replText = self.strings["sticker"].format(
reply.sticker.attributes[1].alt + " "
)
elif reply.file:
replText = self.strings["file"].format(
f", {reply.raw_text}" if reply.caption else ""
)
elif reply.raw_text:
replText = reply.raw_text or ""
reply = {
"name": telethon.utils.get_display_name(r)
if type(r) == Channel
else (
self.strings["deleted_acc"]
if r and r.deleted
else telethon.utils.get_display_name(r)
),
"text": replText,
}
else:
reply = None
await utils.answer(m, self.strings["processing_api"])
js = {
"avatar": base64.b64encode(avatar).decode() if avatar else None,
"name": name,
"text": text,
"id": id,
"pic": base64.b64encode(pic).decode() if pic else None,
"reply": reply,
"viabot": viabot,
}
if self.debug:
f = io.BytesIO(str(js).encode("utf-8"))
f.name = "request.debug"
await m.respond(file=f)
r = requests.post(self.api_url, json=js)
if r.status_code == 200:
quote = io.BytesIO(r.content)
quote.name = "q.webp"
if message:
await message.reply(file=quote)
else:
await m.respond(file=quote)
await m.delete()
else:
await utils.answer(m, self.strings["api_error"].format(r.json()["err"]))

View File

@@ -0,0 +1,70 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import re
from asyncio import sleep
from .. import loader, utils # type: ignore
@loader.tds
class ChatFuckerMod(loader.Module):
"""Чатоёб"""
strings = {"name": "Чатоёб"}
@loader.owner
async def fccmd(self, message):
""".fc <Количество заёба> <reply to text/text>
Заебать чат (СРЁТ В ЛОГИ)
"""
reply = await message.get_reply_message()
repeat = 0
text = ""
if reply:
if utils.get_args_raw(message):
try:
if reply.text:
text = reply.text
repeat = int(utils.get_args_raw(message))
else:
await message.edit("Текста нет!")
return
except Exception:
await message.edit("<b>Err</b>")
return
else:
await message.edit("А скольо раз надо?")
return
elif utils.get_args_raw(message):
try:
repeat = int(utils.get_args_raw(message).split(" ")[0])
text = re.split(r".[a-z-0-9]{1,} [0-9]{1,} ", message.text)[1]
except Exception:
await message.edit("<b>Err</b>")
return
else:
await message.edit("А как же текст/реплай на текст?")
return
await message.delete()
for _ in range(repeat):
m = await message.client.send_message(message.to_id, text)
await sleep(0.5)
await m.delete()
await sleep(0.1)

View File

@@ -0,0 +1,39 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
from requests import get
from .. import loader, utils # type: ignore
@loader.tds
class FullApiMod(loader.Module):
"""Фулл"""
strings = {"name": "FullApi"}
@loader.owner
async def rndfullcmd(self, m):
"получить рандомный фулл :)"
await utils.answer(
m,
'<a href="'
+ get("https://api.d4n13l3k00.ru/shit/random_full").json()["url"]
+ '">Подгончик для братков</a>',
)

View File

@@ -0,0 +1,282 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
# require httpx
import json
from typing import List
import httpx
from telethon import types
from .. import loader, utils # type: ignore
@loader.tds
class OpenAIGPTMod(loader.Module):
"OpenAI GPT"
strings = {
"name": "GPT",
"pref": "<b>[GPT]</b> {}",
"prefcgpt": "<b>[ChatGPT]</b> {}",
"prefom": "<b>[OpenModerator]</b> {}",
"result": "<b>Prompt</b>: {prompt}\n\n<b>Result:</b> {text}\n\n"
"<b>Used tokens:</b> {prompt_tokens}+{completion_tokens}={total_tokens}",
}
def __init__(self):
self.config = loader.ModuleConfig(
*("MODEL", "text-davinci-003", "Model name"),
*(
"COMPLETION_ENDPOINT",
"https://api.openai.com/v1/completions",
"Completions API endpoint",
),
*("MAX_TOKENS", 512, "Maximum tokens"),
*("TEMPERATURE", 0.7, "Temperature"),
*("DEBUG", False, "Debug mode for answers"),
*(
"CGPT_ENDPOINT",
"https://api.openai.com/v1/chat/completions",
"ChatGPT API endpoint",
),
*("CGPT_MODEL", "gpt-3.5-turbo", "ChatGPT model name"),
*("CGPT_TEMPERATURE", 0.7, "ChatGPT temperature"),
*(
"CGPT_SYSTEM_MSG",
"You are Pavel Durov, CEO and owner of Telegram",
"ChatGPT system message",
),
*(
"MODERATION_ENDPOINT",
"https://api.openai.com/v1/moderations",
"OpenAI's moderation endpoint",
),
)
async def client_ready(self, client, db):
self._client = client
self._db = db
self._db_name = "OpenAI_GPT"
self.messages_history_default = [
{
"role": "system",
"content": self.config["CGPT_SYSTEM_MSG"],
}
]
self.messages_history = [] + self.messages_history_default
@loader.owner
async def setgptcmd(self, m: types.Message):
"<token> - set OpenAI access token"
token: str or None = utils.get_args_raw(m)
if not token:
return await utils.answer(m, self.strings("pref", m).format("No token"))
self._db.set(self._db_name, "token", token)
await utils.answer(m, self.strings("pref", m).format("Token set"))
@loader.owner
async def gptcmd(self, m: types.Message):
"<text/reply_to_text> - generate text"
token = self._db.get(self._db_name, "token")
if not token:
return await utils.answer(
m, self.strings("pref", m).format("No token set! Use .setgpt <token>")
)
prompt = utils.get_args_raw(m)
reply = await m.get_reply_message()
if reply:
prompt = prompt or reply.raw_text
if not prompt:
return await utils.answer(m, self.strings("pref", m).format("No text"))
m = await utils.answer(m, self.strings("pref", m).format("Generating..."))
async with httpx.AsyncClient(timeout=300) as client:
response = await client.post(
self.config["COMPLETION_ENDPOINT"],
headers={
"Authorization": f"Bearer {token}",
},
json={
"model": self.config["MODEL"],
"prompt": prompt,
"max_tokens": self.config["MAX_TOKENS"],
"temperature": self.config["TEMPERATURE"],
},
)
j = response.json()
if response.status_code != 200:
if self.config["DEBUG"]:
return await utils.answer(
m, "<code>{}</code>".format(str(json.dumps(j, indent=1)))
)
return await utils.answer(
m,
self.strings("pref", m).format(
f"<b>Error:</b> {response.status_code} {response.reason_phrase}"
),
)
if self.config["DEBUG"]:
return await utils.answer(
m, "<code>{}</code>".format(str(json.dumps(j, indent=1)))
)
text = j["choices"][0]["text"].strip("\n").strip(" ")
if j["choices"][0]["finish_reason"] == "length":
text += "\n<code>TOKEN_LIMIT. Use .config to change them.</code>"
await utils.answer(
m,
self.strings("pref", m).format(
self.strings("result", m).format(
prompt=prompt, text=text, **j["usage"]
)
),
)
@loader.owner
async def cgptcmd(self, m: types.Message):
"<text/reply_to_text> - answer ChatGPT (gpt-3.5-turbo)"
token = self._db.get(self._db_name, "token")
if not token:
return await utils.answer(
m,
self.strings("prefcgpt", m).format("No token set! Use .setgpt <token>"),
)
prompt = utils.get_args_raw(m)
reply = await m.get_reply_message()
if reply:
prompt = prompt or reply.raw_text
if not prompt:
return await utils.answer(m, self.strings("prefcgpt", m).format("No text"))
m = await utils.answer(m, self.strings("prefcgpt", m).format("Generating..."))
async with httpx.AsyncClient(timeout=300) as client:
response = await client.post(
self.config["CGPT_ENDPOINT"],
headers={
"Authorization": f"Bearer {token}",
},
json={
"model": self.config["CGPT_MODEL"],
"messages": self.messages_history
+ [{"role": "user", "content": prompt}],
"temperature": self.config["CGPT_TEMPERATURE"],
},
)
j = response.json()
if response.status_code != 200:
if self.config["DEBUG"]:
return await utils.answer(
m, "<code>{}</code>".format(str(json.dumps(j, indent=1)))
)
return await utils.answer(
m,
self.strings("prefcgpt", m).format(
f"<b>Error:</b> {response.status_code} {response.reason_phrase}"
),
)
if self.config["DEBUG"]:
return await utils.answer(
m, "<code>{}</code>".format(str(json.dumps(j, indent=1)))
)
text = j["choices"][0]["message"]["content"].strip("\n").strip(" ")
self.messages_history.append({"role": "user", "content": prompt})
self.messages_history.append({"role": "assistant", "content": text})
if j["choices"][0]["finish_reason"] == "length":
text += "\n<code>TOKEN_LIMIT. Use .config to change them.</code>"
await utils.answer(
m,
self.strings("prefcgpt", m).format(
self.strings("result", m).format(
prompt=prompt, text=text, **j["usage"]
)
),
)
@loader.owner
async def cgptresetcmd(self, m: types.Message):
"Reset ChatGPT history"
self.messages_history = [] + self.messages_history_default
await utils.answer(m, self.strings("prefcgpt", m).format("History reset"))
@loader.owner
async def omodercmd(self, m: types.Message):
"turn chat text moderation with moderation endpoint (eng only)"
token = self._db.get(self._db_name, "token")
if not token:
return await utils.answer(
m,
self.strings("prefom", m).format("No token set! Use .setgpt <token>"),
)
if not m.chat:
return await utils.answer(
m, self.strings("prefom", m).format("Only chat command")
)
chats: List[int] = self._db.get(self._db_name, "moderation", [])
if m.chat.id not in chats:
chats.append(m.chat.id)
await utils.answer(
m, self.strings("prefom", m).format("Moderation enabled for this chat")
)
else:
chats.remove(m.chat.id)
await utils.answer(
m, self.strings("prefom", m).format("Moderation disabled for this chat")
)
self._db.set(self._db_name, "moderation", chats)
async def watcher(self, m: types.Message):
if not isinstance(m, types.Message):
return
if not m.chat:
return
chats: List[int] = self._db.get(self._db_name, "moderation", [])
if m.chat.id not in chats:
return
token = self._db.get(self._db_name, "token")
async with httpx.AsyncClient(timeout=300) as client:
response = await client.post(
self.config["MODERATION_ENDPOINT"],
headers={
"Authorization": f"Bearer {token}",
},
json={"input": m.raw_text},
)
j = response.json()
if response.status_code != 200:
if self.config["DEBUG"]:
return await utils.answer(
m, "<code>{}</code>".format(str(json.dumps(j, indent=1)))
)
return await utils.answer(
m,
self.strings("prefcgpt", m).format(
f"<b>Error:</b> {response.status_code} {response.reason_phrase}"
),
)
if self.config["DEBUG"]:
return await utils.answer(
m, "<code>{}</code>".format(str(json.dumps(j, indent=1)))
)
if j["results"]["flagged"]:
return await m.delete()

View File

@@ -0,0 +1,244 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
# requires: Pillow aiohttp fake-useragent
import hashlib
import io
import re
from datetime import date
import aiohttp
from fake_useragent import UserAgent
from PIL import Image, ImageEnhance, ImageOps
from telethon import types
from .. import loader, utils # type: ignore
@loader.tds
class ImageEditorMod(loader.Module):
"ImageEditor - Simple tool for working with images"
strings = {
"name": "ImageEditor",
"downloading": "<b>[{}]</b> Downloading...",
"working": "<b>[{}]</b> Working...",
"exporting": "<b>[{}]</b> Exporting...",
"set_value": "<b>[{}]</b> Specify the level...",
"set_size": "<b>[{}]</b> Specify the size...",
"reply": "<b>[{}]</b> reply to image...",
"set_time": "<b>[{}]</b> Specify the time in the format start(ms):end(ms)",
}
@loader.owner
async def resizeicmd(self, m: types.Message):
".resizei <w> <h> - Resize image"
_pref = "Resize"
args = utils.get_args_raw(m)
r = re.compile(r"^(\d+)\s+(\d+)$")
if not args or not r.match(args):
return await utils.answer(m, self.strings("set_size", m).format(_pref))
w, h = [int(i) for i in r.match(args).groups()]
im = await get_image(self, m, _pref)
if not im:
return
out = im.image.resize((w, h))
await go_out(self, m, im, out, _pref)
@loader.owner
async def rmbgicmd(self, m: types.Message):
".rmbgi - Remove background via AI [Powered by Indian's AI]"
_pref = "RemoveBg"
im = await get_image(self, m, _pref)
if not im:
return
b = io.BytesIO()
b.name = "i.png"
im.image.save(b, "PNG")
b.seek(0)
out = None
async with aiohttp.ClientSession(
headers={"User-Agent": UserAgent().chrome}
) as s:
form = aiohttp.FormData()
form.add_field("file", b)
form.add_field("filenameOverride", "true")
form.add_field(
"path",
f"__editor/{date.year}-{date.month}-{date.day}/{hashlib.md5(b.read()).hexdigest()}",
)
b.seek(0)
async with s.post(
"https://api.erase.bg/service/panel/assets/v1.0/upload/direct",
data=form,
) as r:
_url = (await r.json())["url"]
async with s.get(
_url.replace("dummy-cloudname/original", "dummy-cloudname/erase.bg()")
) as r:
i = io.BytesIO(await r.read())
i.name = "ImageEditor.jpeg"
out = Image.open(i)
await go_out(self, m, im, out, _pref, True)
@loader.owner
async def inverticmd(self, m: types.Message):
".inverti - Invert colors"
_pref = "Invert"
im = await get_image(self, m, _pref)
if not im:
return
out = ImageOps.invert(im.image)
await go_out(self, m, im, out, _pref)
@loader.owner
async def bwicmd(self, m: types.Message):
".bwi - BlackWhite"
_pref = "BlackWhite"
im = await get_image(self, m, _pref)
if not im:
return
out = im.image.convert("L")
await go_out(self, m, im, out, _pref)
@loader.owner
async def convicmd(self, m: types.Message):
".convi - Sticker to image | Image to sticker"
_pref = "Converter"
im = await get_image(self, m, _pref)
if not im:
return
im.is_webp = not im.is_webp
await go_out(self, m, im, im.image, _pref)
@loader.owner
async def rotateicmd(self, m: types.Message):
".rotatei <degrees> - Rotate image"
_pref = "Rotate"
args = utils.get_args_raw(m)
r = re.compile(r"^(\d+)$")
if not args or not r.match(args):
return await utils.answer(m, self.strings("set_value", m).format(_pref))
degrees = int(r.match(args).groups()[0])
im = await get_image(self, m, _pref)
if not im:
return
out = im.image.rotate(degrees, expand=True)
await go_out(self, m, im, out, _pref)
@loader.owner
async def contrasticmd(self, m: types.Message):
".contrasti <float> - Change contrast"
_pref = "Contrast"
args = utils.get_args_raw(m)
r = re.compile(r"^(\d*\.?\d*)$")
if not args or not r.match(args):
return await utils.answer(m, self.strings("set_value", m).format(_pref))
level = float(r.match(args).groups()[0])
im = await get_image(self, m, _pref)
if not im:
return
out = ImageEnhance.Contrast(im.image).enhance(level)
await go_out(self, m, im, out, _pref)
@loader.owner
async def sharpnessicmd(self, m: types.Message):
".sharpnessi <float> - Change sharpness"
_pref = "Sharpness"
args = utils.get_args_raw(m)
r = re.compile(r"^(\d*\.?\d*)$")
if not args or not r.match(args):
return await utils.answer(m, self.strings("set_value", m).format(_pref))
level = float(r.match(args).groups()[0])
im = await get_image(self, m, _pref)
if not im:
return
out = ImageEnhance.Sharpness(im.image).enhance(level)
await go_out(self, m, im, out, _pref)
@loader.owner
async def brighticmd(self, m: types.Message):
".brighti <float> - Change bright"
_pref = "Color"
args = utils.get_args_raw(m)
r = re.compile(r"^(\d*\.?\d*)$")
if not args or not r.match(args):
return await utils.answer(m, self.strings("set_value", m).format(_pref))
level = float(r.match(args).groups()[0])
im = await get_image(self, m, _pref)
if not im:
return
out = ImageEnhance.Brightness(im.image).enhance(level)
await go_out(self, m, im, out, _pref)
@loader.owner
async def coloricmd(self, m: types.Message):
".colori <float> - Change color factor"
_pref = "Color"
args = utils.get_args_raw(m)
r = re.compile(r"^(\d*\.?\d*)$")
if not args or not r.match(args):
return await utils.answer(m, self.strings("set_value", m).format(_pref))
level = float(r.match(args).groups()[0])
im = await get_image(self, m, _pref)
if not im:
return
out = ImageEnhance.Color(im.image).enhance(level)
await go_out(self, m, im, out, _pref)
class ImageEditorClass:
image: Image.Image = None
message = None
is_webp: bool = None
pref: str = None
reply = None
async def get_image(self, m, pref: str) -> ImageEditorClass:
r = await m.get_reply_message()
if r and r.file and r.file.mime_type.split("/")[0] in ["image"]:
im = ImageEditorClass()
im.pref = pref
im.reply = r
im.is_webp = r.file.ext == ".webp"
m = await utils.answer(m, self.strings("downloading", m).format(pref))
im.image = Image.open(io.BytesIO(await r.download_media(bytes)))
im.message = await utils.answer(m, self.strings("working", m).format(pref))
return im
await utils.answer(m, self.strings("reply", m).format(pref))
async def go_out(
self, m, im: ImageEditorClass, out: Image.Image, pref, force_document=False
):
m = await utils.answer(m, self.strings("exporting", m).format(pref))
iba = io.BytesIO()
if im.is_webp:
out.thumbnail((512, 512))
out.save(iba, format="WEBP" if im.is_webp else "PNG")
iba.name = "ImageEditor." + ("webp" if im.is_webp else "png")
iba.seek(0)
await utils.answer(
m,
iba,
reply_to=im.reply.id,
supports_streaming=True,
force_document=force_document if not im.is_webp else False,
)

View File

@@ -0,0 +1,157 @@
# Attribution-NonCommercial-NoDerivatives 4.0 International
> *Creative Commons Corporation (“Creative Commons”) is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an “as-is” basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible.*
>
> ### Using Creative Commons Public Licenses
>
> Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses.
>
> * __Considerations for licensors:__ Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC-licensed material, or material used under an exception or limitation to copyright. [More considerations for licensors](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensors).
>
> * __Considerations for the public:__ By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensors permission is not necessary for any reasonfor example, because of any applicable exception or limitation to copyrightthen that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. [More considerations for the public](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensees).
## Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License
By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions.
### Section 1 Definitions.
a. __Adapted Material__ means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image.
b. __Copyright and Similar Rights__ means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights.
e. __Effective Technological Measures__ means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements.
f. __Exceptions and Limitations__ means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material.
h. __Licensed Material__ means the artistic or literary work, database, or other material to which the Licensor applied this Public License.
i. __Licensed Rights__ means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license.
h. __Licensor__ means the individual(s) or entity(ies) granting rights under this Public License.
i. __NonCommercial__ means not primarily intended for or directed towards commercial advantage or monetary compensation. For purposes of this Public License, the exchange of the Licensed Material for other material subject to Copyright and Similar Rights by digital file-sharing or similar means is NonCommercial provided there is no payment of monetary compensation in connection with the exchange.
j. __Share__ means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them.
k. __Sui Generis Database Rights__ means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world.
l. __You__ means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning.
### Section 2 Scope.
a. ___License grant.___
1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to:
A. reproduce and Share the Licensed Material, in whole or in part, for NonCommercial purposes only; and
B. produce and reproduce, but not Share, Adapted Material for NonCommercial purposes only.
2. __Exceptions and Limitations.__ For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions.
3. __Term.__ The term of this Public License is specified in Section 6(a).
4. __Media and formats; technical modifications allowed.__ The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material.
5. __Downstream recipients.__
A. __Offer from the Licensor Licensed Material.__ Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License.
B. __No downstream restrictions.__ You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material.
6. __No endorsement.__ Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i).
b. ___Other rights.___
1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this Public License.
3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties, including when the Licensed Material is used other than for NonCommercial purposes.
### Section 3 License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the following conditions.
a. ___Attribution.___
1. If You Share the Licensed Material, You must:
A. retain the following if it is supplied by the Licensor with the Licensed Material:
i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of warranties;
v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable;
B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and
C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License.
For the avoidance of doubt, You do not have permission under this Public License to Share Adapted Material.
2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information.
3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable.
### Section 4 Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database for NonCommercial purposes only and provided You do not Share Adapted Material;
b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and
c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights.
### Section 5 Disclaimer of Warranties and Limitation of Liability.
a. __Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.__
b. __To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.__
c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability.
### Section 6 Term and Termination.
a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically.
b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License.
### Section 7 Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License.
### Section 8 Interpretation.
a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions.
c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor.
d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority.
> Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at [creativecommons.org/policies](http://creativecommons.org/policies), Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses.
>
> Creative Commons may be contacted at [creativecommons.org](http://creativecommons.org).

View File

@@ -0,0 +1,73 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import requests
from .. import loader, utils # type: ignore
@loader.tds
class MailSearcherMod(loader.Module):
"AntiPublic MYRZ"
strings = {"name": "AntiPublic MYRZ"}
def __init__(self):
self.name = self.strings["name"]
async def client_ready(self, client, db):
self.db = db
async def myrz_keycmd(self, m):
self.db.set("myrz", "key", str(m.raw_text.split(" ", 1)[1]))
await m.edit("[AntiPublic MYRZ] Токен установлен")
@loader.owner
async def msrchcmd(self, m):
"Получить пароли почты/логина"
key = self.db.get("myrz", "key", None)
if not key:
await m.edit(
"<b>Укажите ключ из антипаблика myrz!</b>\n\n<code>.myrz_key [KEY]</code>"
)
return
if args := utils.get_args_raw(m):
await m.edit("Делаю запрос...")
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36"
}
data = requests.post(
"https://myrz.org/api/email_search.php",
data={"key": key, "email": args},
headers=headers,
).json()
try:
if data["success"] is True:
psswds = "\n".join(
f"<code>{i['line']}</code>" for i in data["results"]
)
psswds += f"\n\nОсталось запросов: {data['awailableQueries']}\nНайдено: {data['resultCount']}\nЗапрос: <code>{args}</code>"
await utils.answer(m, str(psswds))
else:
await m.edit(
f"Ничего не найдено по запросу <code>{args}</code>\nОсталось запросов: {data['awailableQueries']}"
)
except Exception:
await m.edit(str(data))
else:
await m.edit("shit...")

View File

@@ -0,0 +1,121 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import requests
from .. import loader, utils # type: ignore
@loader.tds
class nkapimdMod(loader.Module):
strings = {"name": "NekosLife"}
@loader.owner
async def nkcmd(self, m):
"Отправить фото/гиф\nПо умолчанию отправляется neko\nМожно указать другую категорию(.nkct)"
args = utils.get_args_raw(m)
typ = None
if args:
if args in types_of:
typ = args
else:
typ = "neko"
if typ is None:
return await m.edit("<b>не знаю такого</b>")
await m.edit("<b>Mmm...</b>")
reply = await m.get_reply_message()
await m.client.send_file(
m.to_id,
requests.get(f"https://nekos.life/api/v2/img/{typ}").json()["url"],
reply_to=reply.id if reply else None,
)
await m.delete()
async def nkctcmd(self, m):
await m.edit(
"Доступные категории:\n" + "\n".join(f"<code>{i}</code>" for i in types_of)
)
types_of = [
"femdom",
"tickle",
"classic",
"ngif",
"erofeet",
"meow",
"erok",
"poke",
"les",
"hololewd",
"lewdk",
"keta",
"feetg",
"nsfw_neko_gif",
"eroyuri",
"kiss",
"_8ball",
"kuni",
"tits",
"pussy_jpg",
"cum_jpg",
"pussy",
"lewdkemo",
"lizard",
"slap",
"lewd",
"cum",
"cuddle",
"spank",
"smallboobs",
"goose",
"Random_hentai_gif",
"avatar",
"fox_girl",
"nsfw_avatar",
"hug",
"gecg",
"boobs",
"pat",
"feet",
"smug",
"kemonomimi",
"solog",
"holo",
"wallpaper",
"bj",
"woof",
"yuri",
"trap",
"anal",
"baka",
"blowjob",
"holoero",
"feed",
"neko",
"gasm",
"hentai",
"futanari",
"ero",
"solo",
"waifu",
"pwankg",
"eron",
"erokemo",
]

View File

@@ -0,0 +1,47 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
# requires: pornhub-api
from random import choice
from pornhub_api import PornhubApi
from telethon import types
from .. import loader, utils # type: ignore
@loader.tds
class PhSrchMod(loader.Module):
strings = {"name": "PornHub"}
@loader.owner
async def sphcmd(self, m: types.Message):
"Найти видео на pornhub"
if args := utils.get_args_raw(m):
srch = args
else:
return await m.delete()
api = PornhubApi()
data = api.search.search(srch, ordering="mostviewed")
video = choice(data.videos)
await utils.asnwer(
m,
f'<b>Нашёл кое-что по запросу</b> <code>{srch}</code>: <a href="{video.url}">{video.title}</a>',
)

View File

@@ -0,0 +1,239 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
# requires: glQiwiApi pycryptodome
import asyncio
import hashlib
from Crypto.Cipher import DES
from Crypto.Util.Padding import pad, unpad
from glQiwiApi import QiwiWrapper
from telethon import types
from .. import loader, utils # type: ignore
@loader.tds
class QiwiMod(loader.Module):
"Модуль для работы с Qiwi кошельком"
strings = {
"name": "Qiwi",
"pref": "<b>[Qiwi]</b> ",
"need_arg": "{}need args...",
"phone_setted_successfully": "{}Номер и токен установлены!",
"p2p_setted_successfully": "{}Секретный P2P токен установлен!",
"need_phone_token": "{}Необходимо установить номер токен!",
"need_p2p": "{}Необходимо установить P2P токен!",
"bal": "{}Баланс: {}",
"commission": "{}Итоговая сумма: {}\nКомиссия Qiwi: {}\nСумма к зачислению: {}",
"sent": "{}Средства отправлены!\nID: <code>{}</code>",
"bill_created": "{}Счёт создан!\n{}\nСтатус счёта: <code>{}</code>",
"bill_payed": "Оплачен",
"bill_notpayed": "Не оплачен",
"bill_disabled": "Автопроверка отключена после 5 минут",
"bill_link_exp": "Ссылка истекла по причине оплаты",
}
_db = "QiwiMod"
async def client_ready(self, _, db):
self.db = db
self.me = await _.get_me()
def __pad(self, text: bytes):
return text[:8] if len(text) > 8 else text
def __get_enc(self, key: str) -> str:
c = DES.new(
self.__pad(
hashlib.md5((self.me.phone + str(self.me.id)).encode("utf-8"))
.hexdigest()
.encode("utf-8")
),
DES.MODE_ECB,
)
return unpad(c.decrypt(self.db.get(self._db, key, b"")), 8).decode("utf-8")
def __set_enc(self, key: str, value: str):
c = DES.new(
self.__pad(
hashlib.md5((self.me.phone + str(self.me.id)).encode("utf-8"))
.hexdigest()
.encode("utf-8")
),
DES.MODE_ECB,
)
self.db.set(self._db, key, c.encrypt(pad(value.encode("utf-8"), 8)))
def __need_token(func):
async def wrapper(self, m: types.Message):
if not self.db.get(self._db, "phone") or not self.db.get(self._db, "token"):
return await utils.answer(
m,
self.strings("need_phone_token").format(self.strings("pref")),
)
return await func(self, m)
return wrapper
def __need_p2p(func):
async def wrapper(self, m: types.Message):
return (
await func(self, m)
if self.db.get(self._db, "p2p")
else await utils.answer(
m,
self.strings("need_p2p").format(self.strings("pref")),
)
)
return wrapper
async def qsetp2pcmd(self, m: types.Message):
""".qsetp2p <TOKEN>
Установить секретный p2p ключ"""
if args := utils.get_args(m):
self.__set_enc("p2p", args[0])
return await utils.answer(
m, self.strings("p2p_setted_successfully").format(self.strings("pref"))
)
await utils.answer(m, self.strings("need_arg").format(self.strings("pref")))
async def qsetcmd(self, m: types.Message):
""".qset <phone> <TOKEN>
Установить номер и токен"""
if args := utils.get_args(m):
self.__set_enc("phone", args[0])
self.__set_enc("token", args[1])
return await utils.answer(
m,
self.strings("phone_setted_successfully").format(self.strings("pref")),
)
await utils.answer(m, self.strings("need_arg").format(self.strings("pref")))
@__need_token
async def qbalcmd(self, m: types.Message):
".qbal - Получить баланс"
async with QiwiWrapper(self.__get_enc("token"), self.__get_enc("phone")) as w:
w: QiwiWrapper
bal = await w.get_balance()
await utils.answer(
m,
self.strings("bal").format(
self.strings("pref"), str(bal.amount) + bal.currency.symbol
),
)
@__need_token
async def qswalcmd(self, m: types.Message):
".qswal <phone> <amount> <?comment> - Отправить средства по номеру"
async with QiwiWrapper(self.__get_enc("token"), self.__get_enc("phone")) as w:
w: QiwiWrapper
args = utils.get_args(m)
args_raw = utils.get_args_raw(m)
trans_id = await w.to_wallet(
to_number=args[0],
amount=int(args[1]),
comment=args_raw.split(args[1])[1].strip() if len(args) > 2 else None,
)
await utils.answer(
m,
self.strings("sent").format(
self.strings("pref"), str(trans_id.payment_id)
),
)
@__need_token
async def qscardcmd(self, m: types.Message):
".qscard <card_num[no_spaces]> <amount> - Отправить средства на карту"
async with QiwiWrapper(self.__get_enc("token"), self.__get_enc("phone")) as w:
w: QiwiWrapper
args = utils.get_args(m)
trans_id = await w.to_card(
to_card=args[0],
trans_sum=float(args[1]),
)
await utils.answer(
m,
self.strings("sent").format(
self.strings("pref"), str(trans_id.payment_id)
),
)
@__need_token
async def qcmscmd(self, m: types.Message):
".qcms <card_num/phone> <amount> - Посчитать комиссию"
async with QiwiWrapper(self.__get_enc("token"), self.__get_enc("phone")) as w:
w: QiwiWrapper
args = utils.get_args(m)
commission = await w.calc_commission(args[0], float(args[1]))
await utils.answer(
m,
self.strings("commission").format(
self.strings("pref"),
str(commission.withdraw_sum.amount)
+ commission.withdraw_sum.currency.symbol,
str(commission.qiwi_commission.amount)
+ commission.qiwi_commission.currency.symbol,
str(commission.enrollment_sum.amount)
+ commission.enrollment_sum.currency.symbol,
),
)
@__need_p2p
async def qp2pcmd(self, m: types.Message):
".qp2p <amount> <?comment> - Создать счёт для оплаты"
async with QiwiWrapper(secret_p2p=self.__get_enc("p2p")) as w:
w: QiwiWrapper
args = utils.get_args(m)
args_raw = utils.get_args_raw(m)
bill = await w.create_p2p_bill(
amount=args[0],
comment=args_raw.split(args[0])[1].strip() if len(args) > 1 else None,
)
last_status = None
url = bill.pay_url
n = 0
while True:
if n >= 72:
await utils.answer(
m,
self.strings("bill_created").format(
self.strings("pref"),
self.strings("bill_link_exp"),
self.strings("bill_disabled"),
),
)
break
status = (await w.check_p2p_bill_status(bill_id=bill.id)) == "PAID"
if status != last_status:
last_status = status
await utils.answer(
m,
self.strings("bill_created").format(
self.strings("pref"),
url,
self.strings("bill_payed" if status else "bill_notpayed"),
),
)
if status:
break
n += 1
await asyncio.sleep(5)

View File

@@ -0,0 +1,11 @@
# FTG-Modules
📥 Все мои Friendly-Telegram модули
`✅ Совместимы с Friendly-Telegram, GeekTG Userbot`
[@DekFTGModules](https://t.me/DekFTGModules)
---
[Шаблон багрепорта](/bug_report.md) | [Поддержка [Чат]](https://t.me/dftgmchat)

View File

@@ -0,0 +1,73 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import random
import re
from .. import loader, utils # type: ignore
@loader.tds
class RandomizerMod(loader.Module):
strings = {"name": "Рандомайзер"}
prefix = "<b>[Рандомайзер]</b>\n"
@loader.owner
async def rndintcmd(self, m):
".rndint <int> <int> - рандомное число из заданногоо диапозона"
args = utils.get_args_raw(m)
check = re.compile(r"^(\d+)\s+(\d+)$")
if check.match(args):
fr, to = check.match(args).groups()
if int(fr) < int(to):
rndint = random.randint(int(fr), int(to))
await m.edit(
self.prefix
+ f"<b>Режим:</b> Рандомное число из диапозона\n<b>Диапозон:</b> <code>{fr}-{to}</code>\n<b>Выпало число:</b> <code>{rndint}</code>"
)
else:
await m.edit(f"{self.prefix}Вася, укажи диапозон чисел!")
else:
await m.edit(f"{self.prefix}Вася, укажи диапозон чисел!")
@loader.owner
async def rndelmcmd(self, m):
".rndelm <элементы через запятую> - рандомный элемент из списка"
args = utils.get_args_raw(m)
if not args:
await m.edit(f"{self.prefix}Вася, напиши список элементов через запятую!")
return
lst = [i.strip() for i in args.split(",") if i]
await m.edit(
self.prefix
+ f"<b>Режим:</b> Рандомный элемент из списка\n<b>Список:</b> <code>{', '.join(lst)}</code>\n<b>Выпало:</b> <code>{random.choice(lst)}</code>"
)
@loader.owner
async def rndusercmd(self, m):
".rnduser - выбор рандомного юзера из чата"
if not m.chat:
await m.edit(f"{self.prefix}<b>Это не чат</b>")
return
users = await m.client.get_participants(m.chat)
user = random.choice(users)
await m.edit(
self.prefix
+ f'<b>Режим:</b> Рандомный юзер из чата\n<b>Юзер:</b> <a href="tg://user?id={user.id}">{user.first_name}</a> | <code>{user.id}</code>'
)

View File

@@ -0,0 +1,120 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import contextlib
from random import choice
from telethon import functions
from .. import loader # type: ignore
@loader.tds
class ReactionsMod(loader.Module):
"Telegram reactions"
strings = {"name": __doc__}
async def client_ready(self, client, _):
self.client = client
def reaction(func):
async def wrapper(self, *args):
"<reply>"
message = args[0]
emoji = await func(self)
if reply := await message.get_reply_message():
with contextlib.suppress(Exception):
await self.client(
functions.messages.SendReactionRequest(
reply.peer_id, reply.id, reaction=emoji
)
)
if message.out:
await message.delete()
return wrapper
@reaction
async def randrcmd(self):
return choice("👍👎❤️🔥🎉🤩😱😁😢💩🤮🥰🤯🤔🤬👏")
@reaction
async def lovecmd(self):
return ""
@reaction
async def sadcmd(self):
return "😢"
@reaction
async def nastycmd(self):
return "🤮"
@reaction
async def cutecmd(self):
return "🥰"
@reaction
async def clapcmd(self):
return "👏"
@reaction
async def fuckcmd(self):
return "🤬"
@reaction
async def wtfcmd(self):
return "🤯"
@reaction
async def hmmcmd(self):
return "🤔"
@reaction
async def hooraycmd(self):
return "🎉"
@reaction
async def likecmd(self):
return "👍"
@reaction
async def dislikecmd(self):
return "👎"
@reaction
async def firecmd(self):
return "🔥"
@reaction
async def omgcmd(self):
return "😱"
@reaction
async def wowcmd(self):
return "🤩"
@reaction
async def hehecmd(self):
return "😁"
@reaction
async def shitcmd(self):
return "💩"

View File

@@ -0,0 +1,209 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import datetime
import random
from telethon import events, functions
from telethon.errors.rpcerrorlist import YouBlockedUserError
from .. import loader, utils # type: ignore
def register(cb):
cb(RandomNSFWMod())
class RandomNSFWMod(loader.Module):
"""RndNsfw"""
strings = {"name": "RndNsfw"}
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 crncmd(self, message):
"""
Random pic from @wallhaven_nsfw
"""
await message.edit("<b>_-*Wallhaven_NSFW*-_</b>")
chat = "@wallhaven_nsfw"
result = await message.client(
functions.messages.GetHistoryRequest(
peer=chat,
offset_id=0,
offset_date=datetime.datetime.now(),
add_offset=random.choice(range(1, 101, 2)),
limit=1,
max_id=0,
min_id=0,
hash=0,
)
)
await message.delete()
await message.client.send_file(message.to_id, result.messages[0].media)
async def crdcmd(self, message):
"""
Random post from @dvach18
"""
await message.edit("<b>_-*2ch_18+*-_</b>")
chat = "@dvach18"
result = await message.client(
functions.messages.GetHistoryRequest(
peer=chat,
offset_id=0,
offset_date=datetime.datetime.now(),
add_offset=random.randint(0, 1000),
limit=1,
max_id=0,
min_id=0,
hash=0,
)
)
await message.delete()
await message.client.send_message(message.to_id, result.messages[0])
async def crdbcmd(self, message):
"""
Random post from @ru2ch_ban
"""
await message.edit("<b>_-*2ch_Ban*-_</b>")
chat = "@ru2ch_ban"
result = await message.client(
functions.messages.GetHistoryRequest(
peer=chat,
offset_id=0,
offset_date=datetime.datetime.now(),
add_offset=random.randint(0, 1000),
limit=1,
max_id=0,
min_id=0,
hash=0,
)
)
await message.delete()
await message.client.send_message(message.to_id, result.messages[0])
async def crfncmd(self, message):
"""
Random Furry from channel
"""
links = ["https://t.me/joinchat/AAAAAEKWTxZPnvacazjM2Q"]
await message.edit("<b>_-*Furry*-_</b>")
chat = links[random.randint(0, len(links) - 1)]
result = await message.client(
functions.messages.GetHistoryRequest(
peer=chat,
offset_id=0,
offset_date=datetime.datetime.now(),
add_offset=random.randint(0, 1000),
limit=1,
max_id=0,
min_id=0,
hash=0,
)
)
await message.delete()
await message.client.send_message(message.to_id, result.messages[0])
async def crhcmd(self, message):
"""
Random Hentai from channels
"""
#
links = [
"https://t.me/joinchat/AAAAAEWrsWbhMQppqTMNUw",
"https://t.me/joinchat/AAAAAEkJjU8L9J6TDdkAIw",
"@hentai",
]
await message.edit("<b>_-*Hentai*-_</b>")
chat = links[random.randint(0, len(links) - 1)]
result = await message.client(
functions.messages.GetHistoryRequest(
peer=chat,
offset_id=0,
offset_date=datetime.datetime.now(),
add_offset=random.randint(0, 1000),
limit=1,
max_id=0,
min_id=0,
hash=0,
)
)
await message.delete()
await message.client.send_message(message.to_id, result.messages[0])
async def rh2dcmd(self, message):
"""
Random Hentai2D pic/gif from @murglar_bot
You can type category as argument(mustn't)
"""
chat = "@murglar_bot"
args = utils.get_args_raw(message)
if args:
arg = args
else:
arg = None
await message.edit("<b>_-*Hentai_2D*-_</b>")
async with message.client.conversation(chat) as conv:
try:
response = conv.wait_event(
events.NewMessage(incoming=True, from_users=507490514)
)
if arg:
m1 = await message.client.send_message(chat, f"/nudes2d {arg}")
else:
m1 = await message.client.send_message(chat, "/nudes2d")
response = await response
except YouBlockedUserError:
await message.reply("<code>Unblock @murglar_bot</code>")
return
await message.delete()
await m1.delete()
await response.delete()
await message.client.send_message(message.to_id, response.message)
async def rn3dcmd(self, message):
"""
Random Nudes3D from @murglar_bot
"""
chat = "@murglar_bot"
await message.edit("<b>_-*Nudes_3D*-_</b>")
async with message.client.conversation(chat) as conv:
try:
response = conv.wait_event(
events.NewMessage(incoming=True, from_users=507490514)
)
m1 = await message.client.send_message(chat, "/nudes3d")
response = await response
except YouBlockedUserError:
await message.reply("<code>Unblock @murglar_bot</code>")
return
await message.delete()
await m1.delete()
await response.delete()
await message.client.send_message(message.to_id, response.message)

View File

@@ -0,0 +1,72 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
from telethon import types
import rsa
import aioboto3
from .. import loader, utils # type: ignore
@loader.tds
class S3Mod(loader.Module):
"""S3 file manager"""
strings = {"name": "S3 file manager", "pref": "<b>[S3]</b> {}"}
async def client_ready(self, client, db):
self._db = db
self._db_name = "S3"
async def set_auth_data(
self, endpoint: str, region: str, username: str, password: str, bucket: str
) -> None:
self._db.set(self._db_name, "endpoint", endpoint)
self._db.set(self._db_name, "region", region)
self._db.set(self._db_name, "username", username)
self._db.set(self._db_name, "password", password)
self._db.set(self._db_name, "bucket", bucket)
async def get_client(self) -> aioboto3.Session.client:
session = aioboto3.Session(
aws_access_key_id=self._db.get(self._db_name, "username"),
aws_secret_access_key=self._db.get(self._db_name, "password"),
region_name=self._db.get(self._db_name, "region"),
)
return session.client(
service_name="s3",
endpoint_url=f"https://{self._db.get(self._db_name, 'endpoint')}",
)
@loader.owner
async def s3upcmd(self, m: types.Message):
reply = await m.get_reply_message()
if not reply or not reply.document:
return await utils.answer(m, self.strings("s3").format("Reply to a document"))
session = await self.generate_session()
client = await self.get_client()
async with client as s3:
await s3.upload_fileobj(
await bot.download_file_by_id(video.file_id),
os.getenv("S3_BUCKET_NAME"),
video_s3_path,
)
# @loader.owner
# async def s3authcmd(self, m: types.Message):
# pass

View File

@@ -0,0 +1,65 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import io
from telethon import types
from .. import loader, utils # type: ignore
@loader.tds
class SaverMod(loader.Module):
strings = {"name": "Saver"}
async def client_ready(self, client, db):
self.db = db
@loader.owner
async def бляcmd(self, m: types.Message):
".бля <reply> - скачать самоуничтожающееся фото"
reply = await m.get_reply_message()
if not reply or not reply.media or not reply.media.ttl_seconds:
return await m.edit("бля")
await m.delete()
new = io.BytesIO(await reply.download_media(bytes))
new.name = reply.file.name
await m.client.send_file("me", new)
@loader.owner
async def swбляcmd(self, m: types.Message):
"Переключить режим автозагрузки фото в лс"
new_val = not self.db.get("Saver", "state", False)
self.db.set("Saver", "state", new_val)
await utils.answer(m, f"<b>[Saver]</b> <pre>{new_val}</pre>")
async def watcher(self, m: types.Message):
if (
m
and m.media
and m.media.ttl_seconds
and self.db.get("Saver", "state", False)
):
new = io.BytesIO(await m.download_media(bytes))
new.name = m.file.name
await m.client.send_file(
"me",
new,
caption=f"<b>[Saver] Фото от</b> {f'@{m.sender.username}' if m.sender.username else m.sender.first_name} | <pre>{m.sender.id}</pre>\n"
f"Время жизни: <code>{m.media.ttl_seconds}sec</code>",
)

View File

@@ -0,0 +1,52 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
from .. import loader, utils # type: ignore
def register(cb):
cb(SearcherMod())
class SearcherMod(loader.Module):
strings = {"name": "Searcher"}
def __init__(self):
self.name = self.strings["name"]
async def srchcmd(self, m):
""".srch <канал/чат> <запрос>
Найти пост в канале/чате сообщение и переслать
"""
args = utils.get_args_raw(m)
if not args:
return await m.edit("[Search] Укажите аргументы!")
if len(args.split(" ")) == 1:
return await m.edit("[Search] Укажите запрос!")
ch = args.split(" ")[0]
req = args.split(" ", 1)[1]
try:
ms = await m.client.get_messages(ch, search=req, limit=100)
except Exception as e:
return await m.edit("[Searcher] " + str(e.args))
if ms.total == 0:
return await m.edit("[Searcher] Данных по запросу нет")
for i in ms:
await i.forward_to(m.to_id)
await m.delete()

View File

@@ -0,0 +1,49 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import re
from telethon.errors import ChannelInvalidError
from .. import loader, utils # type: ignore
@loader.tds
class SenderMod(loader.Module):
strings = {"name": "Sender"}
@loader.owner
async def sndcmd(self, m):
""".snd <канал/чат/id> <reply>
Отпрпвить сообшение в чат/канал(без авторства)
"""
args = utils.get_args_raw(m)
reply = await m.get_reply_message()
if not args:
return await m.edit("[Sender] Укажите канал/чат")
try:
this = await m.client.get_input_entity(
int(args) if re.match(r"-{0,1}\d+", args) else args
)
except ChannelInvalidError:
return await m.edit("[Sender] Такого канала/чата не существует!")
except Exception as e:
return await m.edit("[Sender] Неизвестная мне ошибка:\n" + " ".join(e.args))
await m.client.send_message(this, reply)
await m.edit("[Sender] Сообщение отправлено!")

View File

@@ -0,0 +1,91 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
# requires: ShazamAPI
import io
from ShazamAPI import Shazam
from .. import loader, utils # type: ignore
@loader.tds
class ShazamMod(loader.Module):
"""Shazam API"""
strings = {"name": "Shazam API"}
tag = "<b>[Shazam]</b> "
@loader.owner
async def shazamcmd(self, m):
""".shazam <reply to audio> - распознать трек"""
s = await get_audio_shazam(m)
if not s:
return
try:
shazam = Shazam(s.track.read())
recog = shazam.recognizeSong()
track = next(recog)[1]["track"]
await m.client.send_file(
m.to_id,
file=track["images"]["background"],
caption=self.tag + "Распознанный трек: " + track["share"]["subject"],
reply_to=s.reply.id,
)
await m.delete()
except:
await m.edit(f"{self.tag}Не удалось распознать...")
async def shazamtextcmd(self, m):
""".shazamtext <reply to audio> - узнать текст трека"""
s = await get_audio_shazam(m)
if not s:
return
try:
shazam = Shazam(s.track.read())
recog = shazam.recognizeSong()
track = next(recog)[1]["track"]
text = track["sections"][1]["text"]
await utils.answer(
m,
"\n".join(
self.tag + f"Текст трека {track['share']['subject']}\n\n" + text
),
)
except Exception:
await m.edit(f"{self.tag}Не удалось распознать... | Текста нет...")
async def get_audio_shazam(m):
class rct:
track = io.BytesIO()
reply = None
reply = await m.get_reply_message()
if reply and reply.file and reply.file.mime_type.split("/")[0] == "audio":
ae = rct()
await utils.answer(m, "<b>[Shazam]</b> Скачиваю...")
ae.track = io.BytesIO(await reply.download_media(bytes))
ae.reply = reply
await m.edit("<b>[Shazam]</b> Распознаю...")
return ae
else:
await utils.answer(m, "<b>[Shazam]</b> reply to audio...")
return None

View File

@@ -0,0 +1,40 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import os
from .. import loader # type: ignore
@loader.tds
class TesseractMod(loader.Module):
strings = {"name": "Tesseract"}
@loader.owner
async def ocrcmd(self, m):
"Распознать текст с картинки"
reply = await m.get_reply_message()
if not reply:
return await m.edit("[OCR] Реплай на пикчу")
await m.edit("[OCR] Распознаём")
file = await reply.download_media()
rec = os.popen(f"tesseract -l rus+eng {file} stdout").read()
await m.edit(
"[OCR]\n" + (("<code>" + rec + "</code>") if rec != "" else "НЕ_РАСПОЗНАНО")
)
os.remove(file)

View File

@@ -0,0 +1,48 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import random
from .. import loader, utils # type: ignore
@loader.tds
class TryMod(loader.Module):
"""Try"""
strings = {"name": "Try"}
@loader.owner
async def trycmd(self, message):
""".try действие"""
do = utils.get_args_raw(message)
rnd = random.choice(
[
"Удачно",
"Удачно",
"Неудачно",
"Неудачно",
"Удачно",
"Неудачно",
"Удачно",
"Неудачно",
"Удачно",
"Неудачно",
]
)
await message.edit(f"<b>{do}</b>\n\n<code>{rnd}</code>")

View File

@@ -0,0 +1,298 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
import contextlib
import os
import random as rnd
import re
import string
import requests
from moviepy.editor import *
from telethon import types
from .. import loader, utils # type: ignore
# meta developer: @D4n13l3k00
# requires: moviepy requests
@loader.tds
class VideoEditorMod(loader.Module):
"Module for working with video"
strings = {
"name": "VideoEditor",
"downloading": "<b>[{}]</b> Downloading...",
"working": "<b>[{}]</b> Working...",
"exporting": "<b>[{}]</b> Exporting...",
"set_value": "<b>[{}]</b> Specify the level from {} to {}...",
"reply": "<b>[{}]</b> reply to video/gif...",
"set_time": "<b>[{}]</b> Specify the time in the format start(ms):end(ms)",
"set_link": "<b>[{}]</b> Enter link...",
}
@loader.owner
async def xflipvcmd(self, m: types.Message):
""".xflipv <reply_to_video> - Flip video by X"""
vid = await get_video(self, m, "XFlip")
if not vid:
return
out = vid.video.fx(vfx.mirror_x)
await go_out(self, vid.message, vid, out, vid.pref)
@loader.owner
async def yflipvcmd(self, m: types.Message):
""".yflipv <reply_to_video> - Flip video by Y"""
vid = await get_video(self, m, "YFlip")
if not vid:
return
out = vid.video.fx(vfx.mirror_y)
await go_out(self, vid.message, vid, out, vid.pref)
@loader.owner
async def bwvcmd(self, m: types.Message):
""".bwv <reply_to_video> - BlackWhite"""
vid = await get_video(self, m, "BlackWhite")
if not vid:
return
out = vid.video.fx(vfx.blackwhite)
await go_out(self, vid.message, vid, out, vid.pref)
@loader.owner
async def revvcmd(self, m: types.Message):
""".revv <reply_to_video> - Reverse video"""
vid = await get_video(self, m, "Reverse")
if not vid:
return
out = vid.video.fx(vfx.time_mirror)
await go_out(self, vid.message, vid, out, vid.pref)
@loader.owner
async def paintvcmd(self, m: types.Message):
""".paintv <reply_to_video> - Paint effect"""
vid = await get_video(self, m, "Paint")
if not vid:
return
out = vid.video.fx(vfx.painting)
await go_out(self, vid.message, vid, out, vid.pref)
@loader.owner
async def invertvcmd(self, m: types.Message):
""".invertv <reply_to_video> - Invert colors"""
vid = await get_video(self, m, "Invert")
if not vid:
return
out = vid.video.fx(vfx.invert_colors)
await go_out(self, vid.message, vid, out, vid.pref)
@loader.owner
async def rmsvcmd(self, m: types.Message):
""".rmsv <reply_to_video> - Remove sound (to gif without compression)"""
vid = await get_video(self, m, "NoAudio")
if not vid:
return
out = vid.video.without_audio()
await go_out(self, vid.message, vid, out, vid.pref)
@loader.owner
async def cutvcmd(self, m: types.Message):
""".cutv <int [Default 30]> <reply_to_video> - Cut video"""
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings("set_time", m).format("Cut"))
r = re.compile(r"^(?P<start>\d+){0,1}:(?P<end>-?\d+){0,1}$")
ee = r.match(args)
if not ee:
return await utils.answer(m, self.strings("set_time", m).format("Cut"))
start = int(ee.group("start")) if ee.group("start") else 0
end = int(ee.group("end")) if ee.group("end") else None
vid = await get_video(self, m, "Cut")
if not vid:
return
out = vid.video.subclip(start, end)
await go_out(self, vid.message, vid, out, vid.pref)
@loader.owner
async def audvcmd(self, m: types.Message):
""".audv <link> <reply_to_video> - Add audio to video"""
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings("set_link", m).format("Audio"))
r = re.compile(
r"((http|https)\:\/\/)?[a-zA-Z0-9\.\/\?\:@\-_=#]+\.([a-zA-Z]){2,6}([a-zA-Z0-9\.\&\/\?\:@\-_=#])*"
)
ee = r.match(args)
if not ee:
return await utils.answer(m, self.strings("set_link", m).format("Audio"))
vid = await get_video(self, m, "Audio")
if not vid:
return
a = requests.get(args)
nm = "".join(rnd.sample(string.ascii_letters, 24)) + ".mp3"
if a.status_code == 200:
open(nm, "wb").write(a.content)
else:
return
out = vid.video
out.audio = CompositeAudioClip([AudioFileClip(nm)])
await go_out(self, vid.message, vid, out, vid.pref)
try:
os.remove(nm)
except Exception:
pass
@loader.owner
async def fpsvcmd(self, m: types.Message):
""".fpsv <int [Default 30]> <reply_to_video> - Change fps"""
args = utils.get_args_raw(m)
if not args:
fps = 30
elif re.match(r"^\d+$", args) and (0 < int(args) < 241):
fps = int(args)
else:
return await utils.answer(
m, self.strings("set_value", m).format("FPS", 1, 240)
)
vid = await get_video(self, m, "FPS")
if not vid:
return
out = vid.video.set_fps(fps)
await go_out(self, vid.message, vid, out, vid.pref)
@loader.owner
async def marginvcmd(self, m: types.Message):
""".marginv <int [Default 5]> <reply_to_video> - Add marging"""
args = utils.get_args_raw(m)
if not args:
margin = 5
elif re.match(r"^\d+$", args) and (0 < int(args) < 101):
margin = int(args)
else:
return await utils.answer(
m, self.strings("set_value", m).format("Scale", 1, 100)
)
vid = await get_video(self, m, "Margin")
if not vid:
return
out = vid.video.fx(vfx.margin, margin)
await go_out(self, vid.message, vid, out, vid.pref)
@loader.owner
async def speedvcmd(self, m: types.Message):
""".speedv <float [Default 1.5]> <reply_to_video> - Speed"""
args = utils.get_args_raw(m)
if not args:
speed = 1.5
elif re.match(r"^\d+(\.\d+)?$", args) and (0.009 < float(args) < 10.1):
speed = float(args)
else:
return await utils.answer(
m, self.strings("set_value", m).format("Speed", 0.01, 10.0)
)
vid = await get_video(self, m, "Speed")
if not vid:
return
out = vid.video.fx(vfx.speedx, speed)
await go_out(self, vid.message, vid, out, vid.pref)
@loader.owner
async def contrastvcmd(self, m: types.Message):
""".contrastv <float [Default 1.5]> <reply_to_video> - Contrast"""
args = utils.get_args_raw(m)
if not args:
contrast = 1.5
elif re.match(r"^\d+(\.\d+)?$", args) and (0.009 < float(args) < 100.1):
contrast = float(args)
else:
return await utils.answer(
m, self.strings("set_value", m).format("Contrast", 0.01, 100.0)
)
vid = await get_video(self, m, "Contrast")
if not vid:
return
out = vid.video.fx(vfx.lum_contrast, contrast=contrast)
await go_out(self, vid.message, vid, out, vid.pref)
@loader.owner
async def lumvcmd(self, m: types.Message):
""".lumv <float [Default 25]> <reply_to_video> - Lum"""
args = utils.get_args_raw(m)
if not args:
lum = 25
elif re.match(r"^\d+(\.\d+)?$", args) and (0.009 < float(args) < 100.1):
lum = float(args)
else:
return await utils.answer(
m, self.strings("set_value", m).format("Lum", 0.01, 100.0)
)
vid = await get_video(self, m, "Lum")
if not vid:
return
out = vid.video.fx(vfx.lum_contrast, lum=lum)
await go_out(self, vid.message, vid, out, vid.pref)
@loader.owner
async def scalevcmd(self, m: types.Message):
""".scalev <float [Default 0.75]> <reply_to_video> - Scale("Resize") video"""
args = utils.get_args_raw(m)
if not args:
scale = 0.75
elif re.match(r"^\d+(\.\d+)?$", args) and (0.009 < float(args) < 100.1):
scale = float(args)
else:
return await utils.answer(
m, self.strings("set_value", m).format("Scale", 0.01, 100.0)
)
vid = await get_video(self, m, "Scale")
if not vid:
return
out = vid.video.resize(scale)
await go_out(self, vid.message, vid, out, vid.pref)
class VideoEditorClass:
video: VideoFileClip = None
message = None
pref: str = None
reply = None
async def get_video(self, m, pref: str):
r = await m.get_reply_message()
if r and r.file and r.file.mime_type.split("/")[0] in ["video"]:
vid = VideoEditorClass()
vid.pref = pref
vid.reply = r
vid.message = await utils.answer(m, self.strings("downloading", m).format(pref))
vid.video = VideoFileClip(await r.download_media())
return vid
await utils.answer(m, self.strings("reply", m).format(pref))
async def go_out(self, m, vid: VideoEditorClass, out: VideoFileClip, pref):
m = await utils.answer(m, self.strings("exporting", m).format(pref))
filename = "".join(rnd.sample(string.ascii_letters, 24)) + ".mp4"
out.write_videofile(filename)
await utils.answer(
m, open(filename, "rb"), reply_to=vid.reply.id, supports_streaming=True
)
with contextlib.suppress(Exception):
os.remove(filename)
with contextlib.suppress(Exception):
os.remove(vid.video.filename)

View File

@@ -0,0 +1,71 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import os
import random
import string
from .. import loader, utils # type: ignore
@loader.tds
class VSHAKALMod(loader.Module):
strings = {"name": "Video Shakal"}
@loader.owner
async def vshcmd(self, m):
".vsh <реплай на видео> <уровень от 1 до 6 (по умолчанию 3)>\n" "Сшакалить видео"
reply = await m.get_reply_message()
if not reply:
return await utils.answer(m, "reply...")
if reply.file.mime_type.split("/")[0] != "video":
return await utils.answer(m, "shit...")
args = utils.get_args_raw(m)
lvls = {
"1": "1M",
"2": "0.5M",
"3": "0.1M",
"4": "0.05M",
"5": "0.01M",
}
if args:
if args in lvls:
lvl = lvls[args]
else:
return await utils.answer(m, "не знаю такого")
else:
lvl = lvls["3"]
m = await utils.answer(m, "[Шакал] Качаю...")
vid = await reply.download_media(
"".join(random.choice(string.ascii_letters) for _ in range(25)) + ".mp4"
)
out = "".join(random.choice(string.ascii_letters) for _ in range(25)) + ".mp4"
m = await utils.answer(m, "[Шакал] Шакалю...")
os.system(
f'ffmpeg -y -i "{vid}" '
f"-b:v {lvl} -maxrate:v {lvl} "
f'-b:a {lvl} -maxrate:a {lvl} "{out}"'
)
m = await utils.answer(m, "[Шакал] Отправляю...")
await utils.answer(m, out)
os.remove(vid)
os.remove(out)

View File

@@ -0,0 +1,58 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
from io import BytesIO
# requires: pydub speechRecognition
import speech_recognition as srec
from pydub import AudioSegment as auds
from .. import loader, utils # type: ignore
@loader.tds
class VoiceRecognitionMod(loader.Module):
"Распознавание речи через Google Recognition API"
strings = {"name": "VoiceRecognition", "pref": "<b>[VRC]</b> "}
@loader.owner
async def recvcmd(self, m):
".recv <reply to voice/audio> - распознать речь"
reply = await m.get_reply_message()
if reply and reply.file.mime_type.split("/")[0] == "audio":
m = await utils.answer(m, self.strings["pref"] + "Downloading...")
source = BytesIO(await reply.download_media(bytes))
source.name = reply.file.name
out = BytesIO()
out.name = "recog.wav"
m = await utils.answer(m, self.strings["pref"] + "Converting...")
auds.from_file(source).export(out, "wav")
out.seek(0)
m = await utils.answer(m, self.strings["pref"] + "Processing...")
recog = srec.Recognizer()
sample_audio = srec.AudioFile(out)
with sample_audio as audio_file:
audio_content = recog.record(audio_file)
await utils.answer(
m,
self.strings["pref"]
+ recog.recognize_google(audio_content, language="ru-RU"),
)
else:
await utils.answer(m, self.strings["pref"] + "reply to audio/voice...")

View File

@@ -0,0 +1,47 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import aiohttp
from .. import loader, utils # type: ignore
@loader.tds
class WttrInMod(loader.Module):
"""WttrIn"""
strings = {"name": __doc__}
@loader.owner
async def wthrcmd(self, m):
""".wthr <Город если надо>
Получить текущую погоду
"""
rr = utils.get_args_raw(m)
await utils.answer(
m,
"<code>{}</code>".format(
await (
await aiohttp.ClientSession().get(
f"https://wttr.in/{rr if rr is not None else ''}?0Tq&lang=ru"
)
).text()
),
)

View File

@@ -0,0 +1,167 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
# requires: yt-dlp
import os
from telethon.tl.types import DocumentAttributeAudio
from yt_dlp import YoutubeDL
from yt_dlp.utils import (
ContentTooShortError,
DownloadError,
ExtractorError,
GeoRestrictedError,
MaxDownloadsReached,
PostProcessingError,
UnavailableVideoError,
XAttrMetadataError,
)
from .. import loader, utils # type: ignore
@loader.tds
class YtDlMod(loader.Module):
"""Youtube-Dl Module"""
strings = {
"name": "Youtube-Dl",
"preparing": "<b>[YouTube-Dl]</b> Preparing...",
"downloading": "<b>[YouTube-Dl]</b> Downloading...",
"working": "<b>[YouTube-Dl]</b> Working...",
"exporting": "<b>[YouTube-Dl]</b> Exporting...",
"reply": "<b>[YouTube-Dl]</b> No link!",
"noargs": "<b>[YouTube-Dl]</b> No args!",
"content_too_short": "<b>[YouTube-Dl]</b> Downloading content too short!",
"geoban": "<b>[YouTube-Dl]</b> The video is not available "
"for your geographical location due to geographical "
"restrictions set by the website!",
"maxdlserr": '<b>[YouTube-Dl]</b> The download limit is as follows: " oh ahah"',
"pperr": "<b>[YouTube-Dl]</b> Error in post-processing!",
"noformat": "<b>[YouTube-Dl]</b> Media is not available in "
"the requested format",
"xameerr": "<b>[YouTube-Dl]</b> {0.code}: {0.msg}\n{0.reason}",
"exporterr": "<b>[YouTube-Dl]</b> Error when exporting video",
"err": "<b>[YouTube-Dl]</b> {}",
"err2": "<b>[YouTube-Dl]</b> {}: {}",
}
async def ripvcmd(self, m):
""".ripv <link / reply_to_link> - download video"""
await self.riper(m, "video")
async def ripacmd(self, m):
""".ripa <link / reply_to_link> - download audio"""
await self.riper(m, "audio")
async def riper(self, m, type):
reply = await m.get_reply_message()
args = utils.get_args_raw(m)
url = args or reply.raw_text
if not url:
return await utils.answer(m, self.strings("noargs", m))
m = await utils.answer(m, self.strings("preparing", m))
if type == "audio":
opts = {
"format": "bestaudio",
"addmetadata": True,
"key": "FFmpegMetadata",
"writethumbnail": True,
"prefer_ffmpeg": True,
"geo_bypass": True,
"nocheckcertificate": True,
"postprocessors": [
{
"key": "FFmpegExtractAudio",
"preferredcodec": "mp3",
"preferredquality": "320",
}
],
"outtmpl": "%(id)s.mp3",
"quiet": True,
"logtostderr": False,
}
video = False
song = True
elif type == "video":
opts = {
"format": "best",
"addmetadata": True,
"key": "FFmpegMetadata",
"prefer_ffmpeg": True,
"geo_bypass": True,
"nocheckcertificate": True,
"postprocessors": [
{"key": "FFmpegVideoConvertor", "preferedformat": "mp4"}
],
"outtmpl": "%(id)s.mp4",
"logtostderr": False,
"quiet": True,
}
song = False
video = True
try:
await utils.answer(m, self.strings("downloading", m))
with YoutubeDL(opts) as rip:
rip_data = rip.extract_info(url)
except DownloadError as DE:
return await utils.answer(m, self.strings("err", m).format(str(DE)))
except ContentTooShortError:
return await utils.answer(m, self.strings("content_too_short", m))
except GeoRestrictedError:
return await utils.answer(m, self.strings("geoban", m))
except MaxDownloadsReached:
return await utils.answer(m, self.strings("maxdlserr", m))
except PostProcessingError:
return await utils.answer(m, self.strings("pperr", m))
except UnavailableVideoError:
return await utils.answer(m, self.strings("noformat", m))
except XAttrMetadataError as XAME:
return await utils.answer(m, self.strings("xameerr", m).format(XAME))
except ExtractorError:
return await utils.answer(m, self.strings("exporterr", m))
except Exception as e:
return await utils.answer(
m, self.strings("err2", m).format(str(type(e)), str(e))
)
if song:
u = rip_data["uploader"] if "uploader" in rip_data else "Northing"
await utils.answer(
m,
open(f"{rip_data['id']}.mp3.mp3", "rb"),
supports_streaming=True,
reply_to=reply.id if reply else None,
attributes=[
DocumentAttributeAudio(
duration=int(rip_data["duration"]),
title=str(rip_data["title"]),
performer=u,
)
],
)
os.remove(f"{rip_data['id']}.mp3")
elif video:
await utils.answer(
m,
open(f"{rip_data['id']}.mp4", "rb"),
reply_to=reply.id if reply else None,
supports_streaming=True,
caption=rip_data["title"],
)
os.remove(f"{rip_data['id']}.mp4")

View File

@@ -0,0 +1,36 @@
**Describe the bug**
A clear and concise description of what the bug is.
---
**To Reproduce**
Steps to reproduce the behavior:
1. Run '...'
2. Do '....'
3. See error
---
**Expected behavior**
A clear and concise description of what you expected to happen.
---
**Screenshots**
If applicable, add screenshots to help explain your problem.
---
**Please complete the following information:**
- OS: [e.g. Ubuntu Server 20.04 LTS or Android 12 Termux]
- Userbot: [e.g. GeekTG Userbot `git rev-parse HEAD`]
---
**Additional context**
Add any other context about the problem here.

View File

@@ -0,0 +1,3 @@
black
isort
pyright

View File

@@ -0,0 +1,3 @@
@echo off
black .
isort --profile black --gitignore .

View File

@@ -0,0 +1,4 @@
#!/bin/bash
isort --gitignore --profile black .
black .

View File

@@ -0,0 +1,119 @@
# .------.------.------.------.------.------.------.------.------.------.
# |D.--. |4.--. |N.--. |1.--. |3.--. |L.--. |3.--. |K.--. |0.--. |0.--. |
# | :/\: | :/\: | :(): | :/\: | :(): | :/\: | :(): | :/\: | :/\: | :/\: |
# | (__) | :\/: | ()() | (__) | ()() | (__) | ()() | :\/: | :\/: | :\/: |
# | '--'D| '--'4| '--'N| '--'1| '--'3| '--'L| '--'3| '--'K| '--'0| '--'0|
# `------`------`------`------`------`------`------`------`------`------'
#
# Copyright 2023 t.me/D4n13l3k00
# Licensed under the Creative Commons CC BY-NC-ND 4.0
#
# Full license text can be found at:
# https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode
#
# Human-friendly one:
# https://creativecommons.org/licenses/by-nc-nd/4.0
# meta developer: @D4n13l3k00
import inspect
import logging
from .. import loader, main, utils # type: ignore
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": "Загружено <code>{}</code> модулей:\n\n",
"mod_tmpl": "\n‣<code>{}</code>",
"first_cmd_tmpl": " ➪ [ {}",
"cmd_tmpl": " | {}",
}
@loader.unrestricted
async def helpcmd(self, message):
""".help [module]"""
if args := utils.get_args_raw(message):
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
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(
f" {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(f" {t}" for t in inspect.getdoc(fun).split("\n"))
)
else:
reply += self.strings("undoc_cmd", message)
else:
count = sum(len(i.commands) != 0 for i in self.allmodules.modules)
reply = self.strings("all_header", message).format(count)
for mod in self.allmodules.modules:
if len(mod.commands) != 0:
commands = [
name
for name, func in mod.commands.items()
if await self.allmodules.check_security(message, func)
]
try:
name = mod.strings("name", message)
except KeyError:
name = getattr(mod, "name", "ERROR")
reply += self.strings("mod_tmpl", message).format(name)
first = True
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)
if commands:
reply += " ]"
await utils.answer(message, reply)
async def client_ready(self, client, db):
self.client = client
self.is_bot = await client.is_bot()
self.db = db

View File

@@ -0,0 +1,9 @@
pydub
telethon
aiogram
aiohttp
requests
yt-dlp
numpy
youtube-dl
moviepy