mirror of
https://github.com/MuRuLOSE/limoka.git
synced 2026-06-16 14:34:17 +02:00
Commited backup
This commit is contained in:
62
D4n13l3k00/FTG-Modules/.gitignore
vendored
Normal file
62
D4n13l3k00/FTG-Modules/.gitignore
vendored
Normal 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
|
||||
4
D4n13l3k00/FTG-Modules/.vscode/settings.json
vendored
Normal file
4
D4n13l3k00/FTG-Modules/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"python.pythonPath": "C:\\Users\\D4n13l3k00\\AppData\\Local\\Programs\\Python\\Python39\\python.exe",
|
||||
"python.analysis.typeCheckingMode": "off"
|
||||
}
|
||||
346
D4n13l3k00/FTG-Modules/AudioEditor.py
Normal file
346
D4n13l3k00/FTG-Modules/AudioEditor.py
Normal 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",
|
||||
)
|
||||
],
|
||||
)
|
||||
80
D4n13l3k00/FTG-Modules/Ava.py
Normal file
80
D4n13l3k00/FTG-Modules/Ava.py
Normal 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"))
|
||||
118
D4n13l3k00/FTG-Modules/BackupMan.py
Normal file
118
D4n13l3k00/FTG-Modules/BackupMan.py
Normal 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()
|
||||
151
D4n13l3k00/FTG-Modules/Captcha.py
Normal file
151
D4n13l3k00/FTG-Modules/Captcha.py
Normal 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"))
|
||||
129
D4n13l3k00/FTG-Modules/ChatStata.py
Normal file
129
D4n13l3k00/FTG-Modules/ChatStata.py
Normal 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)
|
||||
)
|
||||
223
D4n13l3k00/FTG-Modules/ChatVoiceMod.py
Normal file
223
D4n13l3k00/FTG-Modules/ChatVoiceMod.py
Normal 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)))
|
||||
85
D4n13l3k00/FTG-Modules/CheckerTG.py
Normal file
85
D4n13l3k00/FTG-Modules/CheckerTG.py
Normal 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"
|
||||
)
|
||||
)
|
||||
106
D4n13l3k00/FTG-Modules/CopyUser.py
Normal file
106
D4n13l3k00/FTG-Modules/CopyUser.py
Normal 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("Аккаунт клонирован!")
|
||||
181
D4n13l3k00/FTG-Modules/Craiyon.py
Normal file
181
D4n13l3k00/FTG-Modules/Craiyon.py
Normal 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))
|
||||
78
D4n13l3k00/FTG-Modules/DeepAI.py
Normal file
78
D4n13l3k00/FTG-Modules/DeepAI.py
Normal 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>"
|
||||
)
|
||||
44
D4n13l3k00/FTG-Modules/DelTimer.py
Normal file
44
D4n13l3k00/FTG-Modules/DelTimer.py
Normal 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
|
||||
63
D4n13l3k00/FTG-Modules/Demotivator.py
Normal file
63
D4n13l3k00/FTG-Modules/Demotivator.py
Normal 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(),
|
||||
)
|
||||
98
D4n13l3k00/FTG-Modules/DumpUsers.py
Normal file
98
D4n13l3k00/FTG-Modules/DumpUsers.py
Normal 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()
|
||||
183
D4n13l3k00/FTG-Modules/FDQuotes.py
Normal file
183
D4n13l3k00/FTG-Modules/FDQuotes.py
Normal 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"]))
|
||||
70
D4n13l3k00/FTG-Modules/FuckChat.py
Normal file
70
D4n13l3k00/FTG-Modules/FuckChat.py
Normal 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)
|
||||
39
D4n13l3k00/FTG-Modules/FullApi.py
Normal file
39
D4n13l3k00/FTG-Modules/FullApi.py
Normal 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>',
|
||||
)
|
||||
282
D4n13l3k00/FTG-Modules/GPT.py
Normal file
282
D4n13l3k00/FTG-Modules/GPT.py
Normal 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()
|
||||
244
D4n13l3k00/FTG-Modules/ImageEditor.py
Normal file
244
D4n13l3k00/FTG-Modules/ImageEditor.py
Normal 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,
|
||||
)
|
||||
157
D4n13l3k00/FTG-Modules/LICENSE.md
Normal file
157
D4n13l3k00/FTG-Modules/LICENSE.md
Normal 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 licensor’s permission is not necessary for any reason–for example, because of any applicable exception or limitation to copyright–then 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).
|
||||
73
D4n13l3k00/FTG-Modules/MYRZ.py
Normal file
73
D4n13l3k00/FTG-Modules/MYRZ.py
Normal 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...")
|
||||
121
D4n13l3k00/FTG-Modules/NekosLife.py
Normal file
121
D4n13l3k00/FTG-Modules/NekosLife.py
Normal 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",
|
||||
]
|
||||
47
D4n13l3k00/FTG-Modules/PHSearch.py
Normal file
47
D4n13l3k00/FTG-Modules/PHSearch.py
Normal 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>',
|
||||
)
|
||||
239
D4n13l3k00/FTG-Modules/QiwiMod.py
Normal file
239
D4n13l3k00/FTG-Modules/QiwiMod.py
Normal 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)
|
||||
11
D4n13l3k00/FTG-Modules/README.md
Normal file
11
D4n13l3k00/FTG-Modules/README.md
Normal 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)
|
||||
73
D4n13l3k00/FTG-Modules/Randomizer.py
Normal file
73
D4n13l3k00/FTG-Modules/Randomizer.py
Normal 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>'
|
||||
)
|
||||
120
D4n13l3k00/FTG-Modules/Reactions.py
Normal file
120
D4n13l3k00/FTG-Modules/Reactions.py
Normal 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 "💩"
|
||||
209
D4n13l3k00/FTG-Modules/RndNsfw.py
Normal file
209
D4n13l3k00/FTG-Modules/RndNsfw.py
Normal 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)
|
||||
72
D4n13l3k00/FTG-Modules/S3.py
Normal file
72
D4n13l3k00/FTG-Modules/S3.py
Normal 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
|
||||
65
D4n13l3k00/FTG-Modules/Saver.py
Normal file
65
D4n13l3k00/FTG-Modules/Saver.py
Normal 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>",
|
||||
)
|
||||
52
D4n13l3k00/FTG-Modules/Searcher.py
Normal file
52
D4n13l3k00/FTG-Modules/Searcher.py
Normal 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()
|
||||
49
D4n13l3k00/FTG-Modules/Sender.py
Normal file
49
D4n13l3k00/FTG-Modules/Sender.py
Normal 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] Сообщение отправлено!")
|
||||
91
D4n13l3k00/FTG-Modules/Shazam.py
Normal file
91
D4n13l3k00/FTG-Modules/Shazam.py
Normal 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
|
||||
40
D4n13l3k00/FTG-Modules/Tesseract.py
Normal file
40
D4n13l3k00/FTG-Modules/Tesseract.py
Normal 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)
|
||||
48
D4n13l3k00/FTG-Modules/Try.py
Normal file
48
D4n13l3k00/FTG-Modules/Try.py
Normal 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>")
|
||||
298
D4n13l3k00/FTG-Modules/VideoEditor.py
Normal file
298
D4n13l3k00/FTG-Modules/VideoEditor.py
Normal 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)
|
||||
71
D4n13l3k00/FTG-Modules/VideoShakal.py
Normal file
71
D4n13l3k00/FTG-Modules/VideoShakal.py
Normal 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)
|
||||
58
D4n13l3k00/FTG-Modules/VoiceRecognize.py
Normal file
58
D4n13l3k00/FTG-Modules/VoiceRecognize.py
Normal 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...")
|
||||
47
D4n13l3k00/FTG-Modules/WttrIn.py
Normal file
47
D4n13l3k00/FTG-Modules/WttrIn.py
Normal 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()
|
||||
),
|
||||
)
|
||||
167
D4n13l3k00/FTG-Modules/YTdl.py
Normal file
167
D4n13l3k00/FTG-Modules/YTdl.py
Normal 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")
|
||||
36
D4n13l3k00/FTG-Modules/bug_report.md
Normal file
36
D4n13l3k00/FTG-Modules/bug_report.md
Normal 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.
|
||||
3
D4n13l3k00/FTG-Modules/dev-requirements.txt
Normal file
3
D4n13l3k00/FTG-Modules/dev-requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
black
|
||||
isort
|
||||
pyright
|
||||
3
D4n13l3k00/FTG-Modules/format.cmd
Normal file
3
D4n13l3k00/FTG-Modules/format.cmd
Normal file
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
black .
|
||||
isort --profile black --gitignore .
|
||||
4
D4n13l3k00/FTG-Modules/format.sh
Normal file
4
D4n13l3k00/FTG-Modules/format.sh
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
isort --gitignore --profile black .
|
||||
black .
|
||||
119
D4n13l3k00/FTG-Modules/help.py
Normal file
119
D4n13l3k00/FTG-Modules/help.py
Normal 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
|
||||
9
D4n13l3k00/FTG-Modules/requirements.txt
Normal file
9
D4n13l3k00/FTG-Modules/requirements.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
pydub
|
||||
telethon
|
||||
aiogram
|
||||
aiohttp
|
||||
requests
|
||||
yt-dlp
|
||||
numpy
|
||||
youtube-dl
|
||||
moviepy
|
||||
Reference in New Issue
Block a user