Commited backup

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

View File

@@ -0,0 +1,57 @@
# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0
# meta pic: https://img.icons8.com/stickers/344/block.png
# meta developer: @mm_mods
__version__ = "1.0.0"
import asyncio
from hikka import loader, utils
import requests
import telethon as tt
from telethon.tl.types import Message
import logging
logger = logging.getLogger(__name__)
@loader.tds
class AbsolutGrossartigAntwortMod(loader.Module):
"""Tired of people asking you questions? Let this module answer them for you!
P.S. Author is not responsible for all your problems after using it."""
strings = {
'name': 'AGA!',
'langneeded': 'en'
}
strings_ru = {
'_cls_doc': 'Достали вопросы? Этот модуль ответит на них за вас!\nP.S. Автор не несет ответственности за все '
'ваши проблемы после использования этого модуля.',
'langneeded': 'ru',
'_cmd_doc_aga': 'Используйте эту команду, чтобы ответить на вопрос.',
}
async def agacmd(self, m: Message):
"""Use this command to answer the question."""
reply = await m.get_reply_message()
if not reply:
result = requests.post('https://somekindofapp-1-j3340894.deta.app/post/aga', json={'basetext': '',
'lang_needed': self.strings('langneeded')})
await utils.answer(m, result.json()['r'])
else:
result = requests.post('https://somekindofapp-1-j3340894.deta.app/post/aga', json={'basetext': reply.text,
'lang_needed': self.strings('langneeded')})
await utils.answer(m, result.json()['r'])
async def watcher(self, m: Message):
if m.text.casefold() == 'ага':
await self.agacmd(m)

View File

@@ -0,0 +1,414 @@
# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0# meta developer: @mm_mods
# meta pic: https://img.icons8.com/fluency/344/color-palette.png
import random
from .. import loader, utils
import io
import logging
import asyncio
import requests
from textwrap import wrap
from PIL import Image, ImageDraw, ImageFont
logger = logging.getLogger(__name__)
__version__ = (1, 1)
class CoVisMod(loader.Module):
"""Visualise colors by those formules."""
strings = {
"name": "CoVis",
"inargs": "😵 <b>Incorrect args format!</b>",
}
strings_ru = {
"name": "CoVis",
"inargs": "😵 <b>Неверный формат аргумента!</b>",
}
strings_de = {
"name": "CoVis",
"inargs": "😵 <b>Falsches Argumenten-Format!</b>",
}
async def _dl_font(self, font_name, short_name, size):
font_name = font_name.replace(" ", "%20")
setattr(
self,
short_name,
ImageFont.truetype(
io.BytesIO(
(
await utils.run_sync(
requests.get,
f"https://github.com/GD-alt/fonts/blob/main/{font_name}.ttf?raw=true",
)
).content
),
size,
),
)
getattr(self, f"{short_name}_ready").set()
async def client_ready(self, client, db):
self.tnrb_ready = asyncio.Event()
asyncio.ensure_future(self._dl_font("Times New Roman Bold", "tnrb", 64))
self.fptb_ready = asyncio.Event()
asyncio.ensure_future(self._dl_font("FuturaPT-Bold", "fptb", 80))
self.cpsb_ready = asyncio.Event()
asyncio.ensure_future(self._dl_font("SourceCodePro-SemiBold", "cpsb", 45))
self.client = client
async def hpiccmd(self, message):
"""Visualise HEX-coded color.
.hpic <HEX-color>"""
text = utils.get_args_raw(message)
r = c.get_reply_message(m)
if not text:
color = '#'
for i in range(6):
color += random.choice(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'])
image = Image.new("RGBA", (512, 512), (0, 0, 0, 0))
draw = ImageDraw.Draw(image)
draw.rounded_rectangle((0, 0, 512, 512), 50, outline="#000000", fill=color, width=8)
output = io.BytesIO()
output.name = f"{color}.webp"
image.save(output, "WEBP")
output.seek(0)
await message.delete()
if message.reply_to:
return await self.client.send_file(message.chat_id, output, reply_to=message.reply_to_msg_id)
else:
return await self.client.send_file(message.chat_id, output)
color = text
if color.startswith("#") and len(color) == 7:
for ch in color.lower()[1:]:
if ch not in "0123456789abcdef":
await utils.answer(message, self.strings("inargs"))
break
else:
color = '#'
for i in range(6):
color += random.choice(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'])
image = Image.new("RGBA", (512, 512), (0, 0, 0, 0))
draw = ImageDraw.Draw(image)
draw.rounded_rectangle((0, 0, 512, 512), 50, outline="#000000", fill=color, width=8)
output = io.BytesIO()
output.name = f"{color}.webp"
image.save(output, "WEBP")
output.seek(0)
await message.delete()
if message.reply_to:
return await self.client.send_file(message.chat_id, output, reply_to=message.reply_to_msg_id)
else:
return await self.client.send_file(message.chat_id, output)
async def rpiccmd(self, message):
"""Visualise RGB-coded color.
.rpic <RGB-color>"""
text = utils.get_args_raw(message)
if not text:
color = f"rgb({random.randint(0, 255)},{random.randint(0, 255)},{random.randint(0, 255)})"
image = Image.new("RGBA", (512, 512), (0, 0, 0, 0))
draw = ImageDraw.Draw(image)
draw.rounded_rectangle((0, 0, 512, 512), 50, outline="#000000", fill=color, width=8)
output = io.BytesIO()
output.name = f"{color}.webp"
image.save(output, "WEBP")
output.seek(0)
await message.delete()
if message.reply_to:
return await self.client.send_file(message.chat_id, output, reply_to=message.reply_to_msg_id)
else:
return await self.client.send_file(message.chat_id, output)
color = text
if color.startswith("(") and color.endswith(")") and color.count(",") == 2:
color = color.replace("(", "")
color = color.replace(")", "")
r, g, b = color.split(", ")
if not r.isnumeric() or not g.isnumeric() or not b.isnumeric():
await utils.answer(message, self.strings("inargs"))
return
color = eval(f"[{int(r)}, {int(g)}, {int(b)}]")
for i in range(3):
if color[i] > 255 or color[i] < 0:
await utils.answer(message, self.strings("inargs"))
break
color = f"rgb({color[0]},{color[1]},{color[2]})"
else:
color = f"rgb({random.randint(0, 255)},{random.randint(0, 255)},{random.randint(0, 255)})"
image = Image.new("RGBA", (512, 512), (0, 0, 0, 0))
draw = ImageDraw.Draw(image)
draw.rounded_rectangle((0, 0, 512, 512), 50, outline="#000000", fill=color, width=8)
output = io.BytesIO()
output.name = f"{color}.webp"
image.save(output, "WEBP")
output.seek(0)
await message.delete()
if message.reply_to:
return await self.client.send_file(message.chat_id, output, reply_to=message.reply_to_msg_id)
else:
return await self.client.send_file(message.chat_id, output)
async def spiccmd(self, message):
"""Visualise HSB-coded color.
.spic <HSB-color>"""
text = utils.get_args_raw(message)
if not text:
color = f"hsv({random.randint(0, 360)},{random.randint(0, 100)}%,{random.randint(0, 100)}%)"
image = Image.new("RGBA", (512, 512), (0, 0, 0, 0))
draw = ImageDraw.Draw(image)
draw.rounded_rectangle((0, 0, 512, 512), 50, outline="#000000", fill=color, width=8)
output = io.BytesIO()
output.name = f"{color}.webp"
image.save(output, "WEBP")
output.seek(0)
await message.delete()
if message.reply_to:
return await self.client.send_file(message.chat_id, output, reply_to=message.reply_to_msg_id)
else:
return await self.client.send_file(message.chat_id, output)
color = text
if color.startswith("(") and color.endswith(")") and color.count(", ") == 2:
color = color.replace("(", "")
color = color.replace(")", "")
h, s, b = color.split(", ")
if not h.isnumeric() or not s.isnumeric() or not b.isnumeric():
await utils.answer(message, self.strings("inargs"))
return
h = int(h)
s = int(s)
b = int(b)
if h < 0 or h > 360:
await utils.answer(message, self.strings("inargs"))
return
if s < 0 or s > 100:
await utils.answer(message, self.strings("inargs"))
return
if b < 0 or b > 100:
await utils.answer(message, self.strings("inargs"))
return
color = f"hsv({h},{s}%,{b}%)"
else:
color = f"hsv({random.randint(0, 360)},{random.randint(0, 100)}%,{random.randint(0, 100)}%)"
image = Image.new("RGBA", (512, 512), (0, 0, 0, 0))
draw = ImageDraw.Draw(image)
draw.rounded_rectangle((0, 0, 512, 512), 50, outline="#000000", fill=color, width=8)
output = io.BytesIO()
output.name = f"{color}.webp"
image.save(output, "WEBP")
output.seek(0)
await message.delete()
if message.reply_to:
return await self.client.send_file(message.chat_id, output, reply_to=message.reply_to_msg_id)
else:
return await self.client.send_file(message.chat_id, output)
async def hdpiccmd(self, message):
"""Visualise HEX-coded color with color code on it.
.hdpic <HEX-color>"""
text = utils.get_args_raw(message)
if not text:
color = '#'
for i in range(6):
color += random.choice(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'])
await self.fptb_ready.wait()
image = Image.new("RGBA", (512, 512), (0, 0, 0, 0))
draw = ImageDraw.Draw(image)
draw.rounded_rectangle(
(0, 0, 512, 512), 50, outline="#000000", fill=color, width=8
)
draw.text(
(256, 256),
text=color,
anchor="mm",
font=self.fptb,
fill="#FFFFFF",
align="center",
stroke_width=8,
stroke_fill="#000000",
)
output = io.BytesIO()
output.name = f"{color}.webp"
image.save(output, "WEBP")
output.seek(0)
await message.delete()
if message.reply_to:
return await self.client.send_file(message.chat_id, output, reply_to=message.reply_to_msg_id)
else:
return await self.client.send_file(message.chat_id, output)
color = text
if color.startswith("#") and len(color) == 7:
for ch in color.lower()[1:]:
if ch not in "0123456789abcdef":
await utils.answer(message, self.strings("inargs"))
break
else:
color = '#'
for i in range(6):
color += random.choice(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'])
txt = ["\n".join(wrap(line, 20)) for line in utils.get_args_raw(message).split("\n")]
text = "\n".join(txt)
await self.fptb_ready.wait()
image = Image.new("RGBA", (512, 512), (0, 0, 0, 0))
draw = ImageDraw.Draw(image)
draw.rounded_rectangle(
(0, 0, 512, 512), 50, outline="#000000", fill=color, width=8
)
draw.text(
(256, 256),
text=text,
anchor="mm",
font=self.fptb,
fill="#FFFFFF",
align="center",
stroke_width=8,
stroke_fill="#000000",
)
output = io.BytesIO()
output.name = f"{color}.webp"
image.save(output, "WEBP")
output.seek(0)
await message.delete()
if message.reply_to:
return await self.client.send_file(message.chat_id, output, reply_to=message.reply_to_msg_id)
else:
return await self.client.send_file(message.chat_id, output)
async def rdpiccmd(self, message):
"""Visualise RGB-coded color with color code on it.
.rdpic (<RGB-color>)"""
text = utils.get_args_raw(message)
if not text:
color = f"rgb({random.randint(0, 255)},{random.randint(0, 255)},{random.randint(0, 255)})"
image = Image.new("RGBA", (512, 512), (0, 0, 0, 0))
await self.tnrb_ready.wait()
draw = ImageDraw.Draw(image)
draw.rounded_rectangle((0, 0, 512, 512), 50, outline="#000000", fill=color, width=8)
draw.text((256, 256), text=color, anchor="mm", font=self.tnrb, fill="#FFFFFF", align="center",
stroke_width=8, stroke_fill="#000000")
output = io.BytesIO()
output.name = f"{color}.webp"
image.save(output, "WEBP")
output.seek(0)
await message.delete()
if message.reply_to:
return await self.client.send_file(message.chat_id, output, reply_to=message.reply_to_msg_id)
else:
return await self.client.send_file(message.chat_id, output)
color = text
if color.startswith("(") and color.endswith(")") and color.count(", ") == 2:
color = color.replace("(", "")
color = color.replace(")", "")
r, g, b = color.split(", ")
if not r.isnumeric() or not g.isnumeric() or not b.isnumeric():
await utils.answer(message, self.strings("inargs"))
return
color = eval(f"[{int(r)}, {int(g)}, {int(b)}]")
for i in range(3):
if color[i] > 255 or color[i] < 0:
await utils.answer(message, self.strings("inargs"))
break
color = f"rgb({color[0]},{color[1]},{color[2]})"
else:
color = f"rgb({random.randint(0, 255)},{random.randint(0, 255)},{random.randint(0, 255)})"
txt = ["\n".join(wrap(line, 20)) for line in utils.get_args_raw(message).split("\n")]
text = "\n".join(txt)
image = Image.new("RGBA", (512, 512), (0, 0, 0, 0))
await self.tnrb_ready.wait()
draw = ImageDraw.Draw(image)
draw.rounded_rectangle((0, 0, 512, 512), 50, outline="#000000", fill=color, width=8)
draw.text((256, 256), text=text, anchor="mm", font=self.tnrb, fill="#FFFFFF", align="center", stroke_width=8, stroke_fill="#000000")
output = io.BytesIO()
output.name = f"{color}.webp"
image.save(output, "WEBP")
output.seek(0)
await message.delete()
if message.reply_to:
return await self.client.send_file(message.chat_id, output, reply_to=message.reply_to_msg_id)
else:
return await self.client.send_file(message.chat_id, output)
async def sdpiccmd(self, message):
"""Visualise HSB-coded color with color code on it.
.sdpic (<HSB-color>)"""
text = utils.get_args_raw(message)
if not text:
color = f"hsv({random.randint(0, 360)},{random.randint(0, 100)}%,{random.randint(0, 100)}%)"
image = Image.new("RGBA", (512, 512), (0, 0, 0, 0))
draw = ImageDraw.Draw(image)
draw.rounded_rectangle((0, 0, 512, 512), 50, outline="#000000", fill=color, width=8)
await self.cpsb_ready.wait()
draw.text((256, 256), text=color, anchor="mm", font=self.cpsb, fill="#FFFFFF", align="center",
stroke_width=8, stroke_fill="#000000")
output = io.BytesIO()
output.name = f"{color}.webp"
image.save(output, "WEBP")
output.seek(0)
await message.delete()
if message.reply_to:
return await self.client.send_file(message.chat_id, output, reply_to=message.reply_to_msg_id)
else:
return await self.client.send_file(message.chat_id, output)
color = text
if color.startswith("(") and color.endswith(")") and color.count(",") == 2:
color = color.replace("(", "")
color = color.replace(")", "")
h, s, b = color.split(", ")
if not h.isnumeric() or not s.isnumeric() or not b.isnumeric():
await utils.answer(message, self.strings("inargs"))
return
h = int(h)
s = int(s)
b = int(b)
if h < 0 or h > 360:
await utils.answer(message, self.strings("inargs"))
return
if s < 0 or s > 100:
await utils.answer(message, self.strings("inargs"))
return
if b < 0 or b > 100:
await utils.answer(message, self.strings("inargs"))
return
color = f"hsv({h},{s}%,{b}%)"
else:
color = f"hsv({random.randint(0, 360)},{random.randint(0, 100)}%,{random.randint(0, 100)}%)"
txt = ["\n".join(wrap(line, 20)) for line in utils.get_args_raw(message).split("\n")]
text = "\n".join(txt)
image = Image.new("RGBA", (512, 512), (0, 0, 0, 0))
draw = ImageDraw.Draw(image)
draw.rounded_rectangle((0, 0, 512, 512), 50, outline="#000000", fill=color, width=8)
await self.cpsb_ready.wait()
draw.text((256, 256), text=text, anchor="mm", font=self.cpsb, fill="#FFFFFF", align="center", stroke_width=8, stroke_fill="#000000")
output = io.BytesIO()
output.name = f"{color}.webp"
image.save(output, "WEBP")
output.seek(0)
await message.delete()
if message.reply_to:
return await self.client.send_file(message.chat_id, output, reply_to=message.reply_to_msg_id)
else:
return await self.client.send_file(message.chat_id, output)

View File

@@ -0,0 +1,65 @@
# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0
# meta developer: @minimaxno
# meta pic: https://img.icons8.com/emoji/344/bullseye.png
import logging
from telethon.tl.types import Message
from .. import loader, utils
def getnum(list: list, needle: str) -> int:
for i in range(0, len(list)):
if list[i] == needle:
return i
@loader.tds
class DicedestroyerMod(loader.Module):
"""Keeps your chat clean from dices, darts and so on."""
strings = {'name': 'Dicedestroyer', 'on': '🤐 <b>Now I will delete dices.</b>', 'off': '🎲 <b>Now I will no more delete dices.</b>', 'rights?': '🤷🏼‍♂️ <b>I need rights to delete messages.</b>'}
strings_ru = {'name': 'Dicedestroyer', 'on': '🤐 <b>Теперь удаляю кубики.</b>', 'off': '🎲 <b>Теперь не удаляю кубики.</b>', 'rights?': '🤷🏼‍♂️ <b>Эх, щас бы права на удаление сообщений…</b>'}
async def client_ready(self, client, db):
self.client = client
self.db = db
if not self.get('würf.sper', False):
self.set('würf.sper', [])
async def deldicecmd(self, m: Message):
"""Set deleting dices in this chat on/off."""
if str(utils.get_chat_id(m)) not in self.get('würf.sper'):
if not m.is_private:
c = await m.get_chat()
if c.admin_rights or c.creator:
if c.admin_rights.delete_messages == False:
return await utils.answer(m, self.strings('rights?'))
else:
return await utils.answer(m, self.strings('rights?'))
wsperr = self.get('würf.sper')
wsperr.append(str(utils.get_chat_id(m)))
self.set('würf.sper', wsperr)
await utils.answer(m, self.strings('on'))
else:
wsperr = self.get('würf.sper')
del wsperr[getnum(wsperr, str(utils.get_chat_id(m)))]
self.set('würf.sper', wsperr)
await utils.answer(m, self.strings('off'))
async def watcher(self, m: Message):
if not hasattr(m, 'out'):
return
if (not m.dice
or m.out
or str(utils.get_chat_id(m)) not in self.get("würf.sper")
):
return
try:
await m.delete()
except:
return

View File

@@ -0,0 +1,463 @@
# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0
# meta developer: @mm_mods
# meta pic: https://img.icons8.com/stickers/256/qr-code.png
from .. import loader, utils
from telethon.tl.patched import Message
import requests
import urllib.parse
import logging
from telethon.tl.types import InputMediaGeoPoint, InputGeoPoint
logger = logging.getLogger(__name__)
async def check_photo(reply_message: Message):
if reply_message and reply_message.media:
if reply_message.photo:
return reply_message.photo
else:
return False
else:
return False
class Parsers:
@staticmethod
def parse_mecard(data: str):
if not data.startswith("MECARD:"):
return False
data = data.replace("MECARD:", "")
data = data.split(";")
result = {}
for item in data:
try:
datatype, value = item.split(":")
except ValueError:
continue
if datatype == "N":
result["name"] = value
elif datatype == "TEL":
result["phone"] = value
elif datatype == "EMAIL":
result["email"] = value
elif datatype == "ADR":
result["address"] = value
elif datatype == "URL":
result["url"] = value
elif datatype == "ORG":
result["organisation"] = value
elif datatype == "NOTE":
result["note"] = value
else:
continue
return result
@staticmethod
def parse_wifi(data: str):
if not data.startswith("WIFI:"):
return False
data = data.replace("WIFI:", "")
data = data.split(";")
result = {}
for item in data:
try:
datatype, value = item.split(":")
except ValueError:
continue
if datatype == "S":
result["ssid"] = value
elif datatype == "P":
result["password"] = value
elif datatype == "T":
result["encryption"] = value
else:
continue
if "ssid" not in result:
return False
if "password" not in result:
result["password"] = "[none]"
if "encryption" not in result:
result["encryption"] = "[none]"
return result
@staticmethod
def parse_geo(data: str):
if not data.startswith("geo:"):
return False
data = data.replace("geo:", "")
lat, lon = data.split(",")
result = {
"lat": lat,
"lon": lon
}
return [result, InputMediaGeoPoint(InputGeoPoint(lat, lon))]
@staticmethod
def parse_sms(data: str):
if not data.startswith("smsto:"):
return False
data = data.replace("smsto:", "")
data = data.split(":")
phone = data[0]
try:
message = data[1]
except IndexError:
message = "[none]"
result = {
"phone": phone,
"message": message
}
return result
@staticmethod
def parse_phone(data: str):
if not data.startswith("tel:"):
return False
data = data.replace("tel:", "")
result = {
"phone": data
}
return result
@staticmethod
def parse_email(data: str):
if (not data.startswith("mailto:")) and (not data.startswith("MATMSG:")):
return False
if_expanded = True if data.startswith("MATMSG:TO:") else False
if if_expanded:
result = {}
data = data.replace("MATMSG:", "")
data = data.split(";")
for item in data:
try:
datatype, value = item.split(":")
except ValueError:
continue
if datatype == "TO":
result["email"] = value
elif datatype == "SUB":
result["subject"] = value
elif datatype == "BODY":
result["body"] = value
else:
continue
if "email" not in result:
return False
if "subject" not in result:
result["subject"] = "[none]"
if "body" not in result:
result["body"] = "[none]"
else:
data = data.replace("mailto:", "")
result = {
"email": data
}
return result
@staticmethod
def parse_vevent(data: str):
if not data.startswith("BEGIN:VEVENT"):
return False
data = data.split("\n")
result = {}
for item in data:
try:
datatype, value = item.split(":")
except ValueError:
continue
if datatype == "SUMMARY":
result["summary"] = value
elif datatype == "LOCATION":
result["location"] = value
elif datatype == "DESCRIPTION":
result["description"] = value
elif datatype == "DTSTART":
result["start"] = f'{value.split("T")[0][:4]}.{value.split("T")[0][4:6]}.{value.split("T")[0][6:8]} ' \
f'{value.split("T")[1][:2]}:{value.split("T")[1][2:4]}:{value.split("1")[0][4:]}' \
if "T" in value else f'{value[:4]}.{value[4:6]}.{value[6:8]}'
elif datatype == "DTEND":
result["end"] = f'{value.split("T")[0][:4]}.{value.split("T")[0][4:6]}.{value.split("T")[0][6:8]} ' \
f'{value.split("T")[1][:2]}:{value.split("T")[1][2:4]}:{value.split("1")[0][4:]}' \
if "T" in value else f'{value[:4]}.{value[4:6]}.{value[6:8]}'
else:
continue
if "summary" not in result:
return False
if "location" not in result:
result["location"] = "[none]"
if "description" not in result:
result["description"] = "[none]"
if "start" not in result:
result["start"] = "[none]"
if "end" not in result:
result["end"] = "[none]"
return result
class EntziffererMod(loader.Module):
"""Decoding QR codes."""
strings = {
"name": "Entzifferer",
"media?": "🖼 <b>Reply to a message, containing code to scan.</b>",
"qr?!": "❌ <b>There's no code to scan.</b>",
"decoding": "🔍 <b>Decoding…</b>",
"uploading": "📤 <b>Uploading your file…</b>",
"processing": "📊 <b>Processing result…</b>",
"error": "❌ <b>Something went wrong.</b>\nError: <code>{}</code>",
"result": "📄 <b>Result:</b>",
"qr": "🔍 <b>QR code:</b>",
"data": "Data: <code>{}</code>",
"contact": "Contact:\n{}",
"phone": "Phone: <code>{}</code>",
"sms": "SMS: <code>{}</code> to <code>{}</code>",
"geolocation": "Geolocation: latitude: <code>{}</code>, longitude: <code>{}</code>",
"email": "Email: <code>{}</code>",
"email_exp": "Email: <code>{}</code> (subject: <code>{}</code>, body: <code>{}</code>)",
"wifi": "Wi-Fi:\nSSID: <code>{}</code> | Password: <code>{}</code> | Encryption: <i>{}</i>",
"url": "URL: {}",
"calendar": "Event: {}",
"MC-name": "👤 Name: <code>{}</code>",
"MC-phone": "☎ Phone: <code>{}</code>",
"MC-email": "📮 Email: <code>{}</code>",
"MC-address": "🏡 Address: <code>{}</code>",
"MC-note": "📝 Note: <code>{}</code>",
"MC-url": "🔗 URL: <code>{}</code>",
"MC-organisation": "💼 Organisation: <code>{}</code>",
"VE-summary": "🎯 Summary: <code>{}</code>",
"VE-location": "🗺 Location: <code>{}</code>",
"VE-description": "📜 Description: <code>{}</code>",
"VE-start": "➡ Start: <code>{}</code>",
"VE-end": "⬅ End: <code>{}</code>"
}
strings_ru = {
"name": "Entzifferer",
"media?": "🖼 <b>Ответьте на сообщение, содержащее код, для сканирования.</b>",
"qr?!": "❌ <b>Нет кода для сканирования.</b>",
"decoding": "🔍 <b>Сканирую…</b>",
"uploading": "📤 <b>Загружаю…</b>",
"processing": "📊 <b>Обрабатываю результат…</b>",
"error": "❌ <b>Что-то пошло не так.</b>\nОшибка: <code>{}</code>",
"result": "📄 <b>Результат:</b>",
"qr": "🔍 <b>QR-код:</b>",
"data": "Данные: <code>{}</code>",
"contact": "Контакт:\n{}",
"phone": "Телефон: <code>{}</code>",
"sms": "SMS: <code>{}</code> на номер <code>{}</code>",
"geolocation": "Геолокация: широта: <code>{}</code>, долгота: <code>{}</code>",
"email": "Почта: <code>{}</code>",
"email_exp": "Почта: <code>{}</code> (тема: <code>{}</code>, текст: <code>{}</code>)",
"wifi": "Wi-Fi:\nSSID: <code>{}</code> | Пароль: <code>{}</code> | Шифрование: <i>{}</i>",
"url": "URL: {}",
"calendar": "Событие: {}",
"MC-name": "👤 Имя: <code>{}</code>",
"MC-phone": "☎ Телефон: <code>{}</code>",
"MC-email": "📮 Почта: <code>{}</code>",
"MC-address": "🏡 Адрес: <code>{}</code>",
"MC-note": "📝 Примечание: <code>{}</code>",
"MC-url": "🔗 URL: <code>{}</code>",
"MC-organisation": "💼 Организация: <code>{}</code>",
"VE-summary": "🎯 Заголовок: <code>{}</code>",
"VE-location": "🗺 Место: <code>{}</code>",
"VE-description": "📜 Описание: <code>{}</code>",
"VE-start": "➡ Начало: <code>{}</code>",
"VE-end": "⬅ Конец: <code>{}</code>",
"_cls_doc": "Декодирует QR-коды.",
"_cmd_doc_scancode": "Сканировать QR-код"
},
strings_de = {
"name": "Entzifferer",
"media?": "🖼 <b>Antworte auf eine Nachricht, die einen Code enthält.</b>",
"qr?!": "❌ <b>Es gibt keinen Code zum Scannen.</b>",
"decoding": "🔍 <b>Scanne…</b>",
"uploading": "📤 <b>Lade deine Datei hoch…</b>",
"processing": "📊 <b>Verarbeite das Ergebnis…</b>",
"error": "❌ <b>Etwas ist schief gelaufen.</b>\nFehler: <code>{}</code>",
"result": "📄 <b>Ergebnis:</b>",
"qr": "🔍 <b>QR-Code:</b>",
"data": "Daten: <code>{}</code>",
"сontact": "Kontakt:\n{}",
"phone": "Telefon: <code>{}</code>",
"sms": "SMS: <code>{}</code> zu <code>{}</code>",
"geolocation": "Geolocation: Breite: <code>{}</code>, Länge: <code>{}</code>",
"email": "E-Mail: <code>{}</code>",
"email_exp": "E-Mail: <code>{}</code> (Betreff: <code>{}</code>, Text: <code>{}</code>)",
"wifi": "WLAN:\nSSID: <code>{}</code> | Passwort: <code>{}</code> | Verschlüsselung: <i>{}</i>",
"url": "URL: {}",
"calendar": "Ereignis: {}",
"MC-name": "👤 Name: <code>{}</code>",
"MC-phone": "☎ Telefon: <code>{}</code>",
"MC-email": "📮 E-mail: <code>{}</code>",
"MC-address": "🏡 Address: <code>{}</code>",
"MC-note": "📝 Notiz: <code>{}</code>",
"MC-url": "🔗 URL: <code>{}</code>",
"MC-organisation": "💼 Arbeitsplatz: <code>{}</code>",
"VE-summary": "🎯 Zusammenfassung: <code>{}</code>",
"VE-location": "🗺 Ort: <code>{}</code>",
"VE-description": "📜 Beschreibung: <code>{}</code>",
"VE-start": "➡ Start: <code>{}</code>",
"VE-end": "⬅ Ende: <code>{}</code>",
"_cls_doc": "Entziffere QR-Codes.",
"_cmd_doc_scancode": "Scanne einen QR-Code"
}
# noinspection PyCallingNonCallable
async def scancodecmd(self, m: Message):
"""Scan a QR code."""
reply = await m.get_reply_message()
if not reply:
return await utils.answer(m, self.strings("media?", m))
if not (await check_photo(reply)):
return await utils.answer(m, self.strings("qr?!", m))
await utils.answer(m, self.strings("uploading", m))
file = await m.client.download_file(reply.photo, bytes)
path = requests.post(
"https://te.legra.ph/upload", files={"file": ("file", file, None)}
).json()
try:
link = "https://te.legra.ph" + path[0]["src"]
except KeyError:
link = path["error"]
await utils.answer(m, self.strings("decoding"))
path = urllib.parse.quote_plus(link)
url = f"https://api.qrserver.com/v1/read-qr-code/?fileurl={path}"
try:
r = requests.get(url).json()
except Exception as e:
logging.error(e)
return await utils.answer(m, self.strings("error").format(f'{e}'))
if r[0]["symbol"][0]["error"]:
return await utils.answer(m, self.strings("qr?!"))
r = r[0]["symbol"][0]["data"]
await utils.answer(m, self.strings("processing"))
res = ''
if len(r.split('\nQR-Code:')) > 1:
r = r.split('\nQR-Code:')
for i in r:
res += f'{self.strings("qr")}\n{self.classify(i)}\n\n'
else:
res = f"{self.strings('qr')}\n{str(self.classify(r))}"
await utils.answer(m, f'<u>{self.strings("result")}</u>\n\n{res}')
# noinspection PyCallingNonCallable
def classify(self, r: str):
if_url = urllib.parse.urlparse(r)
if all([if_url.scheme, if_url.netloc]):
r = self.strings("url").format(r)
elif Parsers.parse_mecard(r):
mecard = Parsers.parse_mecard(r)
r = ''
for key, value in mecard.items():
r = r + self.strings(f"MC-{key}").format(value) + '\n'
r = self.strings("contact").format(r)
elif Parsers.parse_wifi(r):
wifi = Parsers.parse_wifi(r)
r = self.strings("wifi").format(wifi["ssid"], wifi["password"], wifi["encryption"])
elif Parsers.parse_geo(r):
r = Parsers.parse_geo(r)
r = self.strings("geolocation").format(r[0]['lat'], r[0]['lon'])
elif Parsers.parse_sms(r):
r = self.strings("sms").format(Parsers.parse_sms(r)["message"], Parsers.parse_sms(r)["phone"])
elif Parsers.parse_phone(r):
r = Parsers.parse_phone(r)
r = self.strings("phone").format(r["phone"])
elif Parsers.parse_email(r):
if len(list(Parsers.parse_email(r).keys())) > 1:
r = self.strings("email_exp").format(
Parsers.parse_email(r)["email"],
Parsers.parse_email(r)["subject"],
Parsers.parse_email(r)["body"]
)
else:
r = self.strings("email").format(Parsers.parse_email(r)["email"])
elif Parsers.parse_vevent(r):
vevent = Parsers.parse_vevent(r)
r = ''
for key, value in vevent.items():
r = r + self.strings(f"VE-{key}").format(value) + '\n'
r = self.strings("calendar").format(r)
else:
r = self.strings("data").format(r)
return r

View File

@@ -0,0 +1,90 @@
# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0
# meta developer: @mm_mods
# meta pic: https://img.icons8.com/emoji/256/musical-notes-emoji.png
import logging
from telethon.tl.types import Message, DocumentAttributeAudio
from .. import loader, utils, translations
import requests
logger = logging.getLogger(__name__)
@loader.tds
class GLyricsMod(loader.Module):
"""Get lyrics from Genius"""
strings = {
"name": "GLyrics",
"lyrics": "📝 <b>Lyrics</b> for <b>{}</b>:\n\n{}",
"no_lyrics": "😔 <b>No lyrics</b> for <b>{}</b> or something else happened.",
"args?": "😶 <b>What song do you want lyrics for?</b>",
"wait": "🧐 <b>Searching for lyrics...</b>",
"full_text": "👀 View full lyrics",
}
strings_ru = {
"name": "GLyrics",
"lyrics": "📝 <b>Текст песни</b> <b>{}</b>:\n\n{}",
"no_lyrics": "😔 <b>Текста песни</b> для <b>{}</b> нет или что-то пошло не так.",
"args?": "😶 <b>Какую песню вы хотите найти?</b>",
"wait": "🧐 <b>Ищу текст песни...</b>",
"full_text": "👀 Посмотреть полный текст",
"_cls_doc": "Ищет тексты песен в Genius",
"_cmd_doc_lyrics": "Найти текст песни"
}
strings_de = {
"name": "GLyrics",
"lyrics": "📝 <b>Lyrics</b> für <b>{}</b>:\n\n{}",
"no_lyrics": "😔 <b>Kein Lyrics</b> für <b>{}</b> oder etwas anderes ist passiert.",
"args?": "😶 <b>Welchen Song willst du Lyrics für haben?</b>",
"wait": "🧐 <b>Suche nach Lyrics...</b>",
"full_text": "👀 Vollständigen Text anzeigen",
"_cls_doc": "Sucht nach Lyrics auf Genius",
"_cmd_doc_lyrics": "Suche nach Lyrics"
}
async def lyricscmd(self, m: Message):
"""Search for lyrics"""
r = await m.get_reply_message()
if not utils.get_args_raw(m) and not r:
return await utils.answer(m, self.strings("args?"))
if r and not utils.get_args_raw(m):
if not r.media:
return await utils.answer(m, self.strings("args?"))
attr = r.media.document.attributes[0]
if not isinstance(attr, DocumentAttributeAudio):
return await utils.answer(m, self.strings("args?"))
song = f'{attr.performer} - {attr.title}'
else:
song = utils.get_args_raw(m)
await utils.answer(m, self.strings("wait"))
try:
data = {'name': song}
r = requests.post(f"https://somekindofapp-1-j3340894.deta.app/mirror/genius/lyrics", json=data)
r = r.json()
lyrics = r["res"]["lyrics"]
title = r["res"]["name"]
full_link = r["res"]["url"]
await self.inline.form(
self.strings("lyrics").format(title, lyrics),
reply_markup=[[{"text": self.strings["full_text"], "url": full_link}]],
message=m,
force_me=False
)
except Exception as e:
logger.error(e)
await utils.answer(m, self.strings("no_lyrics").format(song))

View File

@@ -0,0 +1,614 @@
# ---------------------------------------------------------------------------------
# /\_/\ 🌐 This module was loaded through https://t.me/hikkamods_bot
# ( o.o ) 🔓 Not licensed.
# > ^ < ⚠️ Owner of heta.hikariatama.ru doesn't take any responsibilities or intellectual property rights regarding this script
# ---------------------------------------------------------------------------------
# Name: GoogleTrans
# Author: GD-alt
# Commands:
# .autotranslate | .onboardh | .dllap | .dellap | .deflang
# .searchlang | .silentmode | .subsmode | .markmode | .atlist
# .translate
# ---------------------------------------------------------------------------------
# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0
# meta developer: @mm_mods
# meta pic: https://img.icons8.com/color/344/input-latin-letters-emoji.png
# requires: deep-translator
import contextlib
import logging
from deep_translator import GoogleTranslator
from telethon.tl.types import Message
from copy import deepcopy
from .. import loader, translations, utils
translator = GoogleTranslator()
available_languages = translator.get_supported_languages(as_dict=True)
logger = logging.getLogger(__name__)
def get_key(dictionary: dict, needle: str) -> str:
return next((key for key, value in dictionary.items() if value == needle), None)
def get_num(lst: list, needle: str) -> int:
for i in range(len(lst)):
if lst[i] == needle:
return i
@loader.tds
class GoogleTranslateMod(loader.Module):
"""Guaranteed to be the most advanced and feature-rich message translation module based on Google Translate,
with many useful features."""
strings = {
"name": "GoogleTrans",
"load": "🔄 <b>Translating…</b>",
"load2": "🔎 <b>Searching… Please, wait.</b>",
"se-re": "📘 <b>Search result:</b>\n",
"cll": "🔄 <b>Configuring language list…</b>",
"args": "🚫 <b>No arguments, no reply…</b>",
"args2": "🚫 <b>No arguments…</b>",
"no_lang": "📕 <b>No such language!</b>",
"setted": "🔤 <b>Your main language is updated!</b>",
"silent": "🔇 <b>OK, I won't dispay translation message!</b>",
"unsilent": "🔊 <b>OK, I will dispay translation message!</b>",
"mark": "🔇 <b>OK, I won't dispay «translated» mark!</b>",
"unmark": "🔊 <b>OK, I will dispay «translated» mark!</b>",
"tr-ed": "<b>Translated:</b>",
"added": " <b>Chat added to autotranslate list!</b>",
"changed": "〰️ <b>Autotranslate configuration changed!</b>",
"deled": " <b>Chat deleted from autotranslate list!</b>",
"alheader": "📃 <b>Chats, in which autotranslate is activated:</b>",
"subscribe": "🖋️ <b>Now I'll keep original text while autotranslating.</b>",
"unsubscribe": (
"🖋️ <b>Now I won't keep original text while autotranslating.</b>"
),
"onboard-h": (
" <b>Some useful info about syntax</b>\n\n• .deflang {two-digit lang"
" code} sets your language to defined.\n• .markmode, .subsmode,"
" .silentmode, .atlist takes no arguments.\n• .autotranslate {start;finish}"
" takes argument only in such format. You may skip start language to define"
" it automatically. Also you may skip finish language to define it from"
" your default language.\n• .translate ({start;finish}) [text/reply] have"
" same rules while defining languages, as previous command. You may skip"
" block in brackets to translate text from autodefined language to your"
" default language.\n• .searchlang {two-digit language code/russion or"
" english language name} returns following language.\n\n In manual [s-t]"
" being used for unnecessary text block. {s-t} — for necessary."
),
"tt": "en",
"lapi": (
"📥 <b>Language names packet for <code>{}</code> succesfully installed!</b>"
),
"lapd": (
"📤 <b>Language names packet for <code>{}</code> succesfully deleted!</b>"
),
}
strings_de = {
"name": "GoogleTrans",
"load": "🔄 <b>Übersetze…</b>",
"load2": "🔎 <b>Suchen… Bitte warten.</b>",
"se-re": "📘 <b>Gefunden:</b>\n",
"cll": "🔄 <b>Sprachlist konfiguriere…</b>",
"args": "🚫 <b>Kein Antwort, kein Argument…</b>",
"args2": "🚫 <b>Kein Argument…</b>",
"no_lang": "📕 <b>Ich kenne dieser Sprache nicht!</b>",
"setted": "🔤 <b>Deine Muttersprache aktualisiert!</b>",
"silent": "🔇 <b>Jetzt zeige ich Übersetzungnachricht nicht!</b>",
"unsilent": "🔊 <b>Jetzt zeige ich Übersetzungnachricht!</b>",
"mark": "🔇 <b>Jetzt ich zeige »Übersetzt« Merkzeichen nicht!</b>",
"unmark": "🔊 <b>Jetzt ich zeige »Übersetzt« Merkzeichen!</b>",
"tr-ed": "<b>Übersetzt:</b>",
"added": " <b>Chat zum Autoübersetzunglist hinzufügt!</b>",
"changed": "〰️ <b>Autoübersetzung Konfiguration geändert!</b>",
"deled": " <b>Chat aus Autoübersetzunglist entfernt!</b>",
"alheader": "📃 <b>Autoübersetzungchatlist:</b>",
"subscribe": "🖋️ <b>Jetzt zeige ich Originaltext bei Autoübersetzung.</b>",
"unsubscribe": (
"🖋️ <b>Jetzt zeige ich Originaltext bei Autoübersetzung nicht.</b>"
),
"onboard-h": (
" <b>Syntax-Leitfaden</b>\n\n• .deflang {zweistellig Sprachcode} ersetze"
" dein Muttersprache mit eingegebt.\n• .markmode, .subsmode, .silentmode,"
" .atlist kein Argumente benötigt.\n• .autotranslate {Ausgang;Ziel}"
" benötigen Argumente in diesem Format. Wenn Ausgangsprache nicht eigegebt,"
" er wird automatisch erkannt jedes Mal. Wenn Zielsprache nicht eingegebt,"
" es word von deiner Muttersprache definiert.\n• .translate"
" [({Ausgang;Ziel})] {текст/ответ} haben desselben Sprachdefinierung"
" Regeln. Du kannst Blok im Klammern nicht eingegeben um von autoerkennt"
" Sprache auf deiner Muttersprache zu Übersetzen.\n• .searchlang"
" {zweistellig Sprachcode/Sprachname an Englisch, Russisch oder anders"
" installierte Sprache gebe dir Sprachname/Sprachcode.\n\nIn Leitfaden"
" [etwas] ist unbenötigt Textblok. {etwas} — benötigt."
),
"tt": "de",
"_cls_doc": (
"Garantiert das fortschrittlichste und funktionsreichste"
" Nachrichtenübersetzungsmodul auf Basis von Google Translate mit vielen"
" nützlichen Funktionen."
),
"lapi": (
"📥 <b>Sprachesuchpaket für <code>{}</code> Sprache erfolgreich"
" installiert!</b>"
),
"lapd": (
"📤 <b>Sprachesuchpaket für <code>{}</code> Sprache erfolgreich"
" deinstalliert!</b>"
),
"_cmd_doc_onboardh": "Syntaxanleitung.",
"_cmd_doc_dllap": (
"Ermöglicht die Suche in der eingegebenen Sprache, nachdem die Liste"
" erstellt wurde."
),
"_cmd_doc_dellap": "Entfernt das Sprachesuchpaket",
"_cmd_doc_autotranslate": (
"Aktiviert die Autoübersetzung in diesem Chat. Lesen Sie die Hilfe von"
" hier."
),
"_cmd_doc_atlist": (
"Liste der automatisch übersetzten Chats und der dort verwendeten Sprachen"
),
"_cmd_doc_deflang": "Legt die Muttersprache fest.",
"_cmd_doc_searchlang": (
"Sucht die Sprache nach dem Namen in einer der eingestellten Sprachen —"
" standardmäßig Englisch und Russisch — oder Sprachcode."
),
"_cmd_doc_markmode": "Aktiviert/deaktiviert die Markierung »Übersetzt«",
"_cmd_doc_subsmode": (
"Aktiviert/deaktiviert die Textspeicherung bei der automatischen"
" Übersetzung"
),
"_cmd_doc_silentmode": (
"Aktiviert/deaktiviert die Anzeige der Fangmeldung beim Übersetzen."
),
"_cmd_doc_translate": (
"Wie unerwartet, übersetzt. Verwenden Sie (start;final), um die zu"
" Übersetzung Sprachen festzulegen. Verwenden Sie die Hilfe für weitere"
" Informationen."
),
}
strings_ru = {
"name": "GoogleTrans",
"load": "🔄 <b>Перевожу…</b>",
"load2": "🔎 <b>Ищу… Ожидайте.</b>",
"se-re": "📘 <b>Найдено:</b>\n",
"cll": "🔄 <b>Конфигурирую список языков…</b>",
"args": "🚫 <b>Ни аргумента, ни ответа…</b>",
"args2": "🚫 <b>Нет аргумента…</b>",
"no_lang": "📕 <b>Я не знаю такого языка!</b>",
"setted": "🔤 <b>Ваш основной язык обновлён!</b>",
"silent": "🔇 <b>Хорошо, теперь не отображаю сообщение о переводе!</b>",
"unsilent": "🔊 <b>Хорошо, теперь отображаю сообщение о переводе!</b>",
"mark": "🔇 <b>Хорошо, теперь не отображаю пометку «переведено»!</b>",
"unmark": "🔊 <b>Хорошо, теперь отображаю пометку «переведено»!</b>",
"tr-ed": "<b>Переведено:</b>",
"added": " <b>Чат добавлен в список автоперевода!</b>",
"changed": "〰️ <b>Конфигурация автоперевода изменена!</b>",
"deled": " <b>Чат убран из списка автоперевода!</b>",
"alheader": "📃 <b>Список чатов, в которых активен автоперевод:</b>",
"subscribe": "🖋️ <b>Теперь я сохраняю оригинальный текст при автопереводе.</b>",
"unsubscribe": (
"🖋️ <b>Теперь я не сохраняю оригинальный текст при автопереводе.</b>"
),
"onboard-h": (
" <b>Руководство по синтаксису</b>\n\n• .deflang {двузначный языковой"
" код} установит ваш язык по умолчанию на введённый.\n• .markmode,"
" .subsmode, .silentmode, .atlist не принимают аргументов.\n"
" .autotranslate {старт;финал} принимает аргументы только в таком формате."
" При пропуске начального языка, он будет определяться автоматически каждый"
" раз. Финальный язык при пропуске его будет взят из языка по умолчанию.\n"
" .translate [({старт;финал})] {текст/ответ} имеет те же правила по"
" обозначению языков, что и прошлая команда. Можно пропустить блок в"
" круглых скобках чтобы перевести с автопереведённого языка на язык по"
" умолчанию.\n• .searchlang {двузначный языковой код/название языка на"
" русском или английском} выдаёт язык, соотвтетствующий названию или"
" коду.\n\nВ руководстве [что-то] обозначает необязательный текстовый блок."
" {что-то} — обязательный."
),
"tt": "ру",
"lapi": "📥 <b>Языковой пакет для языка <code>{}</code> успешно установлен!</b>",
"lapd": "📤 <b>Языковой пакет для языка <code>{}</code> успешно удалён!</b>",
"_cmd_doc_onboardh": "Справка по синтаксису.",
"_cmd_doc_dllap": (
"Даёт возможность после построения списка искать на введённом языке."
),
"_cmd_doc_dellap": "Удаляет языковой пакет для поиска.",
"_cmd_doc_autotranslate": (
"Включает автоперевод в данном чате. Дальше — читай справку."
),
"_cmd_doc_atlist": "Список чатов с автопереводом и языков, там используемых.",
"_cmd_doc_deflang": "Устанавливает язык по умолчанию.",
"_cmd_doc_searchlang": (
"Ищет язык по названию на одном из установленных языков — по умолчанию "
"английский и русский."
),
"_cmd_doc_markmode": "Включает/выключает пометку «Переведено».",
"_cmd_doc_subsmode": "Включает/выключает сохранение текста при автопереводе.",
"_cmd_doc_silentmode": (
"Включает/выключает показ сообщения загрузки при переводе."
),
"_cmd_doc_translate": (
"Как неожиданно — переводит. Используй (start;final) чтоб установить языки"
" для перевода. Для дальнейшей информации используй справку."
),
"_cls_doc": (
"Гарантированно самый продвинутый и многофункциональный модуль для перевода"
" сообщений, основанный на Google Translate, с множеством полезных функций."
),
}
async def client_ready(self, client, db):
self._client = client
self._db = db
if not self.get("deflang", False):
self.set("deflang", "en")
if not self.get("silence", False):
self.set("silence", False)
if not self.get("mark", False):
self.set("mark", True)
if not self.get("s-script", False):
self.set("s-script", False)
if not self.get("tr_cha", False):
self.set("tr_cha", {})
if not self.get("addla", False):
self.set("addla", [])
async def autotranslatecmd(self, message: Message):
"""Use language code with this command to add this chat to autotranslate list."""
lang = utils.get_args_raw(message)
if (str(utils.get_chat_id(message)) in self.get("tr_cha")) and not lang:
tr_cha = self.get("tr_cha")
del tr_cha[str(utils.get_chat_id(message))]
self.set("tr_cha", tr_cha)
await utils.answer(message, self.strings("deled"))
return
if ";" not in lang:
stla = "auto"
fila = self.get("deflang")
else:
stla, fila = lang.split(";", 1)
stla, fila = stla.strip(), fila.strip()
if not stla:
stla = "auto"
if not fila:
fila = self.get("deflang")
if fila not in available_languages.values():
await utils.answer(message, self.strings("no_lang"))
return
if (stla != "auto") and (stla not in available_languages.values()):
await utils.answer(message, self.strings("no_lang"))
return
lang = f"{stla};{fila}"
tr_cha = self.get("tr_cha")
tco = deepcopy(tr_cha)
tr_cha.update({str(utils.get_chat_id(message)): lang})
self.set("tr_cha", tr_cha)
if str(utils.get_chat_id(message)) not in tco.keys():
await utils.answer(message, self.strings("added"))
else:
await utils.answer(message, self.strings("changed"))
async def onboardhcmd(self, m: Message):
"""Syntax manual."""
await utils.answer(m, self.strings("onboard-h"))
async def dllapcmd(self, m: Message):
"""Downloads languages name pack for entered language. Allows to search languages through .searchlang on your own language."""
lang = utils.get_args_raw(m)
if lang == "":
return await utils.answer(m, self.strings("args2"))
if lang not in available_languages.values():
await utils.answer(m, self.strings("nolang"))
if not self.get(f"{lang}langdb", False):
await utils.answer(m, self.strings("cll"))
rld = {}
langword = GoogleTranslator("en", lang).translate("a language").casefold()
if " " in langword:
langword = GoogleTranslator("en", lang).translate("language").casefold()
for z in available_languages:
ru_n = f"{z} language"
ru_n = (
GoogleTranslator("en", lang)
.translate(ru_n)
.casefold()
.replace(langword, "")
)
if ru_n[-1] == " ":
ru_n = ru_n[:-1]
if ru_n[-1] == "-":
ru_n = ru_n[:-1]
if ru_n[0] == " ":
ru_n = ru_n.replace(" ", "", 1)
if ru_n[0] == "-":
ru_n = ru_n.replace("-", "", 1)
if (lang == "de") and (ru_n[-1] == "e"):
ru_n = ru_n[:-1]
rld[ru_n.casefold()] = available_languages[z]
self.set(f"{lang}langdb", rld)
addla = self.get("addla")
addla.append(lang)
addla = self.set("addla", addla)
return await utils.answer(m, self.strings("lapi").format(lang))
async def dellapcmd(self, m: Message):
"""Deletes custom language pack."""
lang = utils.get_args_raw(m)
if lang == "":
return await utils.answer(m, self.strings("args2"))
if lang not in self.get("addla"):
await utils.answer(m, self.strings("no_lang"))
try:
del self._db[self.__class__.__name__][f"{lang}langdb"]
except Exception as e:
return await utils.answer(m, self.strings("no_lang"))
addla = self.get("addla")
del addla[get_num(addla, lang)]
addla = self.set("addla", addla)
return await utils.answer(m, self.strings("lapd").format(lang))
async def deflangcmd(self, message: Message):
"""Use language code with this command to switch basic translation language."""
lang = utils.get_args_raw(message)
if lang not in available_languages.values():
await utils.answer(message, self.strings("nolang"))
else:
self.set("deflang", lang)
await utils.answer(message, self.strings("setted"))
async def searchlangcmd(self, m: Message):
"""Searching language by code or name (RU and EN names avaliable — if you downloaded others, you may use them; first usage takes some time to configure database)."""
query = utils.get_args_raw(m)
if query == "":
return await utils.answer(m, self.strings("args2"))
if not self.get("rulangdb", False):
await utils.answer(m, self.strings("cll"))
rld = {}
for z in available_languages:
ru_n = f"{z} language"
ru_n = (
GoogleTranslator("en", "ru")
.translate(ru_n)
.replace("язык", "")
.replace(" ", "")
)
rld[ru_n] = available_languages[z]
self.set("rulangdb", rld)
rld = self.get("rulangdb")
for x in range(len(self.get("addla"))):
try:
res = self.get(f'{self.get("addla")[x]}langdb')[query]
return await utils.answer(
m,
(
f'{self.strings("se-re")}<code>{query}</code> ->'
f" <code>{res}</code>"
),
)
except Exception:
continue
try:
res = available_languages[query]
except Exception:
try:
res = rld[query]
except Exception:
if self.strings("tt") == "ру":
res = get_key(rld, query)
elif self.strings("tt") == "de":
if not self.get("delangdb", False):
try:
res = (
get_key(available_languages, query)
+ ' (du kannst Deutsche Namen durch ".dllap de"'
" installieren)"
)
except:
return await utils.answer(m, self.strings("no_lang"))
else:
try:
res = get_key(self.get("delangdb"), query)
except:
return await utils.answer(m, self.strings("no_lang"))
else:
res = get_key(available_languages, query)
if res is None:
return await utils.answer(m, self.strings("no_lang"))
return await utils.answer(
m, f'{self.strings("se-re")}<code>{query}</code> -> <code>{res}</code>'
)
async def silentmodecmd(self, message):
"""Use this command to switch between silent/unsilent mode."""
if self.get("silence"):
self.set("silence", False)
await utils.answer(message, self.strings("unsilent"))
else:
self.set("silence", True)
await utils.answer(message, self.strings("silent"))
async def subsmodecmd(self, message):
"""Use this command to switch autotranslate subscription mode."""
if self.get("s-script"):
self.set("s-script", False)
await utils.answer(message, self.strings("unsubscribe"))
else:
self.set("s-script", True)
await utils.answer(message, self.strings("subscribe"))
async def markmodecmd(self, message):
"""Use this command to switch between showing/unshowing «translated» mark."""
if self.get("mark"):
self.set("mark", False)
await utils.answer(message, self.strings("mark"))
else:
self.set("mark", True)
await utils.answer(message, self.strings("unmark"))
async def atlistcmd(self, message: Message):
"""Sends a list of chats, in which autotranslate is turned on."""
laco = self.strings("tt")
autotranslate = self.get("tr_cha")
alist = self.strings("alheader") + "\n"
avlad = GoogleTranslator().get_supported_languages(as_dict=True)
for i in autotranslate.keys():
st_la, fi_la = autotranslate[i].split(";")
if st_la == "auto":
if laco == "ru":
st_la = "авто"
elif laco == "ru":
st_la = f"{get_key(avlad, st_la)} language"
st_la = (
GoogleTranslator("en", "ru").translate(st_la).replace("язык", "")
)
elif (laco == "de") and (self.get("delangdb")):
st_la = get_key(self.get("delangdb"), st_la)
else:
st_la = get_key(avlad, st_la)
if laco == "ru":
fi_la = f"{get_key(avlad, fi_la)} language"
fi_la = (
GoogleTranslator("en", "ru").translate(fi_la).replace("язык", "")
)
elif (laco == "de") and (self.get("delangdb")):
fi_la = get_key(self.get("delangdb"), fi_la)
else:
fi_la = get_key(avlad, fi_la)
type_ = (
"user"
if getattr(await self._client.get_entity(int(i)), "first_name", False)
else "chat"
)
alist += (
f'<a href="tg://openmessage?{type_}_id={i.replace("-100", "")}">id{i.replace("-100", "")}</a>:'
f" {st_la} » {fi_la}"
+ "\n"
)
if (laco == "de") and (not self.get("delangdb", False)):
alist += (
"\nDu kannst Deutsche Namen durch <code>.dllap de</code> installieren."
)
await utils.answer(message, alist)
async def translatecmd(self, message: Message):
"""In fact, it translates. Use (start;final) to mark the start and end language of the translation.
Leave the start language blank to define it automatically."""
reply = await message.get_reply_message()
prompt = ' '.join(utils.get_args(message))
if not prompt and reply is None:
await utils.answer(message, self.strings("args"))
if prompt and prompt.startswith("("):
lafo, prompt = prompt.split(")", 1)
if ";" not in lafo:
prompt = f"({lafo}){prompt}"
stal = "auto"
finl = self.get("deflang")
else:
lafo = lafo.replace("(", "", 1)
stal, finl = lafo.split(";", 1)
stal, finl = stal.strip(), finl.strip()
if not stal:
stal = "auto"
if not finl:
finl = self.get("deflang")
if (
(stal or finl) not in available_languages.values()
and (stal != "auto")
and (finl not in available_languages.values())
):
await utils.answer(
message,
self.strings("no_lang") + "\n" + stal + " " + finl,
)
return
else:
stal = "auto"
finl = self.get("deflang")
if not self.get("silence"):
await utils.answer(message, self.strings("load"))
if not prompt:
if reply is None:
await utils.answer(message, self.strings("args"))
return
else:
prompt = reply.text
translator = GoogleTranslator(stal, finl)
translated = translator.translate(prompt)
if self.get("mark"):
translated = f'{self.strings("tr-ed")}\n{translated}'
await utils.answer(message, translated)
async def watcher(self, message: Message):
pr = self.get_prefix()
if not message.text:
return
if not message.out:
return
if message.text[0] in ["/", pr]:
return
if str(utils.get_chat_id(message)) not in self.get("tr_cha").keys():
return
stla, fila = self.get("tr_cha")[str(utils.get_chat_id(message))].split(";")
tren = GoogleTranslator(stla, fila)
translated = "".join(
[
await utils.run_sync(lambda: tren.translate(chunk))
for chunk in utils.chunks(message.text, 512)
]
)
if translated == message.text:
return
if self.get("s-script"):
translated = (
message.text + "\n\n" + self.strings("tr-ed") + "\n\n" + translated
)
with contextlib.suppress(Exception):
await utils.answer(message, translated)

View File

@@ -0,0 +1,618 @@
# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0
# meta developer: @mm_mods
# meta pic: https://img.icons8.com/color/344/input-latin-letters-emoji.png
import contextlib
import logging
import requests
from telethon.tl.types import Message
from copy import deepcopy
from .. import loader, translations, utils
class GoogleTranslator:
def __init__(self, start_lang: str = "auto", dest_lang: str = "en"):
self.start_lang = start_lang
self.dest_lang = dest_lang
def get_supported_languages(self, as_dict: bool = False) -> list | dict:
"""Returns a list of supported languages or a dictionary of supported languages with their codes."""
as_dict = 'true' if as_dict else 'false'
return requests.get(f'https://trmr-1-f8335856.deta.app/supported?asd={as_dict}').json()['res']
def translate(self, text: str) -> str:
"""Translates the text into the specified language."""
return requests.post('https://trmr-1-f8335856.deta.app/translate/', json={'from_lang': self.start_lang,
'to_lang': self.dest_lang,
'text': text}).json()['result']
translator = GoogleTranslator()
available_languages = translator.get_supported_languages(as_dict=True)
logger = logging.getLogger(__name__)
def get_key(dictionary: dict, needle: str) -> str:
return next((key for key, value in dictionary.items() if value == needle), None)
def get_num(lst: list, needle: str) -> int:
for i in range(len(lst)):
if lst[i] == needle:
return i
@loader.tds
class GoogleTranslateMod(loader.Module):
"""Guaranteed to be the most advanced and feature-rich message translation module based on Google Translate,
with many useful features."""
strings = {
"name": "GoogleTrans",
"load": "🔄 <b>Translating…</b>",
"load2": "🔎 <b>Searching… Please, wait.</b>",
"se-re": "📘 <b>Search result:</b>\n",
"cll": "🔄 <b>Configuring language list…</b>",
"args": "🚫 <b>No arguments, no reply…</b>",
"args2": "🚫 <b>No arguments…</b>",
"no_lang": "📕 <b>No such language!</b>",
"setted": "🔤 <b>Your main language is updated!</b>",
"silent": "🔇 <b>OK, I won't dispay translation message!</b>",
"unsilent": "🔊 <b>OK, I will dispay translation message!</b>",
"mark": "🔇 <b>OK, I won't dispay «translated» mark!</b>",
"unmark": "🔊 <b>OK, I will dispay «translated» mark!</b>",
"tr-ed": "<b>Translated:</b>",
"added": " <b>Chat added to autotranslate list!</b>",
"changed": "〰️ <b>Autotranslate configuration changed!</b>",
"deled": " <b>Chat deleted from autotranslate list!</b>",
"alheader": "📃 <b>Chats, in which autotranslate is activated:</b>",
"subscribe": "🖋️ <b>Now I'll keep original text while autotranslating.</b>",
"unsubscribe": (
"🖋️ <b>Now I won't keep original text while autotranslating.</b>"
),
"onboard-h": (
" <b>Some useful info about syntax</b>\n\n• .deflang {two-digit lang"
" code} sets your language to defined.\n• .markmode, .subsmode,"
" .silentmode, .atlist takes no arguments.\n• .autotranslate {start;finish}"
" takes argument only in such format. You may skip start language to define"
" it automatically. Also you may skip finish language to define it from"
" your default language.\n• .translate ({start;finish}) [text/reply] have"
" same rules while defining languages, as previous command. You may skip"
" block in brackets to translate text from autodefined language to your"
" default language.\n• .searchlang {two-digit language code/russion or"
" english language name} returns following language.\n\n In manual [s-t]"
" being used for unnecessary text block. {s-t} — for necessary."
),
"tt": "en",
"lapi": (
"📥 <b>Language names packet for <code>{}</code> succesfully installed!</b>"
),
"lapd": (
"📤 <b>Language names packet for <code>{}</code> succesfully deleted!</b>"
),
}
strings_de = {
"name": "GoogleTrans",
"load": "🔄 <b>Übersetze…</b>",
"load2": "🔎 <b>Suchen… Bitte warten.</b>",
"se-re": "📘 <b>Gefunden:</b>\n",
"cll": "🔄 <b>Sprachlist konfiguriere…</b>",
"args": "🚫 <b>Kein Antwort, kein Argument…</b>",
"args2": "🚫 <b>Kein Argument…</b>",
"no_lang": "📕 <b>Ich kenne dieser Sprache nicht!</b>",
"setted": "🔤 <b>Deine Muttersprache aktualisiert!</b>",
"silent": "🔇 <b>Jetzt zeige ich Übersetzungnachricht nicht!</b>",
"unsilent": "🔊 <b>Jetzt zeige ich Übersetzungnachricht!</b>",
"mark": "🔇 <b>Jetzt ich zeige »Übersetzt« Merkzeichen nicht!</b>",
"unmark": "🔊 <b>Jetzt ich zeige »Übersetzt« Merkzeichen!</b>",
"tr-ed": "<b>Übersetzt:</b>",
"added": " <b>Chat zum Autoübersetzunglist hinzufügt!</b>",
"changed": "〰️ <b>Autoübersetzung Konfiguration geändert!</b>",
"deled": " <b>Chat aus Autoübersetzunglist entfernt!</b>",
"alheader": "📃 <b>Autoübersetzungchatlist:</b>",
"subscribe": "🖋️ <b>Jetzt zeige ich Originaltext bei Autoübersetzung.</b>",
"unsubscribe": (
"🖋️ <b>Jetzt zeige ich Originaltext bei Autoübersetzung nicht.</b>"
),
"onboard-h": (
" <b>Syntax-Leitfaden</b>\n\n• .deflang {zweistellig Sprachcode} ersetze"
" dein Muttersprache mit eingegebt.\n• .markmode, .subsmode, .silentmode,"
" .atlist kein Argumente benötigt.\n• .autotranslate {Ausgang;Ziel}"
" benötigen Argumente in diesem Format. Wenn Ausgangsprache nicht eigegebt,"
" er wird automatisch erkannt jedes Mal. Wenn Zielsprache nicht eingegebt,"
" es word von deiner Muttersprache definiert.\n• .translate"
" [({Ausgang;Ziel})] {текст/ответ} haben desselben Sprachdefinierung"
" Regeln. Du kannst Blok im Klammern nicht eingegeben um von autoerkennt"
" Sprache auf deiner Muttersprache zu Übersetzen.\n• .searchlang"
" {zweistellig Sprachcode/Sprachname an Englisch, Russisch oder anders"
" installierte Sprache gebe dir Sprachname/Sprachcode.\n\nIn Leitfaden"
" [etwas] ist unbenötigt Textblok. {etwas} — benötigt."
),
"tt": "de",
"_cls_doc": (
"Garantiert das fortschrittlichste und funktionsreichste"
" Nachrichtenübersetzungsmodul auf Basis von Google Translate mit vielen"
" nützlichen Funktionen."
),
"lapi": (
"📥 <b>Sprachesuchpaket für <code>{}</code> Sprache erfolgreich"
" installiert!</b>"
),
"lapd": (
"📤 <b>Sprachesuchpaket für <code>{}</code> Sprache erfolgreich"
" deinstalliert!</b>"
),
"_cmd_doc_onboardh": "Syntaxanleitung.",
"_cmd_doc_dllap": (
"Ermöglicht die Suche in der eingegebenen Sprache, nachdem die Liste"
" erstellt wurde."
),
"_cmd_doc_dellap": "Entfernt das Sprachesuchpaket",
"_cmd_doc_autotranslate": (
"Aktiviert die Autoübersetzung in diesem Chat. Lesen Sie die Hilfe von"
" hier."
),
"_cmd_doc_atlist": (
"Liste der automatisch übersetzten Chats und der dort verwendeten Sprachen"
),
"_cmd_doc_deflang": "Legt die Muttersprache fest.",
"_cmd_doc_searchlang": (
"Sucht die Sprache nach dem Namen in einer der eingestellten Sprachen —"
" standardmäßig Englisch und Russisch — oder Sprachcode."
),
"_cmd_doc_markmode": "Aktiviert/deaktiviert die Markierung »Übersetzt«",
"_cmd_doc_subsmode": (
"Aktiviert/deaktiviert die Textspeicherung bei der automatischen"
" Übersetzung"
),
"_cmd_doc_silentmode": (
"Aktiviert/deaktiviert die Anzeige der Fangmeldung beim Übersetzen."
),
"_cmd_doc_translate": (
"Wie unerwartet, übersetzt. Verwenden Sie (start;final), um die zu"
" Übersetzung Sprachen festzulegen. Verwenden Sie die Hilfe für weitere"
" Informationen."
),
}
strings_ru = {
"name": "GoogleTrans",
"load": "🔄 <b>Перевожу…</b>",
"load2": "🔎 <b>Ищу… Ожидайте.</b>",
"se-re": "📘 <b>Найдено:</b>\n",
"cll": "🔄 <b>Конфигурирую список языков…</b>",
"args": "🚫 <b>Ни аргумента, ни ответа…</b>",
"args2": "🚫 <b>Нет аргумента…</b>",
"no_lang": "📕 <b>Я не знаю такого языка!</b>",
"setted": "🔤 <b>Ваш основной язык обновлён!</b>",
"silent": "🔇 <b>Хорошо, теперь не отображаю сообщение о переводе!</b>",
"unsilent": "🔊 <b>Хорошо, теперь отображаю сообщение о переводе!</b>",
"mark": "🔇 <b>Хорошо, теперь не отображаю пометку «переведено»!</b>",
"unmark": "🔊 <b>Хорошо, теперь отображаю пометку «переведено»!</b>",
"tr-ed": "<b>Переведено:</b>",
"added": " <b>Чат добавлен в список автоперевода!</b>",
"changed": "〰️ <b>Конфигурация автоперевода изменена!</b>",
"deled": " <b>Чат убран из списка автоперевода!</b>",
"alheader": "📃 <b>Список чатов, в которых активен автоперевод:</b>",
"subscribe": "🖋️ <b>Теперь я сохраняю оригинальный текст при автопереводе.</b>",
"unsubscribe": (
"🖋️ <b>Теперь я не сохраняю оригинальный текст при автопереводе.</b>"
),
"onboard-h": (
" <b>Руководство по синтаксису</b>\n\n• .deflang {двузначный языковой"
" код} установит ваш язык по умолчанию на введённый.\n• .markmode,"
" .subsmode, .silentmode, .atlist не принимают аргументов.\n"
" .autotranslate {старт;финал} принимает аргументы только в таком формате."
" При пропуске начального языка, он будет определяться автоматически каждый"
" раз. Финальный язык при пропуске его будет взят из языка по умолчанию.\n"
" .translate [({старт;финал})] {текст/ответ} имеет те же правила по"
" обозначению языков, что и прошлая команда. Можно пропустить блок в"
" круглых скобках чтобы перевести с автопереведённого языка на язык по"
" умолчанию.\n• .searchlang {двузначный языковой код/название языка на"
" русском или английском} выдаёт язык, соотвтетствующий названию или"
" коду.\n\nВ руководстве [что-то] обозначает необязательный текстовый блок."
" {что-то} — обязательный."
),
"tt": "ру",
"lapi": "📥 <b>Языковой пакет для языка <code>{}</code> успешно установлен!</b>",
"lapd": "📤 <b>Языковой пакет для языка <code>{}</code> успешно удалён!</b>",
"_cmd_doc_onboardh": "Справка по синтаксису.",
"_cmd_doc_dllap": (
"Даёт возможность после построения списка искать на введённом языке."
),
"_cmd_doc_dellap": "Удаляет языковой пакет для поиска.",
"_cmd_doc_autotranslate": (
"Включает автоперевод в данном чате. Дальше — читай справку."
),
"_cmd_doc_atlist": "Список чатов с автопереводом и языков, там используемых.",
"_cmd_doc_deflang": "Устанавливает язык по умолчанию.",
"_cmd_doc_searchlang": (
"Ищет язык по названию на одном из установленных языков — по умолчанию "
"английский и русский."
),
"_cmd_doc_markmode": "Включает/выключает пометку «Переведено».",
"_cmd_doc_subsmode": "Включает/выключает сохранение текста при автопереводе.",
"_cmd_doc_silentmode": (
"Включает/выключает показ сообщения загрузки при переводе."
),
"_cmd_doc_translate": (
"Как неожиданно — переводит. Используй (start;final) чтоб установить языки"
" для перевода. Для дальнейшей информации используй справку."
),
"_cls_doc": (
"Гарантированно самый продвинутый и многофункциональный модуль для перевода"
" сообщений, основанный на Google Translate, с множеством полезных функций."
),
}
async def client_ready(self, client, db):
self._client = client
self._db = db
if not self.get("deflang", False):
self.set("deflang", "en")
if not self.get("silence", False):
self.set("silence", False)
if not self.get("mark", False):
self.set("mark", True)
if not self.get("s-script", False):
self.set("s-script", False)
if not self.get("tr_cha", False):
self.set("tr_cha", {})
if not self.get("addla", False):
self.set("addla", [])
async def autotranslatecmd(self, message: Message):
"""Use language code with this command to add this chat to autotranslate list."""
lang = utils.get_args_raw(message)
if (str(utils.get_chat_id(message)) in self.get("tr_cha")) and not lang:
tr_cha = self.get("tr_cha")
del tr_cha[str(utils.get_chat_id(message))]
self.set("tr_cha", tr_cha)
await utils.answer(message, self.strings("deled"))
return
if ";" not in lang:
stla = "auto"
fila = self.get("deflang")
else:
stla, fila = lang.split(";", 1)
stla, fila = stla.strip(), fila.strip()
if not stla:
stla = "auto"
if not fila:
fila = self.get("deflang")
if fila not in available_languages.values():
await utils.answer(message, self.strings("no_lang"))
return
if (stla != "auto") and (stla not in available_languages.values()):
await utils.answer(message, self.strings("no_lang"))
return
lang = f"{stla};{fila}"
tr_cha = self.get("tr_cha")
tco = deepcopy(tr_cha)
tr_cha.update({str(utils.get_chat_id(message)): lang})
self.set("tr_cha", tr_cha)
if str(utils.get_chat_id(message)) not in tco.keys():
await utils.answer(message, self.strings("added"))
else:
await utils.answer(message, self.strings("changed"))
async def onboardhcmd(self, m: Message):
"""Syntax manual."""
await utils.answer(m, self.strings("onboard-h"))
async def dllapcmd(self, m: Message):
"""Downloads languages name pack for entered language. Allows to search languages through .searchlang on your own language."""
lang = utils.get_args_raw(m)
if lang == "":
return await utils.answer(m, self.strings("args2"))
if lang not in available_languages.values():
await utils.answer(m, self.strings("nolang"))
if not self.get(f"{lang}langdb", False):
await utils.answer(m, self.strings("cll"))
rld = {}
langword = GoogleTranslator("en", lang).translate("a language").casefold()
if " " in langword:
langword = GoogleTranslator("en", lang).translate("language").casefold()
for z in available_languages:
ru_n = f"{z} language"
ru_n = (
GoogleTranslator("en", lang)
.translate(ru_n)
.casefold()
.replace(langword, "")
)
if ru_n[-1] == " ":
ru_n = ru_n[:-1]
if ru_n[-1] == "-":
ru_n = ru_n[:-1]
if ru_n[0] == " ":
ru_n = ru_n.replace(" ", "", 1)
if ru_n[0] == "-":
ru_n = ru_n.replace("-", "", 1)
if (lang == "de") and (ru_n[-1] == "e"):
ru_n = ru_n[:-1]
rld[ru_n.casefold()] = available_languages[z]
self.set(f"{lang}langdb", rld)
addla = self.get("addla")
addla.append(lang)
addla = self.set("addla", addla)
return await utils.answer(m, self.strings("lapi").format(lang))
async def dellapcmd(self, m: Message):
"""Deletes custom language pack."""
lang = utils.get_args_raw(m)
if lang == "":
return await utils.answer(m, self.strings("args2"))
if lang not in self.get("addla"):
await utils.answer(m, self.strings("no_lang"))
try:
del self._db[self.__class__.__name__][f"{lang}langdb"]
except Exception as e:
return await utils.answer(m, self.strings("no_lang"))
addla = self.get("addla")
del addla[get_num(addla, lang)]
addla = self.set("addla", addla)
return await utils.answer(m, self.strings("lapd").format(lang))
async def deflangcmd(self, message: Message):
"""Use language code with this command to switch basic translation language."""
lang = utils.get_args_raw(message)
if lang not in available_languages.values():
await utils.answer(message, self.strings("nolang"))
else:
self.set("deflang", lang)
await utils.answer(message, self.strings("setted"))
async def searchlangcmd(self, m: Message):
"""Searching language by code or name (RU and EN names avaliable — if you downloaded others, you may use them; first usage takes some time to configure database)."""
query = utils.get_args_raw(m)
if query == "":
return await utils.answer(m, self.strings("args2"))
if not self.get("rulangdb", False):
await utils.answer(m, self.strings("cll"))
rld = {}
for z in available_languages:
ru_n = f"{z} language"
ru_n = (
GoogleTranslator("en", "ru")
.translate(ru_n)
.replace("язык", "")
.replace(" ", "")
)
rld[ru_n] = available_languages[z]
self.set("rulangdb", rld)
rld = self.get("rulangdb")
for x in range(len(self.get("addla"))):
try:
res = self.get(f'{self.get("addla")[x]}langdb')[query]
return await utils.answer(
m,
(
f'{self.strings("se-re")}<code>{query}</code> ->'
f" <code>{res}</code>"
),
)
except Exception:
continue
try:
res = available_languages[query]
except Exception:
try:
res = rld[query]
except Exception:
if self.strings("tt") == "ру":
res = get_key(rld, query)
elif self.strings("tt") == "de":
if not self.get("delangdb", False):
try:
res = (
get_key(available_languages, query)
+ ' (du kannst Deutsche Namen durch ".dllap de"'
" installieren)"
)
except:
return await utils.answer(m, self.strings("no_lang"))
else:
try:
res = get_key(self.get("delangdb"), query)
except:
return await utils.answer(m, self.strings("no_lang"))
else:
res = get_key(available_languages, query)
if res is None:
return await utils.answer(m, self.strings("no_lang"))
return await utils.answer(
m, f'{self.strings("se-re")}<code>{query}</code> -> <code>{res}</code>'
)
async def silentmodecmd(self, message):
"""Use this command to switch between silent/unsilent mode."""
if self.get("silence"):
self.set("silence", False)
await utils.answer(message, self.strings("unsilent"))
else:
self.set("silence", True)
await utils.answer(message, self.strings("silent"))
async def subsmodecmd(self, message):
"""Use this command to switch autotranslate subscription mode."""
if self.get("s-script"):
self.set("s-script", False)
await utils.answer(message, self.strings("unsubscribe"))
else:
self.set("s-script", True)
await utils.answer(message, self.strings("subscribe"))
async def markmodecmd(self, message):
"""Use this command to switch between showing/unshowing «translated» mark."""
if self.get("mark"):
self.set("mark", False)
await utils.answer(message, self.strings("mark"))
else:
self.set("mark", True)
await utils.answer(message, self.strings("unmark"))
async def atlistcmd(self, message: Message):
"""Sends a list of chats, in which autotranslate is turned on."""
laco = self.strings("tt")
autotranslate = self.get("tr_cha")
alist = self.strings("alheader") + "\n"
avlad = GoogleTranslator().get_supported_languages(as_dict=True)
for i in autotranslate.keys():
st_la, fi_la = autotranslate[i].split(";")
if st_la == "auto":
if laco == "ru":
st_la = "авто"
elif laco == "ru":
st_la = f"{get_key(avlad, st_la)} language"
st_la = (
GoogleTranslator("en", "ru").translate(st_la).replace("язык", "")
)
elif (laco == "de") and (self.get("delangdb")):
st_la = get_key(self.get("delangdb"), st_la)
else:
st_la = get_key(avlad, st_la)
if laco == "ru":
fi_la = f"{get_key(avlad, fi_la)} language"
fi_la = (
GoogleTranslator("en", "ru").translate(fi_la).replace("язык", "")
)
elif (laco == "de") and (self.get("delangdb")):
fi_la = get_key(self.get("delangdb"), fi_la)
else:
fi_la = get_key(avlad, fi_la)
type_ = (
"user"
if getattr(await self._client.get_entity(int(i)), "first_name", False)
else "chat"
)
alist += (
f'<a href="tg://openmessage?{type_}_id={i.replace("-100", "")}">id{i.replace("-100", "")}</a>:'
f" {st_la} » {fi_la}"
+ "\n"
)
if (laco == "de") and (not self.get("delangdb", False)):
alist += (
"\nDu kannst Deutsche Namen durch <code>.dllap de</code> installieren."
)
await utils.answer(message, alist)
async def translatecmd(self, message: Message):
"""In fact, it translates. Use (start;final) to mark the start and end language of the translation.
Leave the start language blank to define it automatically."""
reply = await message.get_reply_message()
prompt = ' '.join(utils.get_args(message))
if not prompt and reply is None:
await utils.answer(message, self.strings("args"))
if prompt and prompt.startswith("("):
lafo, prompt = prompt.split(")", 1)
if ";" not in lafo:
prompt = f"({lafo}){prompt}"
stal = "auto"
finl = self.get("deflang")
else:
lafo = lafo.replace("(", "", 1)
stal, finl = lafo.split(";", 1)
stal, finl = stal.strip(), finl.strip()
if not stal:
stal = "auto"
if not finl:
finl = self.get("deflang")
if (
(stal or finl) not in available_languages.values()
and (stal != "auto")
and (finl not in available_languages.values())
):
await utils.answer(
message,
self.strings("no_lang") + "\n" + stal + " " + finl,
)
return
else:
stal = "auto"
finl = self.get("deflang")
if not self.get("silence"):
await utils.answer(message, self.strings("load"))
if not prompt:
if reply is None:
await utils.answer(message, self.strings("args"))
return
else:
prompt = reply.text
translator = GoogleTranslator(stal, finl)
translated = translator.translate(prompt)
if self.get("mark"):
translated = f'{self.strings("tr-ed")}\n{translated}'
await utils.answer(message, translated)
async def watcher(self, message: Message):
pr = self.get_prefix()
if not message.text:
return
if not message.out:
return
if message.text[0] in ["/", pr]:
return
if str(utils.get_chat_id(message)) not in self.get("tr_cha").keys():
return
stla, fila = self.get("tr_cha")[str(utils.get_chat_id(message))].split(";")
tren = GoogleTranslator(stla, fila)
translated = "".join(
[
await utils.run_sync(lambda: tren.translate(chunk))
for chunk in utils.chunks(message.text, 512)
]
)
if translated == message.text:
return
if self.get("s-script"):
translated = (
message.text + "\n\n" + self.strings("tr-ed") + "\n\n" + translated
)
with contextlib.suppress(Exception):
await utils.answer(message, translated)

View File

@@ -0,0 +1,58 @@
# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0
# meta developer: @mm_mods, original by Fl1yd
# meta pic: https://img.icons8.com/emoji/344/grapes-emoji.png
from .. import loader, utils
from random import choice
from time import sleep
from telethon import types
from telethon.tl.types import Message
class GrapesMod(loader.Module):
"""Searching for random pic for your query. Original version/idea: Fl1yd."""
strings = {"name": "Grapes", 'lade': '🔎 <b>Searching…</b>', 'p-auf': '👾 <b>O0pS, pr0b1em…</b>', 'n-gef': '<b>Ha, stop, not found… :(</b>', 'gef': '<b>Looks like something is found!..</b>', 'q': 'Query:', 'args?': '📝 <b>Where is arguments, sir?</b>'}
strings_ru = {"name": "Grapes", 'lade': '🔎 <b>Ищу…</b>', 'p-auf': '👾 <b>0й, пр06лемkа…</b>', 'n-gef': '<b>А, нет, не нашлось… :(</b>', 'gef': '<b>Кажется, нашлось!..</b>', 'q': 'Запрос:', 'args?': '📝 <b>И где аргументы, сударь?</b>'}
async def piccmd(self, message: Message):
"""Searching for pics in Yandex."""
try:
args = utils.get_args_raw(message)
if not args:
await utils.answer(message, self.strings('args?'))
return
await utils.answer(message, self.strings('lade'))
reslt = await message.client.inline_query("pic", args)
await utils.answer(message, f'{self.strings("gef")}\n{self.strings("q")} {args}')
sleep(1.5)
await message.delete()
await reslt[reslt.index(choice(reslt))].click(utils.get_chat_id(m))
except:
await message.respond(self.strings('n-gef'))
return
async def dpiccmd(self, message: Message):
"""Searching for pics in DuckDuckGo."""
try:
args = utils.get_args_raw(message)
if not args:
await utils.answer(message, self.strings('args?'))
return
await utils.answer(message, self.strings('lade'))
reslt = await message.client.inline_query("duckpicsbot", args)
await utils.answer(message, f'{self.strings("gef")}\n{self.strings("q")} {args}')
sleep(1.5)
await message.delete()
await reslt[reslt.index(choice(reslt))].click(utils.get_chat_id(m))
except:
await message.respond(self.strings('n-gef'))
return

View File

@@ -0,0 +1,77 @@
# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0
# meta pic: https://img.icons8.com/stickers/344/calendar.png
# meta developer: @mm_mods
__version__ = "1.0.0"
import re
from .. import loader, utils
import bs4
import deep_translator
import requests
from telethon.tl.types import Message
import logging
logger = logging.getLogger(__name__)
@loader.tds
class HolidaysMod(loader.Module):
"""Holidays today."""
strings = {
'name': 'Holidays',
'base': '<b>Holidays today:</b>',
'lang': 'en',
}
strings_ru = {
'name': 'Holidays',
'base': '<b>Праздники сегодня:</b>',
'_cls_doc': 'Показывает праздники сегодня',
'_cmd_doc_hollist': 'Показывает список праздников',
'lang': 'ru',
}
strings_de = {
'name': 'Holidays',
'base': '<b>Feste heute:</b>',
'_cls_doc': 'Zeigt Feste heute',
'_cmd_doc_hollist': 'Zeigt eine Liste von Feste',
'lang': 'de',
}
strings_uk = {
'name': 'Holidays',
'base': '<b>Святкові дні сьогодні:</b>',
'_cls_doc': 'Показує святкові дні сьогодні',
'_cmd_doc_hollist': 'Показує список святкових днів',
'lang': 'uk',
}
strings_uz = {
'name': 'Holidays',
'base': '<b>Bugun kunlar:</b>',
'_cls_doc': 'Bugun kunlarini ko\'rsatadi',
'_cmd_doc_hollist': 'Bugun kunlar ro\'yxatini ko\'rsatadi',
'lang': 'uz',
}
async def hollistcmd(self, m: Message):
"""Shows holiday list."""
hollist = requests.get('https://somekindofapp-1-j3340894.deta.app/mirror/holidays/').json()['res']
res = deep_translator.GoogleTranslator(source='auto', target=self.strings['lang']).translate_batch(hollist) if self.strings['lang'] != 'ru' else hollist
text = f'{self.strings("base")}\n\n'
for i in res:
text += f'{i}\n'
await utils.answer(m, text)

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,791 @@
# meta developer: @mm_mods
# requires: toml
import os
from hikka import loader, utils
import pickle
from telethon.tl.types import Channel
import toml
# noinspection PyCallingNonCallable
@loader.tds
class RPMod(loader.Module):
"""A little upgraded mod of module of @trololo_1."""
def __init__(self):
self.config = loader.ModuleConfig(
loader.ConfigValue(
"action_decoration",
'normal | без стилей',
lambda: self.strings("cfg_action_decoration"),
validator=loader.validators.Choice(
[
"normal | без стилей",
"bold | полужирный",
"italic | курсив",
"underlined | подчёркнутый",
"strikethrough | зачёркнутый",
"spoiler | скрытый",
]
),
),
loader.ConfigValue(
"replica_decoration",
'normal | без стилей',
lambda: self.strings("cfg_replica_decoration"),
validator=loader.validators.Choice(
[
"normal | без стилей",
"bold | полужирный",
"italic | курсив",
"underlined | подчёркнутый",
"strikethrough | зачёркнутый",
"spoiler | скрытый",
]
),
),
loader.ConfigValue(
"speech_bubble",
'💬',
lambda: self.strings("cfg_speech_bubble"),
validator=loader.validators.String()
)
)
strings = {
'name': 'LiMERPMod',
'separator…': '🤐 <b>Here\'s an emoji separator, but no emoji. eh</b>',
'name?': '🧐 <b>Where\'s the name of the RP command?</b>',
'action?': '🧐 <b>Where\'s the action of the RP command?</b>',
'aarf': '🤢 <b>RP commands can\'t be named "all"</b>',
'space': '🤐 <b>RP commands consisting of multiple words aren\'t supported.</b>',
'added1': "🤩 <b>Command '<code>{}</code>' succesfully added with emoji '{}'!</b>",
'added2': "☺️ <b>Command '<code>{}</code>' succesfully added!</b>",
'weresall': '🤐 <b>You\'ve not entered separator or have\'nt entered anything at all.</b>',
'cleared': '🍃 <b>RP commands succesfully cleared!</b>',
'arg?': '🧐 <b>Where\'s the argument?</b>',
'deleted': '🗑️ <b>RP command <code>{}</code> succesfully deleted!</b>',
'notfound': '🧐 <b>Command <code>{}</code> not found!</b>',
'on': '😀 <b>RP commands are now on!</b>',
'off': '😴 <b>RP commands are now off!</b>',
's-t-wrong': '😟 <b>Something went wrong!</b>',
'nick-changed': '🏷️ <b>RP nickname of {} succesfully changed to <code>{}</code>!</b>',
'count': '📋 <b>You have <code>{}</code> commands</b>',
'error-with-type': '❌ <b>Error: <code>{}</code></b>',
'actualised': '👍🏻 <b>RP commands succesfully actualised!</b>',
'chat-excluded': ' <b>Chat {} succesfully excluded!</b>',
'chat-included': ' <b>Chat {} succesfully included!</b>',
'id-wrong': '🔢 <b>Wrong ID!</b>',
'empty-exclude': '🪁 <b>Excluded chats list is empty!</b>',
'excluded-chats': '📃 <b>Excluded chats:</b>',
'on-in-chat': '📗💬 <b>RP commands are now on for members of this chat!</b>',
'off-in-chat': '📕💬 <b>RP commands are now off for members of this chat!</b>',
'who-have': '📄 <b>Who have RP commands access:</b>',
'chats-s': '💬 <b>Chats:</b>',
'users-s': '👤 <b>Users:</b>',
'on-for-usr': '📗 <b>RP commands are now on for <code>{}</code>!</b>',
'off-for-usr': '📕 <b>RP commands are now off for <code>{}</code>!</b>',
'whatschanged': '''🍋 <b>LIME</b> (1.2) — mod of RPMod (@trololo_1) by @mm_mods
What\'s changed?
• No limits now!
• No check for emoji validity now — add custom emojies…
• No buggy import now, everyone can use the module.
• Additions and replicas now save there\'s case.
• New commands backup format.
• Config optoins moved to config.
Enjoy!''',
'with-replica': 'Saying:',
'arg-unknown': '🤌🏻 <b>Unknown argument!</b>',
'num-unknown': 'Ⓜ️ <b>Unknown number!</b>',
'done': '✅ <b>Done!</b>',
'less-then-2': '▫️ <b>Less then 2 arguments!</b>',
'toml-minparse-failure': '😦 <b>Failed to parse toml!</b>\nAre you sure it\'s a backup?',
'toml-parse-failure': '💀 <b>Failed to parse toml!</b>\nThe backup is corrupted.',
'cfg_action_decoration': 'Decoration for RP action',
'cfg_replica_decoration': 'Decoration for RP replica',
'cfg_speech_bubble': 'Speech bubble emoji for «with replica»',
}
strings_ru = {
'name': 'LiMERPMod',
'separator…': '🤐 <b>Вот разделитель, но нет эмодзи. епт</b>',
'name?': '🧐 <b>Где имя РП-команды?</b>',
'action?': '🧐 <b>Где действие РП-команды?</b>',
'aarf': '🤢 <b>РП-команды не могут называться "all"</b>',
'space': '🤐 <b>Многословные команды не поддерживаются.</b>',
'added1': "🤩 <b>Команда '<code>{}</code>' успешно добавлена с эмодзи '{}'!</b>",
'added2': "☺️ <b>Команда '<code>{}</code>' успешно добавлена!</b>",
'weresall': '🤐 <b>Вы не ввели разделитель или ничего не ввели вообще.</b>',
'cleared': '🍃 <b>РП-команды успешно очищены!</b>',
'arg?': '🧐 <b>Где аргумент?</b>',
'deleted': '🗑️ <b>РП-команда <code>{}</code> успешно удалена!</b>',
'notfound': '🧐 <b>Команда <code>{}</code> не найдена!</b>',
'on': '😀 <b>РП-команды теперь включены!</b>',
'off': '😴 <b>РП-команды теперь выключены!</b>',
's-t-wrong': '😟 <b>Что-то пошло не так!</b>',
'nick-changed': '🏷️ <b>Ник {} успешно изменен на <code>{}</code>!</b>',
'count': '📋 <b>У вас <code>{}</code> команд</b>',
'error-with-type': '❌ <b>Ошибка: <code>{}</code></b>',
'actualised': '👍🏻 <b>РП-команды успешно обновлены!</b>',
'chat-excluded': ' <b>Чат {} успешно исключен!</b>',
'chat-included': ' <b>Чат {} успешно включен!</b>',
'id-wrong': '🔢 <b>Неверный ID!</b>',
'empty-exclude': '🪁 <b>Список исключённых чатов пуст!</b>',
'excluded-chats': '📃 <b>Исключённые чаты:</b>',
'on-in-chat': '📗💬 <b>РП-команды теперь включены для участников этого чата!</b>',
'off-in-chat': '📕💬 <b>РП-команды теперь выключены для участников этого чата!</b>',
'who-have': '📄 <b>Кто имеет доступ к РП-командам:</b>',
'chats-s': '💬 <b>Чаты:</b>',
'users-s': '👤 <b>Пользователи:</b>',
'on-for-usr': '📗 <b>РП-команды теперь включены для <code>{}</code>!</b>',
'off-for-usr': '📕 <b>РП-команды теперь выключены для <code>{}</code>!</b>',
'whatschanged': '''🍋 <b>LIME</b> (1.2) — модуль RPMod (@trololo_1) от @mm_mods
Что изменилось?
• Больше нет ограничений!
• Больше нет проверки на валидность эмодзи — добавляйте кастомные эмодзи…
• Больше нет багов с импортом — теперь модуль может использовать каждый.
• Дополнения и реплики теперь сохраняют свой регистр.
• Новый формат сохранения команд.
• Опции конфига переехали в конфиг.
Наслаждайтесь!''',
'with-replica': 'С репликой:',
'arg-unknown': '🤌🏻 <b>Неизвестный аргумент!</b>',
'num-unknown': 'Ⓜ️ <b>Неизвестная цифра!</b>',
'done': '✅ <b>Готово!</b>',
'less-then-2': '▫️ <b>Меньше 2 аргументов!</b>',
'toml-minparse-failure': '😦 <b>Ошибка парсинга toml!</b>\nЭто точно бэкап?',
'toml-parse-failure': '💀 <b>Ошибка парсинга toml!</b>\nБэкап повреждён.',
'cfg_action_decoration': 'Декорация для действия РП-команды',
'cfg_replica_decoration': 'Декорация для реплики РП-команды',
'cfg_speech_bubble': 'Эмодзи речевого пузыря для «с репликой»',
'_cls_doc': 'Слегка улучшенный мод на модуль от @trololo_1.',
'_cmd_doc_dobrp': 'Создать РП-команду. Аргументы: <команда>/<действие>[/<эмодзи>]',
'_cmd_doc_addrp': 'Псевдоним для .dobrp.',
'_cmd_doc_delrp': 'Удалить РП-команду. Аргументы: <команда>',
'_cmd_doc_rplist': 'Показать список РП-команд.',
'_cmd_doc_rpconf': 'Настроить шаблон для РП-команд. Аргументы: <параметр> <значение>',
'_cmd_doc_orpback': 'Сохранить/загрузить РП-команды (старый метод). Используйте без аргументов, чтобы '
'сохранить, или в ответ на файл, чтобы загрузить.',
'_cmd_doc_rpback': 'Новый метод, чтобы сохранить/загрузить РП-команды. Используйте без аргументов, чтобы '
'сохранить, или в ответ на файл, чтобы загрузить.',
'_cmd_doc_rpnick': 'Изменить ник для РП-команд. Аргументы: <ник> или без ника, чтобы его сбросить. '
'В ответ на сообщение нужного пользователя.',
'_cmd_doc_rpnicks': 'Используйте .rpnicks, чтобы просмотреть список ников для РП-команд.',
'_cmd_doc_rpblock': 'Заблокировать/разблокировать РП-команды в чате. Аргументы: <айди чата>. '
'Можно и без него, чтобы сменить настройки в этом чате.',
'_cmd_doc_rptoggle': 'Используйте .rptoggle, чтобы включить/выключить РП-мод.',
'_cmd_doc_useraccept': 'Допустить или нет пользователя/чат к РП-командам. Аргументы: <айди пользователя/чата>. '
'Можно без ответа и аргумента, тогда действие будет выполнена над текущим чатом. '
'Можно просто без аргумента, тогда действие будет выполнено над пользователем из '
'ответа. Еси использовано с -l (л), то будет показан список допущенных пользователей/чатов.',
'_cmd_doc_mmminfo': 'Показать информацию о моде.',
}
async def client_ready(self, client, db):
self.db = db
if not self.db.get("RPMod", "exlist", False):
self.db.set("RPMod", "exlist", [])
if not self.db.get("RPMod", "status", False):
self.db.get("RPMod", "status", 1)
if not self.db.get("RPMod", "rpnicks", False):
self.db.set("RPMod", "rpnicks", {})
if not self.db.get("RPMod", "rpcomands", False):
self.db.set("RPMod", "rpcomands", {})
if not self.db.get("RPMod", "rpemoji", False):
self.db.set("RPMod", "rpemoji", {})
if not self.db.get("RPMod", "nrpcommands", False):
# Check if the old version of the module is installed
if self.db.get("RPMod", "rpcomands", False):
# Copy the dict
commands_old = self.db.get("RPMod", "rpcomands")
emoji_old = self.db.get("RPMod", "rpemoji")
# Create a new dict
commands_new = {}
# For each key in the old dict try to find the emoji in the old dict and add as second element of list
for key in commands_old:
try:
commands_new[key] = [commands_old[key], emoji_old[key]]
except KeyError:
commands_new[key] = [commands_old[key], '']
# Save the new dict
self.db.set("RPMod", "nrpcommands", commands_new)
else:
# If the old version of the module is not installed, create an empty dict
self.db.set("RPMod", "nrpcommands", {})
if not self.db.get("RPMod", "useraccept", False):
self.db.set("RPMod", "useraccept", {"chats": [], "users": []})
elif isinstance(type(self.db.get("RPMod", "useraccept")), list):
self.db.set(
"RPMod",
"useraccept",
{"chats": [], "users": self.db.get("RPMod", "useraccept")},
)
async def dobrpcmd(self, message):
"""Use: .dobrp (command) / (action) / (emoji) to add command. You can do it without emoji."""
args = utils.get_args_raw(message)
dict_rp = self.db.get("RPMod", "nrpcommands")
try:
key_rp = str(args.split("/")[0]).strip().casefold()
value_rp = str(args.split("/", maxsplit=2)[1]).strip()
lenght_args = args.split("/")
count_emoji = 0
if ' ' in key_rp:
await utils.answer(message, self.strings("space"))
return
if len(lenght_args) >= 3:
emoji_rp = str(message.text.split("/", maxsplit=2)[2]).strip()
count_emoji = 1
if not emoji_rp or not emoji_rp.strip():
await utils.answer(
message, self.strings("separator…")
)
return
if not key_rp or not key_rp.strip():
return await utils.answer(message, self.strings("name?"))
elif not value_rp or not value_rp.strip():
return await utils.answer(
message, self.strings("action")
)
elif key_rp == "all":
return await utils.answer(
message, self.strings("aarf"),
)
elif count_emoji == 1:
dict_rp[key_rp] = [value_rp, emoji_rp]
self.db.set("RPMod", "nrpcommands", dict_rp)
await utils.answer(
message,
self.strings("added1").format(key_rp, emoji_rp),
)
else:
dict_rp[key_rp] = [value_rp, '']
self.db.set("RPMod", "nrpcommands", dict_rp)
await utils.answer(
message,
self.strings("added2").format(key_rp),
)
except Exception:
await utils.answer(
message, self.strings("weresall"),
)
async def addrpcmd(self, message):
"""dobrp alias."""
await self.dobrpcmd(message)
async def delrpcmd(self, message):
"""Use: .delrp (command) to delete command.
Use: .delrp all to delete all commands."""
dict_rp = self.db.get("RPMod", "nrpcommands")
args = utils.get_args_raw(message)
key_rp = str(args)
if key_rp == "all":
dict_rp.clear()
self.db.set("RPMod", "nrpcommands", dict_rp)
await utils.answer(message, self.strings("cleared"))
return
elif not key_rp or not key_rp.strip():
await utils.answer(message, self.strings("name?"))
else:
try:
dict_rp.pop(key_rp)
self.db.set("RPMod", "nrpcommands", dict_rp)
await utils.answer(
message, self.strings("deleted").format(key_rp),
)
except KeyError:
await utils.answer(message, self.strings("notfound"))
async def rptogglecmd(self, message):
"""Use: .rptoggle to turn on/off RP mode."""
status = self.db.get("RPMod", "status")
if status == 1:
self.db.set("RPMod", "status", 2)
await utils.answer(message, self.strings("off"))
else:
self.db.set("RPMod", "status", 1)
await utils.answer(message, self.strings("on"))
async def rplistcmd(self, message):
"""Use: .rplist to see list of RP commands."""
com = self.db.get("RPMod", "nrpcommands")
coms_amount = len(com)
com_list = self.strings("count").format(coms_amount)
if len(com) == 0:
await utils.answer(message, self.strings("count").format(coms_amount))
return
for i in com:
if com[i][1] != '':
com_list += f"\n• <b><code>{i}</code> - {com[i][0]} |</b> {com[i][1]}"
else:
com_list += f"\n• <b><code>{i}</code> - {com[i][0]}</b>"
await utils.answer(message, com_list)
async def rpnickcmd(self, message):
"""Use: .rpnick (nick) to change nick to user or yourself."""
args = utils.get_args_raw(message).strip()
reply = await message.get_reply_message()
nicks = self.db.get("RPMod", "rpnicks")
if not reply:
user = await message.client.get_entity(message.sender_id)
else:
user = await message.client.get_entity(reply.sender_id)
if not args:
if str(user.id) in nicks:
nicks.pop(str(user.id))
self.db.set("RPMod", "rpnicks", nicks)
return await utils.answer(
message,
self.strings("nick-changed").format(user.id, user.first_name),
)
nicks[str(user.id)] = args
self.db.set("RPMod", "rpnicks", nicks)
await utils.answer(
message,
self.strings("nick-changed").format(user.id, args),
)
async def rpnickscmd(self, message):
"""Use: .rpnicks to see list of nicknames."""
nicks = self.db.get("RPMod", "rpnicks")
if len(nicks) == 0:
return await utils.answer(message, self.strings("no-nicks"))
str_nicks = "" + "\n".join(
" --- ".join([f"<code>{user_id}</code>", f"<b>{nick}</b>"])
for user_id, nick in nicks.items()
)
await utils.answer(message, str_nicks)
async def orpbackcmd(self, message):
"""Backup RP commands (old fashioned method).
Use as reply to file with commands to load them or use without
arguments to back up them."""
commands = self.db.get("RPMod", "nrpcommands")
file_name = "LiMERPModBackUp (on compat).pickle"
mes_id = message.to_id
reply = await message.get_reply_message()
if not reply:
# Split them into 2 dicts
emojies = {}
for key, value in commands.items():
if commands[key][1] != "":
emojies[key] = commands[key][1]
commands[key] = commands[key][0]
try:
await message.delete()
dict_all = {"rp": commands, "emj": emojies}
with open(file_name, "wb") as f:
pickle.dump(dict_all, f)
await message.client.send_file(mes_id, file_name)
os.remove(file_name)
except Exception as e:
await utils.answer(message, f"<b>Ошибка:\n</b>{e}")
else:
try:
if not reply.document:
await utils.answer(message, self.strings("itsnotafile"))
await reply.download_media(file_name)
with open(file_name, "rb") as f:
data = pickle.load(f)
rp = data["rp"]
emj = data["emj"]
# Iterating through keys
for key in rp.keys():
if key in emj.keys():
rp[key] = [rp[key], emj[key]]
self.db.set("RPMod", "nrpcommands", rp)
await utils.answer(message, self.strings("actualised"))
except Exception as e:
await utils.answer(message, self.strings("error-with-type").format(e))
async def rpbackcmd(self, message):
"""New way to backup RP commands. Use as reply to file with commands to load them or use without arguments to back up them."""
commands = self.db.get("RPMod", "nrpcommands")
file_name = "LiMERPModBackUp.toml"
mes_id = message.to_id
reply = await message.get_reply_message()
if not reply:
# Dump it into toml
try:
await message.delete()
with open(file_name, "w") as f:
toml.dump(commands, f)
await message.client.send_file(mes_id, file_name)
os.remove(file_name)
except Exception as e:
await utils.answer(message, f"<b>Ошибка:\n</b>{e}")
else:
try:
if not reply.document:
await utils.answer(message, self.strings("itsnotafile"))
await reply.download_media(file_name)
with open(file_name, "r") as f:
try:
data = toml.load(f)
except toml.TomlDecodeError as e:
return await utils.answer(message, self.strings("toml-parse-failure"))
# Check validity
for key in data.keys():
if not isinstance(data[key], list):
return await utils.answer(message, self.strings("toml-minparse-failure"))
if len(data[key]) != 2:
return await utils.answer(message, self.strings("toml-minparse-failure"))
self.db.set("RPMod", "nrpcommands", data)
await utils.answer(message, self.strings("actualised"))
except Exception as e:
await utils.answer(message, self.strings("error-with-type").format(e))
async def rpblockcmd(self, message):
"""Use: .rpblock to add/remove exception (use in needed chat).
Use: .rpblock list to see exceptions.
Use .rpblock (id) to remove chat from exceptions."""
args = utils.get_args_raw(message)
ex = self.db.get("RPMod", "exlist")
if not args:
a = await message.client.get_entity(message.to_id)
if a.id in ex:
ex.remove(a.id)
self.db.set("RPMod", "exlist", ex)
try:
name = a.title
except Exception:
name = a.first_name
await utils.answer(
message,
self.strings("chat-included").format(name),
)
else:
ex.append(a.id)
self.db.set("RPMod", "exlist", ex)
try:
name = a.title
except Exception:
name = a.first_name
await utils.answer(
message,
self.strings("chat-excluded").format(name),
)
elif args.isdigit():
args = int(args)
if args in ex:
ex.remove(args)
self.db.set("RPMod", "exlist", ex)
a = await message.client.get_entity(args)
try:
name = a.title
except Exception:
name = a.first_name
await utils.answer(
message,
self.strings("chat-included").format(name),
)
else:
try:
a = await message.client.get_entity(args)
except Exception:
return await utils.answer(message, self.strings("id-wrong"))
ex.append(args)
self.db.set("RPMod", "exlist", ex)
try:
name = a.title
except Exception:
name = a.first_name
await utils.answer(message, self.strings("chat-excluded").format(name))
elif args == "list":
ex_len = len(ex)
if ex_len == 0:
await utils.answer(message, self.strings("empty-exclude"))
return
sms = self.strings("excluded-chats")
for i in ex:
try:
a = await message.client.get_entity(i)
except Exception:
await utils.answer(message, self.strings("id-wrong"))
return
try:
name = a.title
except Exception:
name = a.first_name
sms += f"\n• <b><u>{name}</u> --- </b><code>{i}</code>"
await utils.answer(message, sms)
else:
await utils.answer(message, self.strings("s-t-wrong"))
async def useracceptcmd(self, message):
"""Adding/removing users/chats, allowed to use your commands.
.useraccept {id/reply}
To add chat use without reply and args. Use with -l (L) to see list of users/chats."""
reply = await message.get_reply_message()
args = utils.get_args_raw(message)
user_a = self.db.get("RPMod", "useraccept")
if not reply and not args and message.is_group:
chat = message.chat
if chat.id not in user_a["chats"]:
user_a["chats"].append(chat.id)
return await utils.answer(
message,
self.strings("on-in-chat").format(chat.title),
)
else:
user_a["chats"].remove(chat.id)
return await utils.answer(
message,
self.strings("off-in-chat").format(chat.title),
)
elif args.lower() == "-l" or args.lower() == "л":
sms = self.strings("who-have")
for k, v in user_a.items():
if k == "chats":
sms += '\n' + self.strings("chats-s")
else:
sms += '\n' + self.strings("users-s")
for i in v:
try:
user = (
(await message.client.get_entity(int(i))).title
if k == "chats"
else (await message.client.get_entity(int(i))).first_name
)
sms += f"\n<b>• <u>{user}</u> ---</b> <code>{i}</code>"
except Exception:
sms += f"\n<b>•</b> <code>{i}</code>"
await utils.answer(message, sms)
elif args or reply:
args = int(args) if args.isdigit() else reply.sender_id
if args in user_a["users"]:
user_a["users"].remove(args)
self.db.set("RPMod", "useraccept", user_a)
await utils.answer(
message,
self.strings("off-for-usr").format(args)
)
elif args in user_a["chats"]:
user_a["chats"].remove(args)
self.db.set("RPMod", "useraccept", user_a)
await utils.answer(
message, self.strings("off-in-chat").format(args)
)
elif (
args not in user_a["chats"]
and type(await message.client.get_entity(args)) == Channel
):
user_a["chats"].append(args)
self.db.set("RPMod", "useraccept", user_a)
await utils.answer(
message, self.strings("on-in-chat").format(args)
)
else:
user_a["users"].append(args)
self.db.set("RPMod", "useraccept", user_a)
await utils.answer(
message,
self.strings("on-for-usr").format(args),
)
else:
await utils.answer(message, self.strings("s-t-wrong"))
async def mmminfocmd(self, message):
"""Read mod information and updates."""
await utils.answer(message, self.strings("whatschanged"))
async def rpchatscmd(self, message):
"""Use: .rpchats to see list of chats where RP commands are allowed."""
user_a = self.db.get("RPMod", "useraccept")
sms = self.strings("who-have")
for i in user_a["chats"]:
try:
chat = await message.client.get_entity(i)
sms += f"\n• <b><u>{chat.title}</u> ---</b> <code>{i}</code>"
except Exception:
sms += f"\n• <code>{i}</code>"
await utils.answer(message, sms)
async def watcher(self, message):
try:
status = self.db.get("RPMod", "status")
commands = self.db.get("RPMod", "nrpcommands")
ex = self.db.get("RPMod", "exlist")
nicks = self.db.get("RPMod", "rpnicks")
users_accept = self.db.get("RPMod", "useraccept")
chat_rp = await message.client.get_entity(message.to_id)
if status != 1 or chat_rp.id in ex:
return
me_id = (await message.client.get_me()).id
if (
message.sender_id not in users_accept["users"]
and message.sender_id != me_id
and chat_rp.id not in users_accept["chats"]
):
return
me = await message.client.get_entity(message.sender_id)
if str(me.id) in nicks.keys():
nick = nicks[str(me.id)]
else:
nick = me.first_name
if ' ' in message.text and '\n' not in message.text:
args = message.text.split(' ', 1)[0].casefold() + ' ' + message.text.split(' ', 1)[1]
elif '\n' in message.text:
arl = message.text.split('\n', 1)
if ' ' in arl[0]:
args = arl[0].split(' ', 1)[0].casefold() + ' ' + arl[0].split(' ', 1)[1] + '\n' + arl[1]
else:
args = arl[0].casefold() + '\n' + arl[1]
else:
args = message.text.casefold()
lines = args.splitlines()
tags = lines[0].split(" ")
if not tags[-1].startswith("@"):
reply = await message.get_reply_message()
user = await message.client.get_entity(reply.sender_id)
else:
if not tags[-1][1:].isdigit():
user = await message.client.get_entity(tags[-1])
else:
user = await message.client.get_entity(int(tags[-1][1:]))
lines[0] = lines[0].rsplit(" ", 1)[0]
detail = lines[0].split(" ", maxsplit=1)
if len(detail) < 2:
detail.append(" ")
if detail[0] not in commands.keys():
return
command = commands[detail[0]]
detail[1] = " " + detail[1]
user.first_name = (
nicks[str(user.id)] if str(user.id) in nicks else user.first_name
)
action_decoration = self.config['action_decoration']
replica_decoration = self.config['replica_decoration']
bubble = self.config['speech_bubble']
if 'bold' in action_decoration:
s1 = ["<b>", "</b>"]
elif 'italic' in action_decoration:
s1 = ["<i>", "</i>"]
elif 'underline' in action_decoration:
s1 = ["<u>", "</u>"]
elif 'strikethrough' in action_decoration:
s1 = ["<s>", "</s>"]
elif 'spoiler' in action_decoration:
s1 = ["<spoiler>", "</spoiler>"]
else:
s1 = ["", ""]
if 'bold' in replica_decoration:
s2 = ["<b>", "</b>"]
elif 'italic' in replica_decoration:
s2 = ["<i>", "</i>"]
elif 'underline' in replica_decoration:
s2 = ["<u>", "</u>"]
elif 'strikethrough' in replica_decoration:
s2 = ["<s>", "</s>"]
elif 'spoiler' in replica_decoration:
s2 = ["<spoiler>", "</spoiler>"]
else:
s2 = ["", ""]
rp_message_send = ""
if command[1]:
rp_message_send += command[1] + " | "
rp_message_send += f"<a href=tg://user?id={me.id}>{nick}</a> {s1[0]}{command[0]}{s1[1]} " \
f"<a href=tg://user?id={user.id}>{user.first_name}</a>{detail[1]}"
if len(lines) >= 2:
replica = '\n'.join(lines[1:])
rp_message_send += f"\n{bubble} {self.strings('with-replica')} {s2[0]}{replica}{s2[1]}"
return await utils.answer(message, rp_message_send)
except Exception:
pass
@staticmethod
def merge_dict(d1, d2):
d_all = {**d1, **d2}
for key in d_all:
d_all[key] = {**d1[key], **d_all[key]}
return d_all

View File

@@ -0,0 +1,133 @@
# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0
# meta developer: @minimaxno
# meta pic: https://img.icons8.com/emoji/344/scroll-emoji.png
# requires: deep-translator
from .. import loader, utils
from telethon import types
from telethon.tl.types import Message
import re
import os
import requests as rq
from deep_translator import GoogleTranslator as GT
import logging
logger = logging.getLogger(__name__)
@loader.tds
class MHelpMod(loader.Module):
"""Helps to download mods to file and automaticaly make simple descriptions for your modules."""
strings = {'name': 'MHelp', 'noname': "🙅🏼‍♂️ <b>You've not setted your GitHub username!</b>", 'norepo': "🗒️ <b>You've not setted your Hikka modules repo!</b>", 'format?': '🚫 <b>Incorrect format!</b>', 'inname': '🤖 <b>Name is incorrect!</b>', '404': '🔦 <b>Requested file not found!</b>', 'lang?': '㊙️ <b>I dunno such language!</b>', 'suc': '👌🏻 <b>Succesful!</b>'}
strings_ru = {'name': 'MHelp', 'noname': "🙅🏼‍♂️ <b>Ты ещё не установил свой юзернейм на GitHub!</b>", 'norepo': "🗒️ <b>Ты ещё не установил имя репозитария с модулями!</b>", 'format?': '🚫 <b>Неверный формат!</b>', 'inname': '🤖 <b>Некорректное имя</b>', '404': '🔦 <b>Не нашёл такого файла!</b>', 'lang?': '㊙️ <b>Один из введёных языков мне неизвестен!</b>', 'suc': '👌🏻 <b>Успешно!</b>'}
strings_de = {'name': 'MHelp', 'noname': "🙅🏼‍♂️ <b>Geben Sie Ihren auf GitHub verwendeten Benutzernamen!</b>", 'norepo': "🗒️ <b>Geben Sie den Namen des Repositorys ein, das zum Speichern der Module verwendet wird!</b>", 'format?': '🚫 <b>Ungültiges Format!</b>', 'inname': '🤖 <b>Ungültiger Name!</b>', '404': '🔦 <b>Es gibt keine solche Datei!</b>', 'lang?': '㊙️ <b>Eine der eingegebenen Sprachen ist mir unbekannt!</b>', 'suc': '👌🏻 <b>Erfolgreich!</b>'}
async def client_ready(self, client, db):
self.client = client
self.db = db
async def setuncmd(self, m: Message):
"""Configurates GH username."""
name = utils.get_args_raw(m)
if (len(name) > 39) or (name[len(name)-1] == '-') or (name[0] == '-') or (name == '') or ('--' in name) or (re.search(name, '[^ a-zA-Z0-9-]')):
await utils.answer(m, self.strings('inname'))
return
else:
self.set('ghun', name)
await utils.answer(m, self.strings('suc'))
async def setrepocmd(self, m: Message):
"""Configurates GH repo name."""
name = utils.get_args_raw(m)
if (len(name) > 100) or (name[len(name)-1] == '-') or (name[0] == '-') or (name == '') or ('--' in name) or (re.search(name, '[^ a-zA-Z0-9-_.]')):
await utils.answer(m, self.strings('inname'))
return
else:
self.set('repon', name)
await utils.answer(m, self.strings('suc'))
async def descrcmd(self, m: Message):
"""Makes decription. Required format:
emoji > name > description > base language code, language codes to translate automatocally, … """
if not (self.get("ghun", False)):
await utils.answer(m, self.strings('noname'))
return
if not (self.get("repon", False)):
await utils.answer(m, self.strings('norepo'))
return
prompt = utils.get_args_raw(m)
try:
emoji, name, descr, langs = prompt.split(' > ')
except:
await utils.answer(m, self.strings('format?'))
ans = f'{emoji} <b>{name}'+'</b>\n\n'+descr
if ', ' in langs:
langs = langs.split(', ')
else:
langs = [langs]
avla = GT().get_supported_languages(as_dict = True)
for i in langs:
if i not in avla.values():
await utils.answer(m, self.strings('lang?'))
return
if len(langs) > 1:
for lang in range(1, len(langs)):
tren = GT(langs[0], langs[lang])
tr_descr = "".join(
[
await utils.run_sync(lambda: tren.translate(chunk))
for chunk in utils.chunks(descr, 512)
]
)
ans += '\n\n\n\n' + tr_descr
if langs[0] != 'ru':
download = GT('auto', langs[0]).translate('Скачать')
else:
download = 'Скачать'
for lang in range(1, len(langs)):
if langs[lang] != 'ru':
download += ' | ' + GT('ru', langs[lang]).translate('Скачать')
else:
download += ' | Скачать'
link = 'https://raw.githubusercontent.com/'+self.get('ghun')+'/'+self.get('repon')+'/main/'+name+'.py'
ans += '\n\n\n\n<b>' + download + '</b>\n<code>.dlmod '+link+'</code>'
if rq.get(link).status_code != 200:
await utils.answer(m, self.strings('404'))
return
else:
open(f'{name}.py', 'w').write(rq.get(link).text)
if len(ans) > 1024:
ans = [ans[i:i+1024] for i in range(0, len(ans), 1024)]
else:
ans = [ans]
await m.client.send_file(m.to_id, f'{name}.py', caption=ans[0], parse_mode='HTML')
for i in range(1, len(ans)):
await m.respond(ans[i])
os.remove(f'{name}.py')
await m.delete()
async def topycmd(self, m: Message):
"""Gets module from link."""
link = utils.get_args_raw(m)
if ('github' and 'hikariatama') not in link:
await utils.answer(m, self.strings('format?'))
return
else:
if rq.get(link).status_code != 200:
await utils.answer(m, self.strings('404'))
return
else:
open(f'Mod.py', 'w').write(rq.get(link).text)
await m.client.send_file(m.to_id, f'Mod.py')
os.remove(f'Mod.py')
await m.delete()

View File

@@ -0,0 +1,132 @@
# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0
# meta pic: https://img.icons8.com/stickers/344/block.png
# meta developer: @mm_mods
__version__ = "1.0.0"
import asyncio
from .. import loader, utils
import telethon as tt
from telethon.tl.types import Message
import logging
logger = logging.getLogger(__name__)
@loader.tds
class MMASMod(loader.Module):
"""Protects your account from spam if anyone accessed your account/session."""
strings = {
"name": "MMAS",
"found": "<b>Spam found!</b>\nText: <code>{}</code>",
"limit_set": "<b>Limit set to {}</b>",
"limit_get": "<b>Limit is {}</b>",
"on": "<b>Enabled.</b>",
"off": "<b>Disabled.</b>",
}
strings_ru = {
"name": "MMAS",
"found": "<b>Спам найден!</b>\nТекст: <code>{}</code>",
"limit_set": "<b>Лимит установлен на {}</b>",
"limit_get": "<b>Лимит равен {}</b>",
"on": "<b>Включено.</b>",
"off": "<b>Выключено.</b>",
"_cls_doc": "Защищает ваш аккаунт от спама, если кто-то получил доступ к вашей учетной записи/сеансу.",
"_cmd_doc_mmas": "Включить/выключить модуль.",
"_cmd_doc_mmaslimit": "Получить или установить лимит одинаковых сообщений, отправленных вами.",
}
strings_de = {
"name": "MMAS",
"found": "<b>Spam gefunden!</b>\nText: <code>{}</code>",
"limit_set": "<b>Limit auf {} gesetzt</b>",
"limit_get": "<b>Limit ist {}</b>",
"on": "<b>Aktiviert.</b>",
"off": "<b>Deaktiviert.</b>",
"_cls_doc": "Schützt dein Konto vor Spam, wenn jemand auf dein Konto/zur Sitzung zugreift.",
"_cmd_doc_mmas": "Aktiviere/Deaktiviere das Modul.",
"_cmd_doc_mmaslimit": "Erhalte oder setze das Limit für die Anzahl der gleichen Nachrichten, die du "
"gesendet hast.",
}
strings_tr = {
"name": "MMAS",
"found": "<b>Spam bulundu!</b>\nMetin: <code>{}</code>",
"limit_set": "<b>Sınır {} olarak ayarlandı</b>",
"limit_get": "<b>Sınır {}</b>",
"on": "<b>Açık.</b>",
"off": "<b>Kapalı.</b>",
"_cls_doc": "Hesabınızı kimse erişemezse spam koruması.",
"_cmd_doc_mmas": "Modülü aç/kapat.",
"_cmd_doc_mmaslimit": "Aynı mesajı kaç kere gönderdiğinizi alın veya ayarlayın.",
}
async def client_ready(self, client, db):
self._client = client
self._db = db
if not self.get("limit", False):
self.set("limit", 5)
if not self.get("on", False):
self.set("on", True)
if not self.get("lat", False):
self.set("lat", '')
if not self.get("count", False):
self.set("count", 0)
if not self.get("logged", False):
self.set("logged", False)
async def mmascmd(self, message: Message):
"""Toggle the module."""
if self.get("on", False):
self.set("on", False)
await utils.answer(message, self.strings("off"))
else:
self.set("on", True)
await utils.answer(message, self.strings("on"))
async def mmaslimitcmd(self, message: Message):
"""Get or set the limit of same messages sent by you."""
args = utils.get_args_raw(message)
if not args:
await utils.answer(message, self.strings("limit_get").format(self.get("limit")))
return
try:
if int(args) < 2:
await utils.answer(message, self.strings("limit_set").format(2))
self.set("limit", 2)
return
self.set("limit", int(args))
await utils.answer(message, self.strings("limit_set").format(self.get("limit")))
except ValueError:
await utils.answer(message, self.strings("limit_get").format(self.get("limit")))
async def watcher(self, message: Message):
if not self.get("on", False):
return
if not message.text:
return
if not message.out:
return
if message.raw_text != self.get("lat", False):
self.set("lat", message.raw_text)
self.set("count", 1)
return
else:
self.set("count", self.get("count") + 1)
if self.get("count") >= self.get("limit"):
await message.delete()
if not self.get("logged", False):
self.set("logged", True)
logging.warning(self.strings("found").format(message.raw_text))
return

View File

@@ -0,0 +1,126 @@
# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0
# meta pic: https://img.icons8.com/stickers/344/sticker.png
# meta developer: @mm_mods
__version__ = "1.0.0"
from .. import loader, utils
import random
from telethon.tl.types import Message
import logging
logger = logging.getLogger(__name__)
# Database in format {name: {id: in_chat_id}}
db = {
'cherry': {'1': 2, '2': 3, '3': 4},
'fox1': {'1': 5, '2': 6, '3': 7, '4': 8},
'goose': {'1': 9, '2': 10, '3': 11, '4': 12, '5': 13, '6': 14},
'balloon': {'1': 15, '2': 16, '3': 17, '4': 18},
'cats': {'1': 19, '2': 20, '3': 21, '4': 22, '5': 23},
'croco1': {'1': 24, '2': 25, '3': 26, '4': 27, '5': 28},
'puppy': {'1': 29, '2': 30},
'peach': {'1': 31, '2': 32},
'monkey1': {'1': 33, '2': 34},
'fox2': {'1': 35, '2': 36, '3': 37, '4': 38},
'duck': {'1': 39, '2': 40, '3': 41, '4': 42},
'fire': {'1': 43, '2': 44, '3': 45, '4': 46},
'tiger': {'1': 47, '2': 48, '3': 49, '4': 50},
'bud': {'1': 51, '2': 52},
'croco2': {'1': 53, '2': 54, '3': 55, '4': 56},
'lady': {'1': 57, '2': 58, '3': 59},
'cat1': {'1': 60, '2': 61, '3': 62},
'crab': {'1': 63},
'bunny': {'1': 64, '2': 65, '3': 66, '4': 67, '5': 68},
'arts': {'1': 69, '2': 70, '3': 71},
'lamb': {'1': 72, '2': 73, '3': 74},
'hands': {'1': 75, '2': 76, '3': 77, '4': 78},
'shiba': {'1': 79, '2': 80, '3': 81},
'cloud': {'1': 82},
'cang': {'1': 83},
'made': {'1': 84, '2': 85},
'donut': {'1': 86},
'frog': {'1': 87},
'dog': {'1': 88, '2': 89},
'monkey2': {'1': 90, '2': 91},
'hearts': {'1': 92, '2': 93},
'seagull': {'1': 94, '2': 95, '3': 96},
'cat2': {'1': 97, '2': 98, '3': 99},
'dino': {'1': 100, '2': 101, '3': 102},
'strawberry': {'1': 103, '2': 104, '3': 105, '4': 106},
}
@loader.tds
class PSAMod(loader.Module):
"""Send premium stickers without premium! Advanced version of Hikariatama's module."""
strings = {
'name': 'PremiumStickers2',
'pack?': '🟨 <b>You need to specify a pack name.</b>',
'pack?!': '🟥 <b>There is no such pack.</b>',
'sticker?': '🟨 <b>You need to specify a sticker number.</b>',
'sticker?!': '🟥 <b>There is no such sticker in this pack.</b>',
'args?': '🟨 <b>No arguments.</b>\n<b>Usage:</b> <code>.psa pack_name sticker_number</code>',
'packs': '📜 <b>Available packs:</b>\n'
}
strings_ru = {
'pack?': '🟨 <b>Вы должны указать название пака.</b>',
'pack?!': '🟥 <b>Такого пака нет.</b>',
'sticker?': '🟨 <b>Вы должны указать номер стикера.</b>',
'sticker?!': '🟥 <b>Такого стикера в этом паке нет.</b>',
'args?': '🟨 <b>Нет аргументов.</b>\n<b>Использование:</b> <code>.psa название_пака номер_стикера</code>',
'packs': '📜 <b>Доступные паки:</b>\n',
'_cls_doc': 'Отправляй премиум-стикеры без премиума! Улучшеная версия модуля от Хикари (@hikarimods).',
'_cmd_doc_psa': 'Отправить стикер из пака … под номером … .',
'_cmd_doc_psalist': 'Список паков и количество стикеров в них.'
}
strings_uk = {
'pack?': '🟨 <b>Ви повинні вказати назву паку.</b>',
'pack?!': '🟥 <b>Такого паку немає.</b>',
'sticker?': '🟨 <b>Ви повинні вказати номер стікера.</b>',
'sticker?!': '🟥 <b>Такого стікера в цьому паку немає.</b>',
'args?': '🟨 <b>Немає аргументів.</b>\n<b>Використання:</b> <code>.psa назва_паку номер_стікера</code>',
'packs': '📜 <b>Доступні паки:</b>\n',
'_cls_doc': 'Відправляй преміум-стікери без преміума! Покращена версія модуля від Хікарі (@hikarimods).',
'_cmd_doc_psa': 'Відправити стікер з паку … під номером … .',
'_cmd_doc_psalist': 'Список паків і кількість стікерів в них.'
}
async def psacmd(self, m: Message):
"""Sends from pack … sticker number … ."""
args = utils.get_args_raw(m)
if args == '':
return await utils.answer(m, self.strings('args?'))
if ' ' not in args:
return await utils.answer(m, self.strings('sticker?'))
pack, num = args.split(' ', 1)
if not num.isdigit():
return await utils.answer(m, self.strings('sticker?!'))
if pack not in db.keys():
return await utils.answer(m, self.strings('pack?!'))
if num not in db[pack].keys():
return await utils.answer(m, self.strings('sticker?!'))
if m.out:
await m.delete()
await m.respond(f'<a href="https://t.me/hikka_premum_stickers/{db[pack][num]}">­</a>')
async def psalistcmd(self, m: Message):
"""Packs list."""
plist = self.strings('packs')
for i in db.keys():
plist += f'<code>{i}</code> (<a href="https://t.me/hikka_premum_stickers/{db[i]["1"]}">{len(db[i])}</a>)\n'
await utils.answer(m, plist)

View File

@@ -0,0 +1,260 @@
# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0
# meta pic: https://img.icons8.com/?size=512&id=17387&format=png
# meta developer: @mm_mods
__version__ = "1.0"
import asyncio
import aiohttp
from hikka import loader, utils
from telethon.tl.patched import Message
import logging
import random
logger = logging.getLogger(__name__)
name_models = {
"Analog Diffusion V1": "analog-diffusion-1.0.ckpt [9ca13f02]",
"Anything V3": "anythingv3_0-pruned.ckpt [2700c435]",
"Anything V4": "anything-v4.5-pruned.ckpt [65745d25]",
"Anything V5": "anythingV5_PrtRE.safetensors [893e49b9]",
"Orangemix": "AOM3A3_orangemixs.safetensors [9600da17]",
"Deliberate V2": "deliberate_v2.safetensors [10ec4b29]",
"Dreamlike Diffusion V1": "dreamlike-diffusion-1.0.safetensors [5c9fd6e0]",
"Dreamlike Diffusion V2": "dreamlike-diffusion-2.0.safetensors [fdcf65e7]",
"Dreamshaper V5": "dreamshaper_5BakedVae.safetensors [a3fbf318]",
"Dreamshaper V6": "dreamshaper_6BakedVae.safetensors [114c8abb]",
"Elldreth's Vivid Mix": "elldreths-vivid-mix.safetensors [342d9d26]",
"Lyriel V1.5": "lyriel_v15.safetensors [65d547c5]",
"Meina V9": "meinamix_meinaV9.safetensors [2ec66ab0]",
"OpenJourney V4": "openjourney_V4.ckpt [ca2f377f]",
"Portrait V1": "portrait+1.0.safetensors [1400e684]",
"Realistic Vision V2": "Realistic_Vision_V2.0.safetensors [79587710]",
"Rev Animated V1.22": "revAnimated_v122.safetensors [3f4fefd9]",
"Riffusion V1": "riffusion-model-v1.ckpt [3aafa6fe]",
"StableDiffusion V1.4": "sdv1_4.ckpt [7460a6fa]",
"StableDiffusion V1.5": "v1-5-pruned-emaonly.ckpt [81761151]",
"Shonin's Beautiful People V1": "shoninsBeautiful_v10.safetensors [25d8c546]",
"The Ally's Mix II": "theallys-mix-ii-churned.safetensors [5d9225a4]",
"Timeless V1": "timeless-1.0.ckpt [7c4971d4]",
}
samplers = ["Euler", "Euler a", "Heun", "DPM++ 2M Karras", "DDIM"]
# noinspection PyCallingNonCallable
@loader.tds
class ProdiaMod(loader.Module):
"""Image generator based on Prodia API. No API key required."""
def __init__(self):
self.config = loader.ModuleConfig(
loader.ConfigValue(
"model",
"StableDiffusion V1.5",
lambda: self.strings("model-h"),
validator=loader.validators.Choice(list(name_models.keys())),
),
loader.ConfigValue(
"cfg",
8,
lambda: self.strings("cfg-h"),
validator=loader.validators.Integer(minimum=0, maximum=20),
),
loader.ConfigValue(
"sampler",
"Euler",
lambda: self.strings("sampler-h"),
validator=loader.validators.Choice(samplers),
),
loader.ConfigValue(
"steps",
30,
lambda: self.strings("steps-h"),
validator=loader.validators.Integer(minimum=1, maximum=30),
),
loader.ConfigValue(
"neg_def",
"",
lambda: self.strings("ndef-h"),
validator=loader.validators.String(),
),
)
strings = {
"name": "Prodia IG",
"model-h": "An initial image set on which the model is based.",
"cfg-h": "The higher the value, the closer to prompt the image will be.",
"sampler-h": "The algorithm by which the image will be generated.",
"steps-h": "The number of steps to generate the image, the higher the value, "
"the more detailed the image will be.",
"ndef-h": "Default negative prompt. Negative prompt makes AI to NOT generate described in it thing.",
"args?": "🟡 <b>You provided no args…</b>",
"working": "🎨 <b>Working on your image…</b>\n"
"<b>Prompt:</b> <code>{}</code>{}\n\n"
"<b>Provided parameters:</b>\n"
"<i>Model:</i> {} — ID <code>{}</code>\n"
"<i>CFG</i>: {}\n"
"<i>Sampler:</i> {}\n"
"<i>Steps:</i> {}",
"done": "🎉 <b>Your image is done!</b>\n"
"<b>Prompt:</b> <code>{}</code>{}\n\n"
"<i>Model:</i> {} — ID <code>{}</code>\n"
"<i>CFG:</i> {}\n"
"<i>Sampler:</i> {}\n"
"<i>Steps:</i> {}\n",
"neg_prompt": "\n<i>Negative prompt</i>: <code>{}</code>",
}
strings_ru = {
"name": "Prodia IG",
"model-h": "Начальный набор изображений, на основе которого построена модель.",
"cfg-h": "Чем выше значение, тем более близким к запросу будет изображение.",
"sampler-h": "Алгоритм, по которому будет сгенерировано изображение.",
"steps-h": "Количество шагов для генерации изображения, чем выше значение, "
"тем более детализированным будет изображение.",
"ndef-h": "Стандартный негативный запрос. Негативный промпт заставляет ИИ НЕ генерировать "
"описанную в нём вещь.",
"args?": "🟡 <b>Вы не указали аргументы…</b>",
"working": "🎨 <b>Работаю над изображением…</b>\n"
"<b>Запрос:</b> <code>{}</code>{}\n\n"
"<b>Указанные параметры:</b>\n"
"<i>Модель:</i> {} — ID <code>{}</code>\n"
"<i>CFG</i>: {}\n"
"<i>Сэмплер:</i> {}\n"
"<i>Шаги:</i> {}",
"done": "🎉 <b>Ваше изображение готово!</b>\n"
"<b>Запрос:</b> <code>{}</code>{}\n\n"
"<i>Модель:</i> {} — ID <code>{}</code>\n"
"<i>CFG:</i> {}\n"
"<i>Сэмплер:</i> {}\n"
"<i>Шаги:</i> {}\n",
"neg_prompt": "\n<i>Отрицательный запрос</i>: <code>{}</code>",
"_cls_doc": "Генератор изображений на основе Prodia API. Не требует API ключа.",
"_cmd_doc_prodia": "Сгенерировать изображение с помощью Prodia API.",
}
strings_de = {
"name": "Prodia IG",
"model-h": "Ein Initialbildsatz, auf dem das Modell basiert.",
"cfg-h": "Je höher der Wert, desto näher am Prompt wird das Bild sein.",
"sampler-h": "Der Algorithmus, nach dem das Bild generiert wird.",
"steps-h": "Die Anzahl der Schritte zur Generierung des Bildes, je höher der Wert, "
"desto detaillierter wird das Bild sein.",
"ndef-h": "Standardmäßiger negativer Prompt. Negativer Prompt bewirkt, dass die KI NICHT das in ihm "
"beschriebene Ding generiert.",
"args?": "🟡 <b>Du hast keine Argumente angegeben…</b>",
"working": "🎨 <b>Arbeite an deinem Bild…</b>\n"
"<b>Prompt:</b> <code>{}</code>{}\n\n"
"<b>Angegebene Parameter:</b>\n"
"<i>Modell:</i> {} — ID <code>{}</code>\n"
"<i>CFG</i>: {}\n"
"<i>Sampler:</i> {}\n"
"<i>Schritte:</i> {}",
"done": "🎉 <b>Dein Bild ist fertig!</b>\n"
"<b>Prompt:</b> <code>{}</code>{}\n\n"
"<i>Modell:</i> {} — ID <code>{}</code>\n"
"<i>CFG:</i> {}\n"
"<i>Sampler:</i> {}\n"
"<i>Schritte:</i> {}\n",
"neg_prompt": "\n<i>Negativer Prompt</i>: <code>{}</code>",
"_cls_doc": "Ein Bildgenerator auf Basis der Prodia-API. Benötigt keinen API-Schlüssel.",
"_cmd_doc_prodia": "Generieren Sie ein Bild mit der Prodia-API.",
}
@loader.command("prodia")
async def prodiacmd(self, m: Message):
"""Generate an image using Prodia API."""
prompt = utils.get_args_raw(m)
neg_prompt = ""
if not prompt:
return await utils.answer(m, self.strings("args?"))
if "\n" in prompt:
prompt, neg_prompt = prompt.split("\n", 1)
if neg_prompt == "[]":
neg_prompt = self.config["neg_def"]
mid = name_models[self.config["model"]]
model = self.config["model"]
cfg = self.config["cfg"]
sampler = self.config["sampler"]
steps = self.config["steps"]
if neg_prompt:
nm = await utils.answer(
m,
self.strings("working").format(
prompt,
self.strings("neg_prompt").format(neg_prompt),
model,
mid,
cfg,
sampler,
steps,
),
)
else:
nm = await utils.answer(
m,
self.strings("working").format(
prompt, "", model, mid, cfg, sampler, steps
),
)
url = "https://api.prodia.com"
pars = {
"new": "true",
"prompt": prompt,
"model": mid,
"negative_prompt": neg_prompt,
"steps": steps,
"cfg": cfg,
"seed": random.randint(0, 1000000000),
"sampler": sampler,
"aspect_ratio": "square",
}
async with aiohttp.ClientSession() as s:
async with s.get(f"{url}/generate", params=pars) as r:
resp = await r.json()
job_id = resp["job"]
while True:
async with s.get(f"{url}/job/{job_id}") as r:
resp = await r.json()
if resp["status"] == "succeeded":
break
await asyncio.sleep(0.15)
if neg_prompt:
await utils.answer_file(
nm,
f"https://images.prodia.xyz/{job_id}.png",
caption=self.strings("done").format(
prompt,
self.strings("neg_prompt").format(neg_prompt),
model,
mid,
cfg,
sampler,
steps,
),
)
else:
await utils.answer_file(
nm,
f"https://images.prodia.xyz/{job_id}.png",
caption=self.strings("done").format(
prompt, "", model, mid, cfg, sampler, steps
),
)

View File

@@ -0,0 +1,171 @@
# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0
# meta pic: https://img.icons8.com/stickers/344/diamond-heart.png
# meta developer: @mm_mods
__version__ = "1.0.0"
import asyncio
from .. import loader, utils
import telethon as tt
from telethon.tl.types import Message
import logging
logger = logging.getLogger(__name__)
# Dict with all public reactions of Telegram in format {name: emoji}
edb = {
"like": "👍",
"dislike": "👎",
"love": "❤️",
"fire": "🔥",
"haround": "🥰",
"clap": "👏",
"laugh": "😁",
"suspect": "🤔",
"mindblown": "🤯",
"horror": "😱",
"angry": "🤬",
"sad": "😢",
"fest": "🎉",
"stareyes": "🤩",
"womit": "🤮",
"poop": "💩",
"pray": "🙏",
"ok": "👌",
"peace": "🕊️",
"clown": "🤡",
"tired": "🥱",
"drunk": "🥴",
"hearteyes": "😍",
"whale": "🐳",
"flameheart": "❤️\u200d🔥",
"moon": "🌚",
"hotdog": "🌭",
"100": "💯",
"laughcry": "😂",
"220": "",
"banana": "🍌",
"cup": "🏆",
"brokenheart": "💔",
"hm": "🤨",
"what": "😐",
"berry": "🍓",
"bottle": "🍾",
"kiss": "💋",
"fuck": "🖕",
"devil": "😈",
}
@loader.tds
class ReactTorMod(loader.Module):
"""Reacts manager."""
strings = {
'name': 'Reactor',
'reply?': '🟨 <b>You need to reply a message.</b>',
'name?': '🟨 <b>You need to specify a name.</b>',
'emoji?': '🟨 <b>You need to specify an emoji.</b>',
'name?!': '🟥 <b>Invalid name.</b>',
'emoji?!': '🟥 <b>Invalid emoji.</b>',
'done': '🟩 <b>Done.</b>',
'shorthand_done': '🟩 <b>Created shorthand «{}» for {}.</b>',
}
strings_ru = {
'reply?': '🟨 <b>Тебе нужно ответить на сообщение.</b>',
'name?': '🟨 <b>Тебе нужно указать имя.</b>',
'emoji?': '🟨 <b>Тебе нужно указать эмодзи.</b>',
'name?!': '🟥 <b>Неверное имя.</b>',
'emoji?!': '🟥 <b>Неверный эмодзи.</b>',
'done': '🟩 <b>Готово.</b>',
'shorthand_done': '🟩 <b>Создан ярлык «{}» для {}.</b>',
'_cls_doc': 'Менеджер реакций.',
'_cmd_doc_rshorthand': 'Создать ярлык для реакции.\n/rshorthand <имя> <эмодзи>',
'_cmd_doc_dshorthand': 'Удалить ярлык для реакции.\n/dshorthand <имя>',
'_cmd_doc_shorthands': 'Показать все ярлыки для реакций.',
'_cmd_doc_react': 'Реагирует на сообщение.\n/react <имя>',
}
async def client_ready(self, client, db):
self._client = client
self._db = db
if not self.get("shorthands", False):
self.set("shorthands", {})
async def rshorthandcmd(self, m: Message):
"""Add a shorthand for a reaction.
/rshorthand <name> <emoji>"""
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings('name?'))
args = args.split(" ")
if len(args) < 2:
return await utils.answer(m, self.strings('emoji?'))
name = args[0]
emoji = args[1]
if name in edb.keys():
return await utils.answer(m, self.strings('name?!'))
if emoji not in edb.values() and not isinstance(m.entities[0], tt.tl.types.MessageEntityCustomEmoji):
return await utils.answer(m, self.strings('emoji?!'))
shorthands = self.get("shorthands", {})
if name in shorthands.keys():
return await utils.answer(m, self.strings('name?!'))
if isinstance(m.entities[0], tt.tl.types.MessageEntityCustomEmoji):
emoji = m.entities[0].document_id
shorthands[name] = emoji
self.set("shorthands", shorthands)
await utils.answer(m, self.strings('shorthand_done').format(name, emoji))
async def dshorthandcmd(self, m: Message):
"""Delete a shorthand for a reaction.
/dshorthand <name>"""
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings('name?'))
shorthands = self.get("shorthands", {})
if args not in shorthands.keys():
return await utils.answer(m, self.strings('name?!'))
del shorthands[args]
self.set("shorthands", shorthands)
await utils.answer(m, self.strings('done'))
async def shorthandscmd(self, m: Message):
"""Show all shorthands for reactions."""
shorthands = self.get("shorthands", {})
text = "<b>Ярлыки реакций:</b>\n"+ "".join(f"{name} - {emoji}\n" for name, emoji in shorthands.items()) + "<b>Стандартные ярлыки реакций:</b>\n" + "".join(f"{name} - {emoji}\n" for name, emoji in edb.items())
await utils.answer(m, text)
async def reactcmd(self, m: Message):
"""React to a message.
/react <name>/<emoji>"""
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings('name?'))
if args in edb.keys():
emoji = edb[args]
else:
shorthands = self.get("shorthands", {})
if args in shorthands.keys():
emoji = shorthands[args]
else:
return await utils.answer(m, self.strings('name?!'))
if not m.is_reply:
return await utils.answer(m, self.strings('reply?'))
reply = await m.get_reply_message()
if isinstance(emoji, str):
await reply.react(emoji)
else:
await reply.react(tt.tl.types.ReactionCustomEmoji(emoji))
await utils.answer(m, self.strings('done'))
await asyncio.sleep(1)
await m.delete()

View File

@@ -0,0 +1,597 @@
# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0
# meta pic: https://img.icons8.com/emoji/344/mechanical-arm.png
# meta developer: @mm_mods
__version__ = "1.0.3"
from .. import loader, utils
from telethon.tl.types import Message, PeerChannel, ChannelParticipantsAdmins
import logging
logger = logging.getLogger(__name__)
@loader.tds
class RechteMod(loader.Module):
"""Group rights viewer and manager."""
strings = {
"name": "Rechte",
"group?!": "👥 <b>This command must be used in group.</b>",
"rightslist": "📜 <b>Group members rights:</b>",
"on": "👤 <b>Now only admins can {}.</b>",
"off": "🤖 <b>Now all members can {}.</b>",
"status-on": "👤❕ <b>Only admins can {} here.</b>",
"status-off": "🤖❕ <b>All members can {} here.</b>",
"rights?!": "😔 <b>Error….</b>\nCode: <code>{}</code>",
"adminslist": "👥 <b>Group admins:</b>",
"loading": "🔄 <b>Loading….</b>",
'send-right': 'send messages',
'ib-right': 'use inline bots',
'media-right': 'send media',
'stickers-right': 'send stickers',
'gifs-right': 'send GIFs',
'games-right': 'send games',
'embed-right': 'send links preview',
'polls-right': 'send polls',
'info-right': 'change chat info',
'invite-right': 'invite users',
'pin-right': 'pin messages',
'addadmin-right': 'add admins',
'anonymous-right': 'send anonymous messages',
'ban-right': 'ban users',
'delete-right': 'delete messages',
'edit-right': 'edit messages',
'call-management-right': 'manage voice chats',
'is-banned': '🚫 <b>User is banned.</b>',
'is-left': '🚫 <b>User left the chat.</b>',
'is-admin': '👤 <b>User is admin.</b>',
'is-creator': '👤 <b>User is creator.</b>',
'default': '⭕ <b>User have default permissions.</b>',
}
strings_ru = {
"name": "Rechte",
"group?!": "👥 <b>Работает лишь в группах.</b>",
"rightslist": "📜 <b>Права участников группы:</b>",
"on": "👤 <b>Теперь лишь админы могут {}.</b>",
"off": "🤖 <b>Теперь все могут {}.</b>",
"status-on": "👤❕ <b>Здесь лишь админы могут {}.</b>",
"status-off": "🤖❕ <b>Здесь все могут {}.</b>",
"rights?!": "😔 <b>Ошибка…</b>\nКод: <code>{}</code>",
"adminslist": "👥 <b>Админы группы:</b>",
"loading": "🔄 <b>Загрузка…</b>",
'send-right': 'отправлять сообщения',
"_cls_doc": "Переключает и проверяет права.",
"_cmd_doc_switchsend": "Переключает права на отправку сообщений",
"_cmd_doc_checksend": "Проверяет права на отправку сообщений",
"_cmd_doc_checkib": "Проверяет права на использование инлайн-ботов.",
"_cmd_doc_switchib": "Переключает права на использование инлайн-ботов",
"_cmd_doc_switchmedia": "Переключает права на отправку медиа",
"_cmd_doc_checkmedia": "Проверяет права на отправку медиа",
"_cmd_doc_switchstickers": "Переключает права на отправку стикеров",
"_cmd_doc_checkstickers": "Проверяет права на отправку стикеров",
"_cmd_doc_switchgifs": "Переключает права на отправку GIF",
"_cmd_doc_checkgifs": "Проверяет права на отправку GIF",
"_cmd_doc_switchgames": "Переключает права на отправку игр",
"_cmd_doc_checkgames": "Проверяет права на отправку игр",
"_cmd_doc_switchembed": "Переключает права на отправку предпросмотра ссылок",
"_cmd_doc_checkembed": "Проверяет права на отправку предпросмотра ссылок",
"_cmd_doc_switchpolls": "Переключает права на отправку опросов",
"_cmd_doc_checkpolls": "Проверяет права на отправку опросов",
"_cmd_doc_switchinfo": "Переключает права на изменение информации чата",
"_cmd_doc_checkinfo": "Проверяет права на изменение информации чата",
"_cmd_doc_switchinvite": "Переключает права на приглашение пользователей",
"_cmd_doc_checkinvite": "Проверяет права на приглашение пользователей",
"_cmd_doc_switchpin": "Переключает права на закрепление сообщений",
"_cmd_doc_checkpin": "Проверяет права на закрепление сообщений",
"_cmd_doc_checkall": "Выдаёт список прав обычных учаcтников",
"_cmd_doc_checkadmins": "Выдаёт список админов",
'ib-right': 'использовать инлайн-ботов',
'media-right': 'отправлять медиа',
'stickers-right': 'отправлять стикеры',
'gifs-right': 'отправлять GIF',
'games-right': 'отправлять игры',
'embed-right': 'отправлять предпросмотр ссылок',
'polls-right': 'отправлять опросы',
'info-right': 'менять информацию о чате',
'invite-right': 'приглашать пользователей',
'pin-right': 'закреплять сообщения',
'addadmin-right': 'добавлять администраторов',
'anonymous-right': 'отправлять анонимные сообщения',
'ban-right': 'банить пользователей',
'delete-right': 'удалять сообщения',
'edit-right': 'редактировать сообщения',
'call-management-right': 'управлять звонками',
'is-banned': '🚫 <b>Пользователь забанен.</b>',
'is-left': '🚫 <b>Пользователь покинул чат.</b>',
'is-admin': '👤 <b>Пользователь — администратор.</b>',
'is-creator': '👤 <b>Пользователь — создатель.</b>',
'default': '⭕ <b>У пользователя стандартные права.</b>',
}
strings_de = {
"name": "Rechte",
"group?!": "👥 <b>Funktioniert nur in Gruppen.</b>",
"rightslist": "📜 <b>Gruppenmitgliedern Rechteliste:</b>",
"on": "👤 <b>Nun können nur Admins {}.</b>",
"off": "🤖 <b>Nun können alle {}.</b>",
"status-on": "👤❕ <b>Hier können nur Admins {}.</b>",
"status-off": "🤖❕ <b>Hier können alle {}.</b>",
"rights?!": "😔 <b>Fehler…</b>\nCode: <code>{}</code>",
"adminslist": "👥 <b>Adminsliste:</b>",
"loading": "🔄 <b>Wird geladen…</b>",
"_cls_doc": "Schaltet und überprüft Rechte.",
"_cmd_doc_switchsend": "Schaltet das Senden von Nachrichten",
"_cmd_doc_checksend": "Überprüft das Senden von Nachrichten",
"_cmd_doc_switchib": "Schaltet Rechte für Inline-Bots um",
"_cmd_doc_checkib": "Überprüft Rechte für Inline-Bots",
"_cmd_doc_switchmedia": "Schaltet Rechte für Medien um",
"_cmd_doc_checkmedia": "Überprüft Rechte für Medien",
"_cmd_doc_switchstickers": "Schaltet Rechte für Sticker um",
"_cmd_doc_checkstickers": "Überprüft Rechte für Sticker",
"_cmd_doc_switchgif": "Schaltet Rechte für GIF um",
"_cmd_doc_checkgif": "Überprüft Rechte für GIF",
"_cmd_doc_switchgames": "Schaltet Rechte für Spiele um",
"_cmd_doc_checkgames": "Überprüft Rechte für Spiele",
"_cmd_doc_switchembed": "Schaltet Rechte für Vorschau von Links um",
"_cmd_doc_checkembed": "Überprüft Rechte für Vorschau von Links",
"_cmd_doc_switchpolls": "Schaltet Rechte für Umfragen um",
"_cmd_doc_checkpolls": "Überprüft Rechte für Umfragen",
"_cmd_doc_switchinfo": "Schaltet Rechte für Info-Änderungen um",
"_cmd_doc_checkinfo": "Überprüft Rechte für Info-Änderungen",
"_cmd_doc_switchinvite": "Schaltet Rechte für Einladungen um",
"_cmd_doc_checkinvite": "Überprüft Rechte für Einladungen",
"_cmd_doc_switchpin": "Schaltet Rechte für das Anheften von Nachrichten um",
"_cmd_doc_checkpin": "Überprüft Rechte für das Anheften von Nachrichten",
"_cmd_doc_checkall": "Sendet eine List von alle Rechte des Benutzers",
"_cmd_doc_checkadmins": "Sendet eine Liste von allen Admins",
'ib-right': 'Inline-Bots verwenden',
'media-right': 'Medien senden',
'stickers-right': 'Sticker senden',
'gifs-right': 'GIF senden',
'games-right': 'Spiele senden',
'embed-right': 'Vorschau von Links senden',
'polls-right': 'Umfragen senden',
'info-right': 'Gruppeninformationen ändern',
'invite-right': 'Benutzer einladen',
'pin-right': 'Nachrichten anheften',
'addadmin-right': 'Admins hinzufügen',
'anonymous-right': 'Anonyme Nachrichten senden',
'ban-right': 'Benutzer bannen',
'delete-right': 'Nachrichten löschen',
'edit-right': 'Nachrichten bearbeiten',
'call-management-right': 'Anrufe verwalten',
'is-banned': '🚫 <b>Benutzer ist gebannt.</b>',
'is-left': '🚫 <b>Benutzer hat den Chat verlassen.</b>',
'is-admin': '👤 <b>Benutzer ist ein Admin.</b>',
'is-creator': '👤 <b>Benutzer ist der Inhaber.</b>',
'default': '⭕ <b>Benutzer hat Standardrechte.</b>',
}
async def switchibcmd(self, m: Message):
"""Switches inline bots using rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).send_inline:
try:
await m.client.edit_permissions(utils.get_chat_id(m), send_inline=False)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('on').format(self.strings('ib-right')))
else:
try:
await m.client.edit_permissions(utils.get_chat_id(m), send_inline=True)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('off').format(self.strings('ib-right')))
async def checkibcmd(self, m: Message):
"""Checks inline bots using rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).send_inline:
return await utils.answer(m, self.strings('status-off').format(self.strings('ib-right')))
else:
return await utils.answer(m, self.strings('status-on').format(self.strings('ib-right')))
async def switchsendcmd(self, m: Message):
"""Switches sending messages rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).send_messages:
try:
await m.client.edit_permissions(utils.get_chat_id(m), send_messages=False)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('on').format(self.strings('send-right')))
else:
try:
await m.client.edit_permissions(utils.get_chat_id(m), send_messages=True)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('off').format(self.strings('send-right')))
async def checksendcmd(self, m: Message):
"""Checks sending messages rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).send_messages:
return await utils.answer(m, self.strings('status-off').format(self.strings('send-right')))
else:
return await utils.answer(m, self.strings('status-on').format(self.strings('send-right')))
async def switchmediacmd(self, m: Message):
"""Switches media using rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).send_media:
try:
await m.client.edit_permissions(utils.get_chat_id(m), send_media=False)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('on'))
else:
try:
await m.client.edit_permissions(utils.get_chat_id(m), send_media=True)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('off'))
async def checkmediacmd(self, m: Message):
"""Checks media using rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).send_media:
return await utils.answer(m, self.strings('status-off').format(self.strings('media-right')))
else:
return await utils.answer(m, self.strings('status-on').format(self.strings('media-right')))
async def switchstickerscmd(self, m: Message):
"""Switches stickers using rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).send_stickers:
try:
await m.client.edit_permissions(utils.get_chat_id(m), send_stickers=False)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('on').format(self.strings('stickers-right')))
else:
try:
await m.client.edit_permissions(utils.get_chat_id(m), send_stickers=True)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('off').format(self.strings('stickers-right')))
async def checkstickerscmd(self, m: Message):
"""Checks stickers using rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).send_stickers:
return await utils.answer(m, self.strings('status-off').format(self.strings('stickers-right')))
else:
return await utils.answer(m, self.strings('status-on').format(self.strings('stickers-right')))
async def switchgifscmd(self, m: Message):
"""Switches gifs using rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).send_gifs:
try:
await m.client.edit_permissions(utils.get_chat_id(m), send_gifs=False)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('on').format(self.strings('gifs-right')))
else:
try:
await m.client.edit_permissions(utils.get_chat_id(m), send_gifs=True)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('off').format(self.strings('gifs-right')))
async def checkgifscmd(self, m: Message):
"""Checks gifs using rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).send_gifs:
return await utils.answer(m, self.strings('status-off').format(self.strings('gifs-right')))
else:
return await utils.answer(m, self.strings('status-on').format(self.strings('gifs-right')))
async def switchgamescmd(self, m: Message):
"""Switches games using rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).send_games:
try:
await m.client.edit_permissions(utils.get_chat_id(m), send_games=False)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('on').format(self.strings('games-right')))
else:
try:
await m.client.edit_permissions(utils.get_chat_id(m), send_games=True)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('off').format(self.strings('games-right')))
async def checkgamescmd(self, m: Message):
"""Checks games using rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).send_games:
return await utils.answer(m, self.strings('status-off').format(self.strings('games-right')))
else:
return await utils.answer(m, self.strings('status-on').format(self.strings('games-right')))
async def switchembedcmd(self, m: Message):
"""Switches links preview using rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).embed_links:
try:
await m.client.edit_permissions(utils.get_chat_id(m), embed_links=False)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('on').format(self.strings('embed-right')))
else:
try:
await m.client.edit_permissions(utils.get_chat_id(m), embed_links=True)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('off').format(self.strings('embed-right')))
async def checkembedcmd(self, m: Message):
"""Checks links preview using rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).embed_links:
return await utils.answer(m, self.strings('status-off').format(self.strings('embed-right')))
else:
return await utils.answer(m, self.strings('status-on').format(self.strings('embed-right')))
async def switchpollscmd(self, m: Message):
"""Switches polls using rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).send_polls:
try:
await m.client.edit_permissions(utils.get_chat_id(m), send_polls=False)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('on').format(self.strings('polls-right')))
else:
try:
await m.client.edit_permissions(utils.get_chat_id(m), send_polls=True)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('off').format(self.strings('polls-right')))
async def checkpollscmd(self, m: Message):
"""Checks polls using rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).send_polls:
return await utils.answer(m, self.strings('status-off').format(self.strings('polls-right')))
else:
return await utils.answer(m, self.strings('status-on').format(self.strings('polls-right')))
async def switchinfocmd(self, m: Message):
"""Switches info changing rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).change_info:
try:
await m.client.edit_permissions(utils.get_chat_id(m), change_info=False)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('on').format(self.strings('info-right')))
else:
try:
await m.client.edit_permissions(utils.get_chat_id(m), check_info=True)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('off').format(self.strings('info-right')))
async def checkinfocmd(self, m: Message):
"""Checks info changing rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).change_info:
return await utils.answer(m, self.strings('status-off').format(self.strings('info-right')))
else:
return await utils.answer(m, self.strings('status-on').format(self.strings('info-right')))
async def switchinvitecmd(self, m: Message):
"""Switches invite rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).invite_users:
try:
await m.client.edit_permissions(utils.get_chat_id(m), invite_users=False)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('on').format(self.strings('invite-right')))
else:
try:
await m.client.edit_permissions(utils.get_chat_id(m), invite_users=True)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('off').format(self.strings('invite-right')))
async def checkinvitecmd(self, m: Message):
"""Checks invite rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).invite_users:
return await utils.answer(m, self.strings('status-off').format(self.strings('invite-right')))
else:
return await utils.answer(m, self.strings('status-on').format(self.strings('invite-right')))
async def switchpincmd(self, m: Message):
"""Switches pin message rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).pin_messages:
try:
await m.client.edit_permissions(utils.get_chat_id(m), pin_messages=False)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('on').format(self.strings('pin-right')))
else:
try:
await m.client.edit_permissions(utils.get_chat_id(m), pin_messages=True)
except Exception as e:
return await utils.answer(m, self.strings('rights?!').format(e))
return await utils.answer(m, self.strings('off').format(self.strings('pin-right')))
async def checkpincmd(self, m: Message):
"""Checks pin message rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
if not (await m.client.get_permissions(utils.get_chat_id(m))).pin_messages:
return await utils.answer(m, self.strings('status-off').format(self.strings('pin-right')))
else:
return await utils.answer(m, self.strings('status-on').format(self.strings('pin-right')))
async def checkallcmd(self, m: Message):
"""Shows all rights."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
await utils.answer(m, self.strings('loading'))
listr = f"{self.strings('rightslist')}\n\n"
if (await m.client.get_permissions(utils.get_chat_id(m))).send_messages != True:
listr += '<i>' + self.strings('send-right').capitalize() + '</i>: ✅\n'
else:
listr += '<i>' + self.strings('send-right').capitalize() + '</i>: ❌\n'
if (await m.client.get_permissions(utils.get_chat_id(m))).send_media != True:
listr += '<i>' + self.strings('media-right').capitalize() + '</i>: ✅\n'
else:
listr += '<i>' + self.strings('media-right').capitalize() + '</i>: ❌\n'
if (await m.client.get_permissions(utils.get_chat_id(m))).send_stickers != True:
listr += '<i>' + self.strings('stickers-right').capitalize() + '</i>: ✅\n'
else:
listr += '<i>' + self.strings('stickers-right').capitalize() + '</i>: ❌\n'
if (await m.client.get_permissions(utils.get_chat_id(m))).send_gifs != True:
listr += '<i>' + self.strings('gifs-right').capitalize() + '</i>: ✅\n'
else:
listr += '<i>' + self.strings('gifs-right').capitalize() + '</i>: ❌\n'
if (await m.client.get_permissions(utils.get_chat_id(m))).send_games != True:
listr += '<i>' + self.strings('games-right').capitalize() + '</i>: ✅\n'
else:
listr += '<i>' + self.strings('games-right').capitalize() + '</i>: ❌\n'
if (await m.client.get_permissions(utils.get_chat_id(m))).send_inline != True:
listr += '<i>' + self.strings('ib-right').capitalize() + '</i>: ✅\n'
else:
listr += '<i>' + self.strings('ib-right').capitalize() + '</i>: ❌\n'
if (await m.client.get_permissions(utils.get_chat_id(m))).embed_links != True:
listr += '<i>' + self.strings('embed-right').capitalize() + '</i>: ✅\n'
else:
listr += '<i>' + self.strings('embed-right').capitalize() + '</i>: ❌\n'
if (await m.client.get_permissions(utils.get_chat_id(m))).send_polls != True:
listr += '<i>' + self.strings('polls-right').capitalize() + '</i>: ✅\n'
else:
listr += '<i>' + self.strings('polls-right').capitalize() + '</i>: ❌\n'
if (await m.client.get_permissions(utils.get_chat_id(m))).change_info != True:
listr += '<i>' + self.strings('info-right').capitalize() + '</i>: ✅\n'
else:
listr += '<i>' + self.strings('info-right').capitalize() + '</i>: ❌\n'
if (await m.client.get_permissions(utils.get_chat_id(m))).invite_users != True:
listr += '<i>' + self.strings('invite-right').capitalize() + '</i>: ✅\n'
else:
listr += '<i>' + self.strings('invite-right').capitalize() + '</i>: ❌\n'
if (await m.client.get_permissions(utils.get_chat_id(m))).pin_messages != True:
listr += '<i>' + self.strings('pin-right').capitalize() + '</i>: ✅\n'
else:
listr += '<i>' + self.strings('pin-right').capitalize() + '</i>: ❌\n'
return await utils.answer(m, listr)
async def checkadminscmd(self, m: Message):
"""Shows admins."""
if not isinstance(m.peer_id, PeerChannel):
return await utils.answer(m, self.strings('group?!'))
await utils.answer(m, self.strings('loading'))
listr = f"{self.strings('adminslist')}\n"
async for user in m.client.iter_participants(utils.get_chat_id(m), filter=ChannelParticipantsAdmins):
listr += f"\n<b>{user.first_name} {user.last_name if user.last_name is not None else ''} ({user.id})</b>\n"
if (await m.client.get_permissions(utils.get_chat_id(m), user.id)).is_creator == True:
listr += self.strings('is-creator') + '\n'
if (await m.client.get_permissions(utils.get_chat_id(m), user.id)).add_admins == True:
listr += '<i>' + self.strings('addadmin-right').capitalize() + '</i>: ✅\n'
else:
listr += '<i>' + self.strings('addadmin-right').capitalize() + '</i>: ❌\n'
if (await m.client.get_permissions(utils.get_chat_id(m), user.id)).ban_users == True:
listr += '<i>' + self.strings('ban-right').capitalize() + '</i>: ✅\n'
else:
listr += '<i>' + self.strings('ban-right').capitalize() + '</i>: ❌\n'
if (await m.client.get_permissions(utils.get_chat_id(m), user.id)).delete_messages == True:
listr += '<i>' + self.strings('delete-right').capitalize() + '</i>: ✅\n'
else:
listr += '<i>' + self.strings('delete-right').capitalize() + '</i>: ❌\n'
if (await m.client.get_permissions(utils.get_chat_id(m), user.id)).anonymous == True:
listr += '<i>' + self.strings('anonymous-right').capitalize() + '</i>: ✅\n'
else:
listr += '<i>' + self.strings('anonymous-right').capitalize() + '</i>: ❌\n'
if (await m.client.get_permissions(utils.get_chat_id(m), user.id)).manage_call == True:
listr += '<i>' + self.strings('call-management-right').capitalize() + '</i>: ✅\n'
else:
listr += '<i>' + self.strings('call-management-right').capitalize() + '</i>: ❌\n'
if (await m.client.get_permissions(utils.get_chat_id(m), user.id)).pin_messages == True:
listr += '<i>' + self.strings('pin-right').capitalize() + '</i>: ✅\n'
else:
listr += '<i>' + self.strings('pin-right').capitalize() + '</i>: ❌\n'
return await utils.answer(m, listr)

View File

@@ -0,0 +1,579 @@
# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0
# meta developer: @mm_mods
# meta pic: https://img.icons8.com/color/344/input-latin-letters-emoji.png
import contextlib
import logging
from telethon.tl.types import Message
from .. import loader, utils, translations
import requests
class YandexTranslator:
def __init__(self, start_lang: str = "auto", dest_lang: str = "en"):
self.start_lang = start_lang
self.dest_lang = dest_lang
def get_supported_languages(self, as_dict: bool = False) -> list | dict:
"""Returns a list of supported languages or a dictionary of supported languages with their codes."""
as_dict = 'true' if as_dict else 'false'
return requests.get(f'https://somekindofapp-1-j3340894.deta.app/get/ytranslate/supported?asd={as_dict}').json()['res']
def translate(self, text: str) -> str:
"""Translates the text into the specified language."""
return requests.post('https://somekindofapp-1-j3340894.deta.app/post/ytranslate/translate', json={'from_lang': self.start_lang,
'to_lang': self.dest_lang,
'text': text}).json()['res']
translator = YandexTranslator()
available_languages = translator.get_supported_languages(as_dict=True)
logger = logging.getLogger(__name__)
def get_key(dictionary: dict, needle: str) -> str:
return next((key for key, value in dictionary.items() if value == needle), None)
def get_num(lst: list, needle: str) -> int:
for i in range(len(lst)):
if lst[i] == needle:
return i
@loader.tds
class YaTranslateMod(loader.Module):
"""Guaranteed to be the most advanced and feature-rich message translation module based on Yandex Translate,
with many useful features (GoogleTrans, but rewritten). RR-version (Requirements Reduced)."""
strings = {
"name": "YandexTrans",
"load": "🔄 <b>Translating…</b>",
"load2": "🔎 <b>Searching… Please, wait.</b>",
"se-re": "📘 <b>Search result:</b>\n",
"cll": "🔄 <b>Configuring language list…</b>",
"args": "🚫 <b>No arguments, no reply…</b>",
"args2": "🚫 <b>No arguments…</b>",
"no_lang": "📕 <b>No such language!</b>",
"setted": "🔤 <b>Your main language is updated!</b>",
"silent": "🔇 <b>OK, I won't dispay translation message!</b>",
"unsilent": "🔊 <b>OK, I will dispay translation message!</b>",
"mark": "🔇 <b>OK, I won't dispay «translated» mark!</b>",
"unmark": "🔊 <b>OK, I will dispay «translated» mark!</b>",
"tr-ed": "<b>Translated:</b>",
"added": " <b>Chat added to autotranslate list!</b>",
"changed": "〰️ <b>Autotranslate configuration changed!</b>",
"deled": " <b>Chat deleted from autotranslate list!</b>",
"alheader": "📃 <b>Chats, in which autotranslate is activated:</b>",
"subscribe": "🖋️ <b>Now I'll keep original text while autotranslating.</b>",
"unsubscribe": (
"🖋️ <b>Now I won't keep original text while autotranslating.</b>"
),
"onboard-h": (
" <b>Some useful info about syntax</b>\n\n• .deflang {two-digit lang"
" code} sets your language to defined.\n• .markmode, .subsmode,"
" .silentmode, .atlist takes no arguments.\n• .autotranslate {start;finish}"
" takes argument only in such format. You may skip start language to define"
" it automatically. Also you may skip finish language to define it from"
" your default language.\n• .translate ({start;finish}) [text/reply] have"
" same rules while defining languages, as previous command. You may skip"
" block in brackets to translate text from autodefined language to your"
" default language.\n• .searchlang {two-digit language code/russion or"
" english language name} returns following language.\n\n In manual [s-t]"
" being used for unnecessary text block. {s-t} — for necessary."
),
"tt": "en",
"lapi": (
"📥 <b>Language names packet for <code>{}</code> succesfully installed!</b>"
),
"lapd": (
"📤 <b>Language names packet for <code>{}</code> succesfully deleted!</b>"
),
}
strings_de = {
"name": "YandexTrans",
"load": "🔄 <b>Übersetze…</b>",
"load2": "🔎 <b>Suchen… Bitte warten.</b>",
"se-re": "📘 <b>Gefunden:</b>\n",
"cll": "🔄 <b>Sprachlist konfiguriere…</b>",
"args": "🚫 <b>Kein Antwort, kein Argument…</b>",
"args2": "🚫 <b>Kein Argument…</b>",
"no_lang": "📕 <b>Ich kenne dieser Sprache nicht!</b>",
"setted": "🔤 <b>Deine Muttersprache aktualisiert!</b>",
"silent": "🔇 <b>Jetzt zeige ich Übersetzungnachricht nicht!</b>",
"unsilent": "🔊 <b>Jetzt zeige ich Übersetzungnachricht!</b>",
"mark": "🔇 <b>Jetzt ich zeige »Übersetzt« Merkzeichen nicht!</b>",
"unmark": "🔊 <b>Jetzt ich zeige »Übersetzt« Merkzeichen!</b>",
"tr-ed": "<b>Übersetzt:</b>",
"added": " <b>Chat zum Autoübersetzunglist hinzufügt!</b>",
"changed": "〰️ <b>Autoübersetzung Konfiguration geändert!</b>",
"deled": " <b>Chat aus Autoübersetzunglist entfernt!</b>",
"alheader": "📃 <b>Autoübersetzungchatlist:</b>",
"subscribe": "🖋️ <b>Jetzt zeige ich Originaltext bei Autoübersetzung.</b>",
"unsubscribe": (
"🖋️ <b>Jetzt zeige ich Originaltext bei Autoübersetzung nicht.</b>"
),
"onboard-h": (
" <b>Syntax-Leitfaden</b>\n\n• .deflang {zweistellig Sprachcode"
"} ersetze dein Muttersprache mit eingegebt.\n• .markmode,"
" .subsmode, .silentmode, .atlist kein Argumente benötigt.\n"
" .autotranslate {Ausgang;Ziel} benötigen Argumente in diesem Format."
" Wenn Ausgangsprache nicht eigegebt, er wird automatisch erkannt"
" jedes Mal. Wenn Zielsprache nicht eingegebt, es word von deiner Muttersprache definiert.\n"
" .translate [({Ausgang;Ziel})] {текст/ответ} haben desselben Sprachdefinierung Regeln."
" Du kannst Blok im Klammern nicht eingegeben"
" um von autoerkennt Sprache auf"
" deiner Muttersprache zu Übersetzen.\n• .searchlang {zweistellig Sprachcode/Sprachname an"
" Englisch, Russisch oder anders installierte Sprache gebe dir Sprachname/Sprachcode"
".\n\nIn Leitfaden [etwas] ist unbenötigt Textblok."
" {etwas} — benötigt."
),
"tt": "de",
"_cls_doc": "Garantiert das fortschrittlichste und funktionsreichste Nachrichtenübersetzungsmodul auf Basis von"
" Yandex Translate mit vielen nützlichen Funktionen (geändert Version von GoogleTrans). RR-Version (kein Abhängigkeiten).",
"lapi": "📥 <b>Sprachesuchpaket für <code>{}</code> Sprache erfolgreich installiert!</b>",
"lapd": "📤 <b>Sprachesuchpaket für <code>{}</code> Sprache erfolgreich deinstalliert!</b>",
'_cmd_doc_yonboardh': 'Syntaxanleitung.',
'_cmd_doc_ydllap': 'Ermöglicht die Suche in der eingegebenen Sprache, nachdem die Liste erstellt wurde.',
'_cmd_doc_ydellap': 'Entfernt das Sprachesuchpaket',
'_cmd_doc_yautotranslate': 'Aktiviert die Autoübersetzung in diesem Chat. Lesen Sie die Hilfe von hier.',
'_cmd_doc_yatlist': 'Liste der automatisch übersetzten Chats und der dort verwendeten Sprachen',
'_cmd_doc_ydeflang': 'Legt die Muttersprache fest.',
'_cmd_doc_ysearchlang': 'Sucht die Sprache nach dem Namen in einer der eingestellten Sprachen — standardmäßig '
'Englisch und Russisch — oder Sprachcode.',
'_cmd_doc_ymarkmode': 'Aktiviert/deaktiviert die Markierung »Übersetzt«',
'_cmd_doc_ysubsmode': 'Aktiviert/deaktiviert die Textspeicherung bei der automatischen Übersetzung',
'_cmd_doc_ysilentmode': 'Aktiviert/deaktiviert die Anzeige der Fangmeldung beim Übersetzen.',
'_cmd_doc_ytranslate': 'Wie unerwartet, übersetzt. Verwenden Sie (start;final), um die zu Übersetzung Sprachen '
'festzulegen. Verwenden Sie die Hilfe für weitere Informationen.'
}
strings_ru = {
"name": "YandexTrans",
"load": "🔄 <b>Перевожу…</b>",
"load2": "🔎 <b>Ищу… Ожидайте.</b>",
"se-re": "📘 <b>Найдено:</b>\n",
"cll": "🔄 <b>Конфигурирую список языков…</b>",
"args": "🚫 <b>Ни аргумента, ни ответа…</b>",
"args2": "🚫 <b>Нет аргумента…</b>",
"no_lang": "📕 <b>Я не знаю такого языка!</b>",
"setted": "🔤 <b>Ваш основной язык обновлён!</b>",
"silent": "🔇 <b>Хорошо, теперь не отображаю сообщение о переводе!</b>",
"unsilent": "🔊 <b>Хорошо, теперь отображаю сообщение о переводе!</b>",
"mark": "🔇 <b>Хорошо, теперь не отображаю пометку «переведено»!</b>",
"unmark": "🔊 <b>Хорошо, теперь отображаю пометку «переведено»!</b>",
"tr-ed": "<b>Переведено:</b>",
"added": " <b>Чат добавлен в список автоперевода!</b>",
"changed": "〰️ <b>Конфигурация автоперевода изменена!</b>",
"deled": " <b>Чат убран из списка автоперевода!</b>",
"alheader": "📃 <b>Список чатов, в которых активен автоперевод:</b>",
"subscribe": "🖋️ <b>Теперь я сохраняю оригинальный текст при автопереводе.</b>",
"unsubscribe": (
"🖋️ <b>Теперь я не сохраняю оригинальный текст при автопереводе.</b>"
),
"onboard-h": (
" <b>Руководство по синтаксису</b>\n\n• .deflang {двузначный языковой"
" код} установит ваш язык по умолчанию на введённый.\n• .markmode,"
" .subsmode, .silentmode, .atlist не принимают аргументов.\n"
" .autotranslate {старт;финал} принимает аргументы только в таком формате."
" При пропуске начального языка, он будет определяться автоматически каждый"
" раз. Финальный язык при пропуске его будет взят из языка по умолчанию.\n"
" .translate [({старт;финал})] {текст/ответ} имеет те же правила по"
" обозначению языков, что и прошлая команда. Можно пропустить блок в"
" круглых скобках чтобы перевести с автопереведённого языка на язык по"
" умолчанию.\n• .searchlang {двузначный языковой код/название языка на"
" русском или английском} выдаёт язык, соотвтетствующий названию или"
" коду.\n\nВ руководстве [что-то] обозначает необязательный текстовый блок."
" {что-то} — обязательный."
),
"tt": "ру",
"lapi": "📥 <b>Языковой пакет для языка <code>{}</code> успешно установлен!</b>",
"lapd": "📤 <b>Языковой пакет для языка <code>{}</code> успешно удалён!</b>",
'_cmd_doc_yonboardh': 'Справка по синтаксису.',
'_cmd_doc_ydllap': 'Даёт возможность после построения списка искать на введённом языке.',
'_cmd_doc_ydellap': 'Удаляет языковой пакет для поиска.',
'_cmd_doc_yautotranslate': 'Включает автоперевод в данном чате. Дальше — читай справку.',
'_cmd_doc_yatlist': 'Список чатов с автопереводом и языков, там используемых.',
'_cmd_doc_ydeflang': 'Устанавливает язык по умолчанию.',
'_cmd_doc_ysearchlang': 'Ищет язык по названию на одном из установленных языков — по умолчанию '
'английский и русский.',
'_cmd_doc_ymarkmode': 'Включает/выключает пометку «Переведено».',
'_cmd_doc_ysubsmode': 'Включает/выключает сохранение текста при автопереводе.',
'_cmd_doc_ysilentmode': 'Включает/выключает показ сообщения загрузки при переводе.',
'_cmd_doc_ytranslate': 'Как неожиданно — переводит. Используй (start;final) чтоб установить языки для перевода. '
'Для дальнейшей информации используй справку.',
"_cls_doc": "Гарантированно самый продвинутый и многофункциональный модуль для перевода сообщений, основанный "
"на Yandex Translate, с множеством полезных функций. (переписанный GoogleTrans) RR-версия (без зависимостей).",
}
async def client_ready(self, client, db):
self._client = client
self._db = db
if not self.get("deflang", False):
self.set("deflang", "en")
if not self.get("silence", False):
self.set("silence", False)
if not self.get("mark", False):
self.set("mark", True)
if not self.get("s-script", False):
self.set("s-script", False)
if not self.get("tr_cha", False):
self.set("tr_cha", {})
if not self.get("addla", False):
self.set("addla", [])
async def yautotranslatecmd(self, message: Message):
"""Use language code with this command to add this chat to autotranslate list."""
lang = utils.get_args_raw(message)
if (str(utils.get_chat_id(message)) in self.get("tr_cha")) and not lang:
tr_cha = self.get("tr_cha")
del tr_cha[str(utils.get_chat_id(message))]
self.set("tr_cha", tr_cha)
await utils.answer(message, self.strings("deled"))
return
if ";" not in lang:
stla = "auto"
fila = self.get("deflang")
else:
stla, fila = lang.split(";", 1)
stla, fila = stla.strip(), fila.strip()
if not stla:
stla = "auto"
if not fila:
fila = self.get("deflang")
if fila not in available_languages.values():
await utils.answer(message, self.strings("no_lang"))
return
if (stla != "auto") and (stla not in available_languages.values()):
await utils.answer(message, self.strings("no_lang"))
return
lang = f"{stla};{fila}"
tr_cha = tco = self.get("tr_cha")
tr_cha.update({str(utils.get_chat_id(message)): lang})
self.set("tr_cha", tr_cha)
if str(utils.get_chat_id(message)) not in tco.keys():
await utils.answer(message, self.strings("added"))
else:
await utils.answer(message, self.strings("changed"))
async def yonboardhcmd(self, m: Message):
"""Syntax manual."""
await utils.answer(m, self.strings("onboard-h"))
async def ydllapcmd(self, m: Message):
"""Downloads languages name pack for entered language. Allows to search languages through .searchlang on your own language."""
lang = utils.get_args_raw(m)
if lang == "":
return await utils.answer(m, self.strings("args2"))
if lang not in available_languages.values():
await utils.answer(m, self.strings("nolang"))
if not self.get(f"{lang}langdb", False):
await utils.answer(m, self.strings("cll"))
rld = {}
langword = (
YandexTranslator("en", lang)
.translate("a language")
.casefold()
)
if " " in langword:
langword = (
YandexTranslator("en", lang)
.translate("language")
.casefold()
)
for z in available_languages:
ru_n = f"{z} language"
ru_n = (
YandexTranslator("en", lang)
.translate(ru_n)
.casefold()
.replace(langword, "")
)
if ru_n[-1] == " ":
ru_n = ru_n[:-1]
if ru_n[-1] == "-":
ru_n = ru_n[:-1]
if ru_n[0] == " ":
ru_n = ru_n.replace(" ", "", 1)
if ru_n[0] == "-":
ru_n = ru_n.replace("-", "", 1)
if (lang == 'de') and (ru_n[-1] == 'e'):
ru_n = ru_n[:-1]
rld[ru_n.casefold()] = available_languages[z]
self.set(f"{lang}langdb", rld)
addla = self.get("addla")
addla.append(lang)
addla = self.set("addla", addla)
return await utils.answer(m, self.strings("lapi").format(lang))
async def ydellapcmd(self, m: Message):
"""Deletes custom language pack."""
lang = utils.get_args_raw(m)
if lang == "":
return await utils.answer(m, self.strings("args2"))
if lang not in self.get("addla"):
await utils.answer(m, self.strings("no_lang"))
try:
del self._db[self.__class__.__name__][f"{lang}langdb"]
except Exception as e:
return await utils.answer(m, self.strings("no_lang"))
addla = self.get("addla")
del addla[get_num(addla, lang)]
addla = self.set("addla", addla)
return await utils.answer(m, self.strings("lapd").format(lang))
async def ydeflangcmd(self, message: Message):
"""Use language code with this command to switch basic translation language."""
lang = utils.get_args_raw(message)
if lang not in available_languages.values():
await utils.answer(message, self.strings("nolang"))
else:
self.set("deflang", lang)
await utils.answer(message, self.strings("setted"))
async def ysearchlangcmd(self, m: Message):
"""Searching language by code or name (RU and EN names avaliable — if you downloaded others, you may use them; first usage takes some time to configure database)."""
query = utils.get_args_raw(m)
if query == "":
return await utils.answer(m, self.strings("args2"))
if not self.get("rulangdb", False):
await utils.answer(m, self.strings("cll"))
rld = {}
for z in available_languages:
ru_n = f"{z} language"
ru_n = (
YandexTranslator("en", "ru")
.translate(ru_n)
.replace("язык", "")
.replace(" ", "")
)
rld[ru_n] = available_languages[z]
self.set("rulangdb", rld)
rld = self.get("rulangdb")
for x in range(len(self.get("addla"))):
try:
res = self.get(f'{self.get("addla")[x]}langdb')[query]
return await utils.answer(
m,
f'{self.strings("se-re")}<code>{query}</code> ->'
f" <code>{res}</code>",
)
except Exception:
continue
try:
res = available_languages[query]
except Exception:
try:
res = rld[query]
except Exception:
if self.strings("tt") == "ру":
res = get_key(rld, query)
elif self.strings("tt") == "de":
if not self.get("delangdb", False):
try:
res = get_key(available_languages,
query) + ' (du kannst Deutsche Namen durch ".dllap de" installieren)'
except:
return await utils.answer(m, self.strings("no_lang"))
else:
try:
res = get_key(self.get('delangdb'), query)
except:
return await utils.answer(m, self.strings("no_lang"))
else:
res = get_key(available_languages, query)
if res is None:
return await utils.answer(m, self.strings("no_lang"))
return await utils.answer(
m, f'{self.strings("se-re")}<code>{query}</code> -> <code>{res}</code>'
)
async def ysilentmodecmd(self, message):
"""Use this command to switch between silent/unsilent mode."""
if self.get("silence"):
self.set("silence", False)
await utils.answer(message, self.strings("unsilent"))
else:
self.set("silence", True)
await utils.answer(message, self.strings("silent"))
async def ysubsmodecmd(self, message):
"""Use this command to switch autotranslate subscription mode."""
if self.get("s-script"):
self.set("s-script", False)
await utils.answer(message, self.strings("unsubscribe"))
else:
self.set("s-script", True)
await utils.answer(message, self.strings("subscribe"))
async def ymarkmodecmd(self, message):
"""Use this command to switch between showing/unshowing «translated» mark."""
if self.get("mark"):
self.set("mark", False)
await utils.answer(message, self.strings("mark"))
else:
self.set("mark", True)
await utils.answer(message, self.strings("unmark"))
async def yatlistcmd(self, message: Message):
"""Sends a list of chats, in which autotranslate is turned on."""
laco = self.strings('tt')
autotranslate = self.get("tr_cha")
alist = self.strings("alheader") + "\n"
avlad = YandexTranslator().get_supported_languages(as_dict=True)
for i in autotranslate.keys():
st_la, fi_la = autotranslate[i].split(";")
if st_la == "auto":
if laco == "ru":
st_la = "авто"
elif laco == "ru":
st_la = f"{get_key(avlad, st_la)} language"
st_la = (
YandexTranslator("en", "ru")
.translate(st_la)
.replace("язык", "")
)
elif (laco == 'de') and (self.get('delangdb')):
st_la = get_key(self.get('delangdb'), st_la)
else:
st_la = get_key(avlad, st_la)
if laco == "ru":
fi_la = f"{get_key(avlad, fi_la)} language"
fi_la = (
YandexTranslator("en", "ru")
.translate(fi_la)
.replace("язык", "")
)
elif (laco == 'de') and (self.get('delangdb')):
fi_la = get_key(self.get('delangdb'), fi_la)
else:
fi_la = get_key(avlad, fi_la)
type_ = (
"user"
if getattr(await self._client.get_entity(int(i)), "first_name", False)
else "chat"
)
alist += (
f'<a href="tg://openmessage?{type_}_id={i.replace("-100", "")}">id{i.replace("-100", "")}</a>:'
f" {st_la} » {fi_la}" + "\n"
)
if (laco == 'de') and (not self.get('delangdb', False)):
alist += '\nDu kannst Deutsche Namen durch <code>.dllap de</code> installieren.'
await utils.answer(message, alist)
async def ytranslatecmd(self, message: Message):
"""In fact, it translates. Use (start;final) to mark the start and end language of the translation.
Leave the start language blank to define it automatically."""
reply = await message.get_reply_message()
prompt = utils.get_args_raw(message)
if not prompt and reply is None:
await utils.answer(message, self.strings("args"))
if prompt and prompt.startswith("("):
lafo, prompt = prompt.split(")", 1)
if ";" not in lafo:
prompt = f"({lafo}){prompt}"
stal = "auto"
finl = self.get("deflang")
else:
lafo = lafo.replace("(", "", 1)
stal, finl = lafo.split(";", 1)
stal, finl = stal.strip(), finl.strip()
if not stal:
stal = "auto"
if not finl:
finl = self.get("deflang")
if (
(stal or finl) not in available_languages.values()
and (stal != "auto")
and (finl not in available_languages.values())
):
await utils.answer(
message,
self.strings("no_lang") + "\n" + stal + " " + finl,
)
return
else:
stal = "auto"
finl = self.get("deflang")
if not self.get("silence"):
await utils.answer(message, self.strings("load"))
if not prompt:
if reply is None:
await utils.answer(message, self.strings("args"))
return
else:
prompt = reply.raw_text
translator = YandexTranslator(stal, finl)
translated = translator.translate(prompt)
if self.get("mark"):
translated = f'{self.strings("tr-ed")}\n{translated}'
await utils.answer(message, translated)
async def watcher(self, message: Message):
pr = self.get_prefix()
if not message.text:
return
if not message.out:
return
if message.text[0] in ['/', pr]:
return
if str(utils.get_chat_id(message)) not in self.get("tr_cha").keys():
return
stla, fila = self.get("tr_cha")[str(utils.get_chat_id(message))].split(";")
tren = YandexTranslator(stla, fila)
translated = "".join(
[
await utils.run_sync(lambda: tren.translate(chunk))
for chunk in utils.chunks(message.raw_text, 512)
]
)
if translated == message.raw_text:
return
if self.get("s-script"):
translated = (
message.raw_text + "\n\n" + self.strings("tr-ed") + "\n\n" + translated
)
with contextlib.suppress(Exception):
await utils.answer(message, translated)

View File

@@ -0,0 +1,510 @@
# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0
# meta pic: https://img.icons8.com/stickers/344/block.png
# meta developer: @mm_mods
__version__ = "1.0.0"
from hikka import loader, utils
from telethon.tl.patched import Message
import logging
from datetime import datetime, timedelta
logger = logging.getLogger(__name__)
# noinspection PyCallingNonCallable
@loader.tds
class ASAPMod(loader.Module):
"""Advanced Sending Automatisation Program"""
strings = {
'name': 'ASAP',
'args?!': '🟥 <b>Arguments needed!</b>',
'incorrecttime': '🟥 <b>Incorrect time!</b>\n{example}',
'taskslist': '📄 <b>Tasks list:</b>\n\n',
'task': '<i>Task <code>{x}</code>:</i> send <code>{text}</code> to <code>{address}</code> ({at_time}).\n',
'tasklistempty': '🟨 <b>Tasks list is empty!</b>',
'taskadded': '🟩 <b>Task added!</b>\nNext execution: <code>{at_time}</code>, task number: <code>{x}</code>',
'taskremoved': '🟩 <b>Task removed!</b>',
'tasknotfound': '🟥 <b>Task not found!</b>',
'tasklistcleared': '🟩 <b>Tasks list cleared!</b>',
'taskpaused': '🟩 <b>Task paused!</b>',
'allpaused': '🟩 <b>All tasks paused!</b>',
'taskresumed': '🟩 <b>Task resumed!</b>',
'taskpretimeexecuted': '🟩 <b>Task executed!</b>\nNext execution: <code>{at_time}</code>',
'taskreplanned': '🟩 <b>Task replanned!</b>\nNext execution: <code>{at_time}</code>',
'defaultintervalset': '🟩 <b>Default interval set!</b>\n{example}',
'incorrectinterval': '🟥 <b>Incorrect interval!</b>',
'timeformatexample': '🟦 <i>Time format example:</i> <code>2h</code> — 2 hours, '
'<code>1d 2h 30m</code> — 1 day, 2 hours and 30 minutes, '
'<code>20s</code> — 20 seconds.',
'tzset': '🟩 <b>Timezone set!</b>',
'incorrecttz': '🟥 <b>Incorrect timezone!</b>',
'safetyreasonerror': '🟨 <b>For safety reasons, you can\'t set such short interval!</b>',
}
strings_ru = {
'name': 'ASAP',
'_cls_doc': 'Продвинутая программа автоматизации отправки сообщений',
'args?!': '🟥 <b>Нужны аргументы!</b>',
'incorrecttime': '🟥 <b>Неверное время!</b>\n{example}',
'taskslist': '📄 <b>Список задач:</b>\n\n',
'task': '<i>Задача <code>{x}</code>:</i> отправить <code>{text}</code> на <code>{address}</code> ({at_time}).'
'\n',
'tasklistempty': '🟨 <b>Список задач пуст!</b>',
'taskadded': '🟩 <b>Задача добавлена!</b>\nСледующее выполнение: <code>{at_time}</code>, номер задачи: <code>{'
'x}</code>',
'taskremoved': '🟩 <b>Задача удалена!</b>',
'tasknotfound': '🟩 <b>Задача не найдена!</b>',
'tasklistcleared': '🟩 <b>Список задач очищен!</b>',
'taskpaused': '🟩 <b>Задача приостановлена!</b>',
'allpaused': '🟩 <b>Все задачи приостановлены!</b>',
'taskresumed': '🟩 <b>Задача возобновлена!</b>',
'taskpretimeexecuted': '🟩 <b>Задача выполнена!</b>\nСледующее выполнение: <code>{at_time}</code>',
'taskreplanned': '🟩 <b>Задача перепланирована!</b>\nСледующее выполнение: <code>{at_time}</code>',
'defaultintervalset': '🟩 <b>Интервал по умолчанию установлен!</b>',
'incorrectinterval': '🟥 <b>Неверный интервал!</b>\n{example}',
'timeformatexample': '🟦 <i>Пример формата времени:</i> <code>2h</code> — 2 часа, '
'<code>1d 2h 30m</code> — 1 день, 2 часа и 30 минут, '
'<code>20s</code> — 20 секунд.',
'tzset': '🟩 <b>Часовой пояс установлен!</b>',
'incorrecttz': '🟥 <b>Неверный часовой пояс!</b>',
'safetyreasonerror': '🟨 <b>По соображениям безопасности вы не можете установить такой короткий интервал!</b>',
}
strings_de = {
'name': 'ASAP',
'_cls_doc': 'Fortgeschrittenes Programm zur Automatisierung des Nachrichtenversands',
'args?!': '🟥 <b>Argumente benötigt!</b>',
'incorrecttime': '🟥 <b>Falsche Zeit!</b>\n{example}',
'taskslist': '📄 <b>Aufgabenliste:</b>\n\n',
'task': '<i>Aufgabe <code>{x}</code>:</i> senden <code>{text}</code> zu <code>{address}</code> ({at_time}).\n',
'tasklistempty': '🟨 <b>Aufgabenliste ist leer!</b>',
'taskadded': '🟩 <b>Aufgabe hinzugefügt!</b>\nNächste Ausführung: <code>{at_time}</code>, '
'Aufgabennummer: <code>{x}</code>',
'taskremoved': '🟩 <b>Aufgabe entfernt!</b>',
'tasknotfound': '🟩 <b>Aufgabe nicht gefunden!</b>',
'tasklistcleared': '🟩 <b>Aufgabenliste gelöscht!</b>',
'taskpaused': '🟩 <b>Aufgabe pausiert!</b>',
'allpaused': '🟩 <b>Alle Aufgaben pausiert!</b>',
'taskresumed': '🟩 <b>Aufgabe fortgesetzt!</b>',
'taskpretimeexecuted': '🟩 <b>Aufgabe ausgeführt!</b>\nNächste Ausführung: <code>{at_time}</code>',
'taskreplanned': '🟩 <b>Aufgabe neu geplant!</b>\nNächste Ausführung: <code>{at_time}</code>',
'defaultintervalset': '🟩 <b>Standardintervall gesetzt!</b>',
'incorrectinterval': '🟥 <b>Falsches Intervall!</b>\n{example}',
'timeformatexample': '🟦 <i>Beispiel für das Zeitformat:</i> <code>2h</code> — 2 Stunden, '
'<code>1d 2h 30m</code> — 1 Tag, 2 Stunden und 30 Minuten, '
'<code>20s</code> — 20 Sekunden.',
'tzset': '🟩 <b>Zeitzone gesetzt!</b>',
'incorrecttz': '🟥 <b>Falsche Zeitzone!</b>',
'safetyreasonerror': '🟨 <b>Aus Sicherheitsgründen können Sie kein so kurzes Intervall festlegen!</b>',
}
async def client_ready(self):
if not self.get('default_interval'):
self.set('default_interval', '2h')
if not self.get('tasks'):
self.set('tasks', {})
if not self.get('tz'):
self.set('tz', 0)
@loader.loop(interval=1, autostart=True)
async def _run_tasks(self):
tasks = self.get('tasks')
if not tasks:
return
for k, task in tasks.items():
if datetime.strptime(task['next_execution'], '%d.%m.%Y %H:%M:%S') <= datetime.now():
await self._run_task(task, k)
@staticmethod
def validate_time(time: str) -> bool:
"""
Validates the time.
:param time: time to validate.
:return: if time is valid or not.
"""
if not time:
return False
args = time.split()
for arg in args:
if not arg[:-1].isdigit():
return False
if arg[-1] not in ['s', 'm', 'h', 'd']:
return False
return True
@staticmethod
def convert_time(time: str) -> timedelta:
"""
Converts time to timedelta.
:param time: time to convert.
:return: timedelta.
"""
args = time.split()
res = timedelta()
for arg in args:
try:
if arg[-1] == 's':
res += timedelta(seconds=int(arg[:-1]))
elif arg[-1] == 'm':
res += timedelta(minutes=int(arg[:-1]))
elif arg[-1] == 'h':
res += timedelta(hours=int(arg[:-1]))
elif arg[-1] == 'd':
res += timedelta(days=int(arg[:-1]))
except ValueError:
pass
return res
@loader.command(
'ataskadd',
ru_doc='Добавить задачу в список задач.\nИспользование: .ataskadd <текст>\n[время]\n[адресат]',
de_doc='Fügen Sie eine Aufgabe zur Aufgabenliste hinzu.\nVerwendung: .ataskadd <Text>\n[Zeit]\n[Empfänger]',
)
async def ataskaddcmd(self, m: Message):
"""Add a task to the list of tasks.
Usage: .ataskadd <text>
[time]
[target]"""
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings('args?!'))
args = args.split('\n')
if len(args) == 2:
interval = args[1]
address = m.chat_id
elif len(args) == 3:
interval = args[1]
address = args[2]
else:
interval = self.get('default_interval')
address = m.chat_id
if not self.validate_time(interval):
return await utils.answer(m, self.strings('incorrecttime'))
if self.convert_time(interval) < timedelta(seconds=10):
return await utils.answer(m, self.strings('safetyreasonerror'))
task = {
'text': args[0],
'interval': interval,
'address': address,
'paused': False,
'next_execution': (datetime.now() + self.convert_time(interval)).strftime('%d.%m.%Y %H:%M:%S'),
}
tasks = self.get('tasks')
x = len(tasks) + 1
tasks[str(x)] = task
self.set('tasks', tasks)
await utils.answer(
m, self.strings('taskadded').format(
at_time=task['next_execution'],
x=x
)
)
@loader.command(
'ataskremove',
ru_doc='Удалить задачу из списка задач.\nИспользование: .ataskremove <номер>',
de_doc='Entfernen Sie eine Aufgabe aus der Aufgabenliste.\nVerwendung: .ataskremove <Nummer>',
)
async def ataskremovecmd(self, m: Message):
"""Remove a task from the list of tasks.
Usage: .ataskremove <number>"""
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings('args?!'))
try:
x = int(args)
except ValueError:
return await utils.answer(m, self.strings('args?!'))
x = str(x)
tasks = self.get('tasks')
if x not in tasks:
return await utils.answer(m, self.strings('tasknotfound'))
del tasks[x]
self.set('tasks', tasks)
await utils.answer(m, self.strings('taskremoved'))
@loader.command(
'atasklist',
ru_doc='Показать список задач.',
de_doc='Zeigt die Liste der Aufgaben an.',
)
async def atasklistcmd(self, m: Message):
"""Show the list of tasks."""
tasks = self.get('tasks')
if not tasks:
return await utils.answer(m, self.strings('tasklistempty'))
res = self.strings('taskslist')
for k, task in tasks.items():
res += self.strings('task').format(
x=k if not task['paused'] else f'</code><b><s>{k}</s></b><code>',
text=task['text'],
address=task['address'],
at_time=datetime.strptime(task['next_execution'], '%d.%m.%Y %H:%M:%S') + timedelta(hours=self.get('tz'))
)
await utils.answer(m, res)
@loader.command(
'ataskclear',
ru_doc='Очистить список задач.',
de_doc='Löschen Sie die Liste der Aufgaben.',
)
async def ataskclearcmd(self, m: Message):
"""Clear the list of tasks."""
self.set('tasks', {})
await utils.answer(m, self.strings('tasklistcleared'))
@loader.command(
'ataskpause',
ru_doc='Приостановить задачу.\nИспользование: .ataskpause <номер>\nБез аргументов — приостановить все задачи.',
de_doc='Aufgabe pausieren.\nVerwendung: .ataskpause <Nummer>\nOhne Argumente - alle Aufgaben pausieren.',
)
async def ataskpausecmd(self, m: Message):
"""Pause a task.
Usage: .ataskpause <number>
If no arguments — pause all tasks."""
args = utils.get_args_raw(m)
if not args:
tasks = self.get('tasks')
for k, task in tasks.items():
task['paused'] = True
tasks[k] = task
self.set('tasks', tasks)
return await utils.answer(m, self.strings('taskpaused'))
try:
x = int(args)
except ValueError:
return await utils.answer(m, self.strings('args?!'))
x = str(x)
tasks = self.get('tasks')
if x not in tasks:
return await utils.answer(m, self.strings('tasknotfound'))
tasks[x]['paused'] = True
self.set('tasks', tasks)
await utils.answer(m, self.strings('taskpaused'))
@loader.command(
'ataskresume',
ru_doc='Возобновить задачу.\nИспользование: .ataskresume <номер>',
de_doc='Aufgabe fortsetzen.\nVerwendung: .ataskresume <Nummer>',
)
async def ataskresumecmd(self, m: Message):
"""Resume a task.
Usage: .ataskresume <number>"""
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings('args?!'))
try:
x = int(args)
except ValueError:
return await utils.answer(m, self.strings('args?!'))
tasks = self.get('tasks')
if x > len(tasks):
return await utils.answer(m, self.strings('tasknotfound'))
tasks[x - 1]['paused'] = False
self.set('tasks', tasks)
await utils.answer(m, self.strings('taskresumed'))
@loader.command(
'ataskexec',
ru_doc='Выполнить задачу сейчас и перепланировать согласно интервалу.\nИспользование: .ataskexec <номер>',
de_doc='Führen Sie die Aufgabe jetzt aus und planen Sie sie entsprechend dem Intervall neu.\nVerwendung: '
'.ataskexec <Nummer>',
)
async def ataskexeccmd(self, m: Message):
"""Execute a task right now and replan according to the interval.
Usage: .ataskexec <number>"""
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings('args?!'))
try:
x = int(args)
except ValueError:
return await utils.answer(m, self.strings('args?!'))
x = str(x)
tasks = self.get('tasks')
if x not in tasks:
return await utils.answer(m, self.strings('tasknotfound'))
task = tasks[x]
if task['paused']:
return await utils.answer(m, self.strings('taskpaused'))
task['next_execution'] = datetime.now() + self.convert_time(task['interval'])
self.set('tasks', tasks)
await utils.answer(
m, self.strings('taskpretimeexecuted').format(
at_time=datetime.strptime(task['next_execution'], '%d.%m.%Y %H:%M:%S') + timedelta(hours=self.get('tz'))
)
)
await self._run_task(task, x)
@loader.command(
'ataskreplan',
ru_doc='Изменить интервал задачи.\nИспользование: .ataskreplan <номер> <время>',
de_doc='Ändern Sie das Intervall der Aufgabe.\nVerwendung: .ataskreplan <Nummer> <Zeit>',
)
async def ataskreplancmd(self, m: Message):
"""Change the interval of the task.
Usage: .ataskreplan <number>"""
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings('args?!'))
args = args.split(maxsplit=1)
x, time = args[0], args[1]
tasks = self.get('tasks')
if x not in tasks:
return await utils.answer(m, self.strings('tasknotfound'))
task = tasks[x]
if not self.validate_time(time):
return await utils.answer(m, self.strings('incorrecttime'))
task['interval'] = time
if task['paused']:
return await utils.answer(m, self.strings('taskpaused'))
task['next_execution'] = (datetime.now() + self.convert_time(task['interval'])).strftime('%d.%m.%Y %H:%M:%S')
tasks[x] = task
self.set('tasks', tasks)
await utils.answer(
m, self.strings('taskreplanned').format(
at_time=datetime.strptime(task['next_execution'], '%d.%m.%Y %H:%M:%S') + timedelta(hours=self.get('tz'))
)
)
@loader.command(
'adeftint',
ru_doc='Установить интервал по умолчанию.\nИспользование: .adeftint <время>',
de_doc='Setzen Sie das Standardintervall.\nVerwendung: .adeftint <Zeit>',
)
async def adeftintcmd(self, m: Message):
"""Set the default interval.
Usage: .ataskdeftint <time>"""
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings('args?!'))
if not self.validate_time(args):
return await utils.answer(m, self.strings('incorrectinterval'))
self.set('default_interval', args)
await utils.answer(
m, self.strings('defaultintervalset').format(
example=self.strings('timeformatexample')
)
)
@loader.command(
'atz',
ru_doc='Явно установить часовой пояс, если время отображается неверно.\nИспользование: .atz <часовой пояс>',
de_doc='Legen Sie die Zeitzone explizit fest, wenn die Zeit falsch angezeigt wird.\nVerwendung: '
'.atz <Zeitzone>',
)
async def atzcmd(self, m: Message):
"""Set the timezone explicitly if time displayed wrong.
Usage: .atz <timezone>"""
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings('args?!'))
try:
tz = int(args)
except ValueError:
try:
tz = float(args)
except ValueError:
return await utils.answer(m, self.strings('incorrecttz'))
if tz < -12 or tz > 12:
return await utils.answer(m, self.strings('incorrecttz'))
self.set('tz', tz)
await utils.answer(m, self.strings('tzset'))
async def _run_task(self, task: dict, index: str):
if task['paused']:
return
await self.client.send_message(task['address'], task['text'])
tasks = self.get('tasks')
this = tasks[index]
this['next_execution'] = (datetime.now() + self.convert_time(this['interval'])).strftime('%d.%m.%Y %H:%M:%S')
tasks[index] = this
self.set('tasks', tasks)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
hikka_config:
name: "HikkaConfig"
choose_core: "⚙️ <b>Wiel eng Kategorie</b>"
configure: "⚙️ <b>Wiel en Modul fir ze konfiguréieren</b>"
configure_lib: "📦 <b>Wiel eng Bibliothéik fir ze konfiguréieren</b>"
configuring_mod: "⚙️ <b>Wiel eng Konfiguratiounsoptioun fir de Modul</b> <code>{}</code>\n\n<b>Aktuell Optiounen:</b>\n\n{}"
configuring_lib: "📦 <b>Wiel eng Konfiguratiounsoptioun fir d'Bibliothéik</b> <code>{}</code>\n\n<b>Aktuell Optiounen:</b>\n\n{}"
configuring_option: "⚙️ <b>Optioun</b> <code>{}</code> <b>am Modul</b> <code>{}</code> <b>konfiguréieren</b>\n<i> {}</i>\n\n<b>Standard: {}</b>\n\n<b>Aktuell: {}</b>\n\n{}"
configuring_option_lib: "📦 <b>Optioun</b> <code>{}</code> <b>am Bibliothéik</b> <code>{}</code> <b>konfiguréieren</b>\n<i> {}</i>\n\n<b>Standard: {}</b>\n\n<b>Aktuell: {}</b>\n\n{}"
option_saved: "<emoji document_id=5318933532825888187>⚙️</emoji> <b>Optioun</b> <code>{}</code> <b>am Modul</b> <code>{}</code><b> gespäichert!</b>\n<b>Aktuell: {}</b>"
option_saved_lib: "<emoji document_id=5431736674147114227>📦</emoji> <b>Optioun</b> <code>{}</code> <b>am Bibliothéik</b> <code>{}</code><b> gespäichert!</b>\n<b>Aktuell: {}</b>"
option_reset: "♻️ <b>Optioun</b> <code>{}</code> <b>am Modul</b> <code>{}</code> <b>op Standard zréckgesat</b>\n<b>Aktuell: {}</b>"
option_reset_lib: "♻️ <b>Optioun</b> <code>{}</code> <b>am Bibliothéik</b> <code>{}</code> <b>op Standard zréckgesat</b>\n<b>Aktuell: {}</b>"
args: "🚫 <b>Dir hutt e falsche(n) Argument(er) uginn</b>"
no_mod: "🚫 <b>De Modul existéiert net</b>"
no_option: "🚫 <b>De Konfiguratiounsoptioun existéiert net</b>"
validation_error: "🚫 <b>Dir hutt e falsche(n) Konfiguratiounswäert uginn.\nError: {}</b>"
try_again: "🔁 Erëm probéieren"
typehint: "🕵️ <b>Muss e{eng_art} {} sinn</b>"
set: "setzen"
set_default_btn: "♻️ Op Standard zrécksetzen"
enter_value_btn: "✍️ Wäert aginn"
enter_value_desc: "✍️ Neien Konfiguratiounswäert fir dës Optioun aginn"
add_item_desc: "✍️ Element fir derzouzefüen aginn"
remove_item_desc: "✍️ Element fir ze läschen aginn"
back_btn: "👈 Zréck"
close_btn: "🔻 Zoumaachen"
add_item_btn: " Element derbäisetzen"
remove_item_btn: " Element läschen"
show_hidden: "🚸 Wäert weisen"
hide_value: "🔒 Wäert verstoppen"
builtin: "🛰 Eegebaut"
external: "🛸 Extern"
libraries: "📦 Bibliothéiken"
_cmd_doc_config: "Moduler konfiguréieren"
_cmd_doc_fconfig: "<module_name> <property_name> <config_value> - setzt de Konfiguratiounswäert fir de Modul"
_cls_doc: "Interaktiv Konfiguratioun fir de Hikka Userbot"
test:
name: "Tester"
set_loglevel: "<emoji document_id=5210952531676504517>🚫</emoji> <b>Gitt w.e.g. d'Verbalitéit als eng ganz Zuel oder eng Zeechenkett un</b>"
no_logs: "<emoji document_id=5363948200291998612>🤷‍♀️</emoji> <b>Dir hutt keng Logs op der Verbosität</b> <code>{}</code><b>.</b>"
logs_caption: "<emoji document_id=5188377234380954537>🌘</emoji> <b>Hikka Logs mat der Verbosität</b> <code>{}</code>\n\n<emoji document_id=6318902906900711458>⚪️</emoji> <b>Versioun: {}.{}.{}</b>{}"
suspend_invalid_time: "<emoji document_id=5210952531676504517>🚫</emoji> <b>Ongülteg Zäit fir ze suspendéieren</b>"
suspended: "<emoji document_id=5452023368054216810>🥶</emoji> <b>Bot suspendéiert fir</b> <code>{}</code> <b>Sekonnen</b>"
results_ping: "<emoji docu ment_id=5431449001532594346>⚡️</emoji> <b>Telegram Ping:</b> <code>{}</code> <b>ms</b>\n<emoji document_id=5445284980978621387>🚀</emoji> <b>Uptime: {}</b>"

View File

@@ -0,0 +1,262 @@
# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0
# meta pic: https://img.icons8.com/stickers/344/block.png
# meta developer: @mm_mods
__version__ = "1.2"
import asyncio
from hikka import loader, utils
import telethon as tt
from telethon.tl.types import Message
import logging
logger = logging.getLogger(__name__)
@loader.tds
class MiyaHostMod(loader.Module):
"""Module to manage your miyahost."""
strings = {
"name": "miyahost.manager",
"error": "😵 <b>Error</b> ({}): {}",
"success": "{} <b>Your container was successfully {}!</b> ({})",
"err.NoAuthKeyProvided": "no auth key provided",
"err.NoDBRecord": "you're not registered, not subscribed, or don't have a container",
"err.Verlangsamt": "you're being rate limited. Try again at {}",
"err.Banned": "you're banned from using this service",
"err.InvalidAuthKey": "invalid auth key",
"err.AuthNotEnabled": "API auth is not enabled",
"err.APIServerDown": "API server isn't responding or down",
"userinfo": "👤 <b>User</b> <code>{}</code>:\nSubscribed? {}\nBanned? {}",
"err.NoUser": "no such user",
"state.started": "started",
"state.stopped": "stopped",
"state.restarted": "restarted"
}
strings_ru = {
"name": "miyahost.manager",
"error": "😵 <b>Ошибка</b> ({}): {}",
"success": "{} <b> Контейнер успешно {}!</b> ({})",
"err.NoAuthKeyProvided": "не указан ключ авторизации",
"err.NoDBRecord": "Вы не зарегистрированы, не подписаны или не имеете контейнера",
"err.Verlangsamt": "Вы ограничены в использовании этого сервиса. Попробуйте снова в {}",
"err.Banned": "Вы забанены",
"err.InvalidAuthKey": "Неверный ключ авторизации",
"err.AuthNotEnabled": "Авторизация по API не включена",
"err.APIServerDown": "API сервер не отвечает или недоступен",
"userinfo": "👤 <b>Пользователь</b> <code>{}</code>:\nПодписан? {}\nЗабанен? {}",
"err.NoUser": "Нет такого пользователя",
"_cls_doc": "Модуль для управлением вашим miyahost.",
"_cmd_doc_mhinfo": "Отображает информацию о пользователе miyahost.",
"_cmd_doc_mhstart": "Запускает ваш контейнер.",
"_cmd_doc_mhstop": "Останавливает ваш контейнер.",
"_cmd_doc_mhrestart": "Перезапускает ваш контейнер.",
"state.started": "запущен",
"state.stopped": "остановлен",
"state.restarted": "перезапущен"
}
strings_de = {
"name": "miyahost.manager",
"error": "😵 <b>Fehler</b> ({}): {}",
"success": "{} <b>Ihren Kontainer würde erfolgreich {}!</b> ({})",
"err.NoAuthKeyProvided": "kein Authentifizierungsschlüssel angegeben",
"err.NoDBRecord": "Sie sind nicht registriert, nicht abonniert oder haben keinen Container",
"err.Verlangsamt": "Sie werden aufgrund von Rate-Limits eingeschränkt. Versuchen Sie es erneut um {}",
"err.Banned": "Sie sind von der Nutzung dieses Dienstes ausgeschlossen",
"err.InvalidAuthKey": "ungültiger Authentifizierungsschlüssel",
"err.AuthNotEnabled": "API-Authentifizierung ist nicht aktiviert",
"err.APIServerDown": "API-Server antwortet nicht oder ist nicht erreichbar",
"userinfo": "👤 <b>Nutzer</b> <code>{}</code>:\nAbonniert? {}\nGebannt? {}",
"err.NoUser": "kein solcher Nutzer",
"_cls_doc": "Modul zum Ihren miyahost beheren.",
"_cmd_doc_mhinfo": "Zeigt Informationen über den miyahost-Benutzer an.",
"_cmd_doc_mhstart": "Startet Ihren Container.",
"_cmd_doc_mhstop": "Stoppt Ihren Container.",
"_cmd_doc_mhrestart": "Startet Ihren Container neu.",
"state.started": "gestarted",
"state.stopped": "gestoppt",
"state.restarted": "neugestartet"
}
def __init__(self):
self.config = loader.ModuleConfig(
loader.ConfigValue(
"auth_key",
'NULL',
lambda: "Basic auth key for miyahost API — get it via @miyahostbot using /hhttpauth",
validator=loader.validators.Hidden(loader.validators.RegExp(r'[a-zA-Z0-9]+|NULL'))
),
loader.ConfigValue(
"mock_id",
'NULL',
lambda: "Enter another person's ID to rule it's container having it's auth key",
validator=loader.validators.RegExp(r'[0-9]+|NULL')
)
)
async def mhinfocmd(self, m: Message):
"""Get info about miyahost user."""
if not utils.get_args_raw(m) and not m.is_reply:
user = m.from_id
elif utils.get_args_raw(m) and not m.is_reply:
user = utils.get_args_raw(m)
else:
user = (await m.get_reply_message()).from_id
try:
import requests
req = requests.get(f"http://129.151.220.181:41154/mhapi/{user}").json()
except Exception as e:
return await utils.answer(m, self.strings("error").format(500, self.strings('err.APIServerDown')))
if list(req.keys())[0] == "error":
req = req["error"]
if req[0] == 404:
return await utils.answer(m, self.strings("error").format(404, self.strings("err.NoUser")))
else:
req = req["OK"]
useri = req[1]
subscr = f"✅ ({useri['datumbis']})" if useri["activated"] else ""
banned = "" if useri["banned"] else ""
return await utils.answer(m, self.strings("userinfo").format(user, subscr, banned))
async def mhstartcmd(self, m: Message):
"""Start miyahost container."""
mock = False
user = m.from_id
if self.config["auth_key"] == 'NULL':
return await utils.answer(m, self.strings("error").format(403, self.strings("err.NoAuthKeyProvided")))
if self.config['mock_id'] != 'NULL':
user = self.config['mock_id']
mock = True
try:
import requests
req = requests.get(
f"http://129.151.220.181:41154/mhapi/controls/start/{user}",
params={"basic_key": self.config["auth_key"]}
).json()
except Exception as e:
return await utils.answer(m, self.strings("error").format(500, self.strings('err.APIServerDown')))
if list(req.keys())[0] == "error":
req = req["error"]
if req[0] == 404:
logging.error(f'Failed with request to http://129.151.220.181:41154/mhapi/controls/start/{user}?basic_key={self.config["auth_key"]}, got {req[0]}')
return await utils.answer(m, self.strings("error").format(404, self.strings("err.NoDBRecord")))
elif req[0] == 401:
logging.error(f'Failed with request to http://129.151.220.181:41154/mhapi/controls/start/{user}?basic_key={self.config["auth_key"]}, got {req[0]}')
return await utils.answer(m, self.strings("error").format(401, self.strings("err.InvalidAuthKey")))
elif req[0] == 429:
logging.error(f'Failed with request to http://129.151.220.181:41154/mhapi/controls/start/{user}?basic_key={self.config["auth_key"]}, got {req[0]}')
return await utils.answer(m, self.strings("error").format(429, self.strings("err.Verlangsamt").format(req[2])))
elif req[0] == 403 and "banned" in req[1]:
logging.error(f'Failed with request to http://129.151.220.181:41154/mhapi/controls/start/{user}?basic_key={self.config["auth_key"]}, got {req[0]}')
return await utils.answer(m, self.strings("error").format(403, self.strings("err.Banned")))
elif req[0] == 403:
logging.error(f'Failed with request to http://129.151.220.181:41154/mhapi/controls/start/{user}?basic_key={self.config["auth_key"]}, got {req[0]}')
return await utils.answer(m, self.strings("error").format(403, self.strings("err.AuthNotEnabled")))
else:
emoji = '(⚫) ▶' if mock else ''
return await utils.answer(m, self.strings("success").format(emoji, self.strings("state.started"), user))
async def mhstopcmd(self, m: Message):
"""Stop miyahost container."""
user = m.from_id
mock = False
if self.config["auth_key"] == 'NULL':
return await utils.answer(m, self.strings("error").format(403, self.strings("err.NoAuthKeyProvided")))
if self.config['mock_id'] != 'NULL':
user = self.config['mock_id']
mock = True
emoji = '(⚫) ⏸' if mock else ''
await utils.answer(m, self.strings("success").format(emoji, self.strings("state.stopped"), user))
try:
import requests
req = requests.get(
f"http://129.151.220.181:41154/mhapi/controls/stop/{user}",
params={"basic_key": self.config["auth_key"]}
).json()
except Exception as e:
return await utils.answer(m, self.strings("error").format(500, self.strings('err.APIServerDown')))
if list(req.keys())[0] == "error":
req = req["error"]
if req[0] == 404:
logging.error(f'Failed with request to http://129.151.220.181:41154/mhapi/controls/start/{user}?basic_key={self.config["auth_key"]}, got {req[0]}')
return await utils.answer(m, self.strings("error").format(404, self.strings("err.NoDBRecord")))
elif req[0] == 401:
logging.error(f'Failed with request to http://129.151.220.181:41154/mhapi/controls/start/{user}?basic_key={self.config["auth_key"]}, got {req[0]}')
return await utils.answer(m, self.strings("error").format(401, self.strings("err.InvalidAuthKey")))
elif req[0] == 429:
logging.error(f'Failed with request to http://129.151.220.181:41154/mhapi/controls/start/{user}?basic_key={self.config["auth_key"]}, got {req[0]}')
return await utils.answer(m, self.strings("error").format(429, self.strings("err.Verlangsamt").format(
req[2])))
elif req[0] == 403 and "banned" in req[1]:
logging.error(f'Failed with request to http://129.151.220.181:41154/mhapi/controls/start/{user}?basic_key={self.config["auth_key"]}, got {req[0]}')
return await utils.answer(m, self.strings("error").format(403, self.strings("err.Banned")))
elif req[0] == 403:
logging.error(f'Failed with request to http://129.151.220.181:41154/mhapi/controls/start/{user}?basic_key={self.config["auth_key"]}, got {req[0]}')
return await utils.answer(m, self.strings("error").format(403, self.strings("err.AuthNotEnabled")))
else:
return
async def mhrestartcmd(self, m: Message):
"""Restart miyahost container."""
user = m.from_id
mock = False
if self.config["auth_key"] == 'NULL':
return await utils.answer(m, self.strings("error").format(403, self.strings("err.NoAuthKeyProvided")))
if self.config['mock_id'] != 'NULL':
user = self.config['mock_id']
mock = True
emoji = '(⚫) 🔁' if mock else '🔁'
await utils.answer(m, self.strings("success").format(emoji, self.strings("state.restarted"), user))
try:
import requests
req = requests.get(
f"http://129.151.220.181:41154/mhapi/controls/restart/{user}",
params={"basic_key": self.config["auth_key"]}
).json()
except Exception as e:
return await utils.answer(m, self.strings("error").format(500, self.strings('err.APIServerDown')))
if list(req.keys())[0] == "error":
req = req["error"]
if req[0] == 404:
logging.error(f'Failed with request to http://129.151.220.181:41154/mhapi/controls/start/{user}?basic_key={self.config["auth_key"]}, got {req[0]}')
return await utils.answer(m, self.strings("error").format(404, self.strings("err.NoDBRecord")))
elif req[0] == 401:
logging.error(f'Failed with request to http://129.151.220.181:41154/mhapi/controls/start/{user}?basic_key={self.config["auth_key"]}, got {req[0]}')
return await utils.answer(m, self.strings("error").format(401, self.strings("err.InvalidAuthKey")))
elif req[0] == 429:
logging.error(f'Failed with request to http://129.151.220.181:41154/mhapi/controls/start/{user}?basic_key={self.config["auth_key"]}, got {req[0]}')
return await utils.answer(m, self.strings("error").format(429, self.strings("err.Verlangsamt").format(
req[2])))
elif req[0] == 403 and "banned" in req[1]:
logging.error(f'Failed with request to http://129.151.220.181:41154/mhapi/controls/start/{user}?basic_key={self.config["auth_key"]}, got {req[0]}')
return await utils.answer(m, self.strings("error").format(403, self.strings("err.Banned")))
elif req[0] == 403:
logging.error(f'Failed with request to http://129.151.220.181:41154/mhapi/controls/start/{user}?basic_key={self.config["auth_key"]}, got {req[0]}')
return await utils.answer(m, self.strings("error").format(403, self.strings("err.AuthNotEnabled")))
else:
return

View File

@@ -0,0 +1,37 @@
$inline:
opening_form: " <b>Opening form...</b>"
opening_gallery: " <b>Opening gallery...</b>"
opening_list: " <b>Opening list...</b>"
inline403: "<emoji document_id=5210952531676504517>🚫</emoji> <b>You can't send inline units in this chat</b>"
invoke_failed: "<emoji document_id=5210952531676504517>🚫</emoji> <b>Unit invoke failed! More info in logs</b>"
invoke_failed_logs: "<emoji document_id=5210952531676504517>🚫</emoji> <b>Unit invoke failed!</b>\n\n<emoji document_id=5226512880362332956>📖</emoji> <b>Logs:</b>\n\n<pre><code class=\"language-logs\">{}</code></pre>"
show_inline_cmds: "📄 Show all available inline commands"
no_inline_cmds: "You have no available commands"
no_inline_cmds_msg: "<b>😔 There are no available inline commands or you lack access to them</b>"
inline_cmds: " You have {} available command(-s)"
inline_cmds_msg: "<b> Available inline commands:</b>\n\n{}"
run_command: "🏌️ Run command"
command_msg: "<b>🌘 Command «{}»</b>\n\n<i>{}</i>"
command: "🌘 Command «{}»"
button403: "You are not allowed to press this button!"
keep_id: "⚠️ Do not remove ID! {}"
# Luxembourgish
$inline-lb:
opening_form: " <b>Formulaire opmaken...</b>"
opening_gallery: " <b>Galerie opmaken...</b>"
opening_list: " <b>Lëscht opmaken...</b>"
inline403: "<emoji document_id=5210952531676504517>🚫</emoji> <b>Du kanns keng Inline-Units an dësem Chat schécken</b>"
invoke_failed: "<emoji document_id=5210952531676504517>🚫</emoji> <b>Unit invoke failed! Méi Info an de Logs</b>"
invoke_failed_logs: "<emoji document_id=5210952531676504517>🚫</emoji> <b>Unit invoke failed!</b>\n\n<emoji document_id=5226512880362332956>📖</emoji> <b>Logs:</b>\n\n<pre><code class=\"language-logs\">{}</code></pre>"
show_inline_cmds: "📄 All Inline-Befehl weisen"
no_inline_cmds: "D'ginn keng Inline-Befehl"
no_inline_cmds_msg: "<b>😔 Et ginn keng Inline-Befehl oder Dir hutt keng Zougrëff op se</b>"
inline_cmds: " Dir hutt {} verfügbar Befehl(-er)"
inline_cmds_msg: "<b> Verfügbar Inline-Befehl:</b>\n\n{}"
run_command: "🏌️ Befehl ausféieren"
command_msg: "<b>🌘 Befehl «{}»</b>\n\n<i>{}</i>"
command: "🌘 Befehl «{}»"
button403: "Dir dierft dëse Knäppchen net drécken!"
keep_id: "⚠️ Entfernt d'ID net! {}"

View File

@@ -0,0 +1,413 @@
# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0
# meta developer: @mm_mods
# meta pic: https://img.icons8.com/emoji/256/locked-with-pen.png
import os
import requests
import logging
from telethon.tl.patched import Message
from hikka import loader, utils
logger = logging.getLogger(__name__)
URL = 'https://versteck-1-j8565404.deta.app'
# noinspection PyCallingNonCallable
@loader.tds
class VersteckMod(loader.Module):
"""Work with VersteckAPI — download modules if you are common user, grant permissions for downloading if you are
developer!"""
def __init__(self):
self.config = loader.ModuleConfig(
loader.ConfigValue(
'dev_name',
'',
lambda: 'Name of Versteck to use (if you are developer)',
validator=loader.validators.String()
),
loader.ConfigValue(
'dev_password',
'',
lambda: 'Password of Versteck to use (if you are developer)',
validator=loader.validators.Hidden(loader.validators.Hidden())
),
)
strings = {
'name': 'Versteck',
'password?!': '🔴 <b>Password is incorrect!</b>',
'args?': '🔴 <b>Not enough arguments!</b>',
'name_already_exists': '🔴 <b>Name already exists!</b>',
'token_del_suc': '🟢 <b>Token deleted successfully!</b>',
'token_not_found': '🟡 <b>Token not found!</b>',
'versteck_not_found': '🟡 <b>Versteck not found!</b>',
'in-token_wrong': '🔴 <b>In-token is incorrect!</b>',
'connection_succesfull': '🔵 <b>Connection succesfull!</b>',
'permission_denied': '🟠 <b>Permission denied!</b>\nIt means that credentials were correct, but you don\'t '
'have permissions to download this file.',
'file_not_found': '🟠 <b>File not found!</b>\nIt means that credentials were correct, but file was not found.',
'not_a_file': '🟠 <b>Not a file!</b>\nIt means that credentials were correct, but this is not a file.',
'rights_of_unauthorized_insuffucient': '🟠 <b>Rights of unauthorized user are insufficient!</b>\nIt means '
'that Versteck exists, but you can\'t download this file without '
'authorization.',
'no_unauthorized': '🔴 <b>Unauthorized access for this Versteck is disabled!</b>',
'out-token_invalid': '⚫ <b>Out-token is invalid!</b>\nIt means that credentials were correct, but out-token '
'(the token, that Versteck uses to download files) is invalid. Contact the developer '
'of module you trying to download.',
'out-token_updated': '🟢 <b>Out-token was updated successfully!</b>',
'versteck_created': '🟢 <b>Versteck was created successfully!</b>\nPassword: <code>{}</code>\nName: <code>{}</code>\nUAP: <code>{}</code>',
'versteck_deleted': '🟢 <b>Versteck was deleted successfully!</b>',
'in-token_created': '🟢 <b>In-token was created successfully!</b>\nToken: <code>{}</code>\nRestrictions: <code>{}</code>',
'in-token_deleted': '🟢 <b>In-token was deleted successfully!</b>',
'module_result': '🟢 <b>Module <code>{}</code> was {} successfully!</b>',
'local_file_not_found': '🔴 <b>This file isn\'t presenting in cache!</b>',
'cache_cleared': '🟢 <b>Cache was cleared successfully!</b>',
'cache_contents': '💾 <b>Cache contents:</b>\n',
'cache_empty': '🟠 <b>Cache is empty!</b>',
'send_action:dwnld': 'downloaded',
'send_action:frmcch': 'extracted from cache',
}
strings_ru = {
'name': 'Versteck',
'password?!': '🔴 <b>Пароль неверен!</b>',
'args?': '🔴 <b>Недостаточно аргументов!</b>',
'name_already_exists': '🔴 <b>Имя уже существует!</b>',
'token_del_suc': '🟢 <b>Токен успешно удалён!</b>',
'token_not_found': '🔴 <b>Токен не найден!</b>',
'versteck_not_found': '🔴 <b>Versteck-источник не найден!</b>',
'in-token_wrong': '🔴 <b>Входной токен неверен!</b>',
'connection_succesfull': '🔵 <b>Соединение успешно установлено!</b>',
'permission_denied': '🟠 <b>Доступ запрещён!</b>\nЭто означает, что данные были верны, но у вас нет '
'прав на скачивание этого файла.',
'file_not_found': '🟠 <b>Файл не найден!</b>\nЭто означает, что данные были верны, но файл не был найден.',
'not_a_file': '🟠 <b>Это не файл!</b>\nЭто означает, что данные были верны, но это не файл.',
'rights_of_unauthorized_insuffucient': '🟠 <b>Права неавторизованного пользователя недостаточны!</b>\nЭто '
'означает, что Versteck-источник существует, но вы не можете скачать этот '
'файл без авторизации.',
'no_unauthorized': '🔴 <b>Неавторизованный доступ для этого Versteck-источника отключён!</b>',
'out-token_invalid': '⚫ <b>Внешний токен неверен!</b>\nЭто означает, что данные были верны, но внешний токен '
'(токен, который использует Versteck для скачивания файлов) неверен. Свяжитесь с '
'разработчиком модуля, который вы пытаетесь скачать.',
'out-token_updated': '🟢 <b>Внешний токен был обновлён!</b>',
'versteck_created': '🟢 <b>Versteck-источник был создан!</b>\nПароль: <code>{}</code>\nИмя: <code>{}</code>\nАПУ: <code>{}</code>',
'versteck_deleted': '🟢 <b>Versteck-источник был удалён!</b>',
'in-token_created': '🟢 <b>Входной токен был создан!</b>\nТокен: <code>{}</code>\nОграничения: <code>{}</code>',
'in-token_deleted': '🟢 <b>Входной токен был удалён!</b>',
'module_result': '🟢 <b>Модуль <code>{}</code> был успешно {}!</b>',
'local_file_not_found': '🔴 <b>Этого файла нет в кэше!</b>',
'cache_cleared': '🟢 <b>Кэш был успешно очищен!</b>',
'cache_contents': '💾 <b>Содержимое кэша:</b>\n',
'cache_empty': '🟠 <b>Кэш пуст!</b>',
'send_action:dwnld': 'скачан',
'send_action:frmcch': 'извлечён из кэша',
'_cls_doc': 'Модуль для работы с VersteckAPI — скачивай модули, если ты обычный пользователь, давай разрешения '
'на загрузку, если ты разработчик!',
'_cmd_doc_newv': 'Создаёт новый Versteck-источник.',
'_cmd_doc_delv': 'Удаляет Versteck-источник.',
'_cmd_doc_newi': 'Создаёт новый входной токен.',
'_cmd_doc_deli': 'Удаляет входной токен.',
'_cmd_doc_testv': 'Проверяет соединение с Versteck.',
'_cmd_doc_vml': 'Скачивает модуль из Versteck-источника.',
'_cmd_doc_updateot': 'Обновляет внешний токен.',
'_cmd_doc_vcacheclear': 'Очищает кэш.',
'_cmd_doc_vcachefetch': 'Обыскивает кэш и, если передано имя файла, отправляет соответствующий файл.',
}
strings_de = {
'name': 'Versteck',
'password?!': '🔴 <b>Passwort ist falsch!</b>',
'args?': '🔴 <b>Nicht genug Argumente!</b>',
'name_already_exists': '🔴 <b>Name existiert bereits!</b>',
'token_del_suc': '🟢 <b>Token erfolgreich gelöscht!</b>',
'token_not_found': '🔴 <b>Token nicht gefunden!</b>',
'versteck_not_found': '🔴 <b>Versteck nicht gefunden!</b>',
'in-token_wrong': '🔴 <b>In-Token ist falsch!</b>',
'connection_succesfull': '🔵 <b>Verbindung erfolgreich hergestellt!</b>',
'permission_denied': '🟠 <b>Zugriff verweigert!</b>\nDas bedeutet, dass die Anmeldeinformationen korrekt waren, '
'Sie jedoch keine Berechtigung zum Herunterladen dieser Datei haben.',
'file_not_found': '🟠 <b>Datei nicht gefunden!</b>\nDas bedeutet, dass die Anmeldeinformationen korrekt waren, '
'die Datei jedoch nicht gefunden wurde.',
'not_a_file': '🟠 <b>Keine Datei!</b>\nDas bedeutet, dass die Anmeldeinformationen korrekt waren, dies jedoch '
'keine Datei ist.',
'rights_of_unauthorized_insuffucient': '🟠 <b>Die Rechte des nicht autorisierten Benutzers sind unzureichend!</b>\n'
'Das bedeutet, dass der Versteck vorhanden ist, Sie jedoch '
'diese Datei ohne Autorisierung nicht herunterladen können.',
'no_unauthorized': '🔴 <b>Der nicht autorisierte Zugriff für diese Versteck ist deaktiviert!</b>',
'out-token_invalid': '⚫ <b>Aus-Token ist ungültig!</b>\nDas bedeutet, dass die Anmeldeinformationen korrekt '
'waren, aber der Aus-Token (der Token, den Versteck zum Herunterladen von Dateien '
'verwendet) ist ungültig. Wenden Sie sich an den Entwickler des Moduls, das Sie '
'herunterladen möchten.',
'out-token_updated': '🟢 <b>Aus-Token wurde erfolgreich aktualisiert!</b>',
'versteck_created': '🟢 <b>Versteck erfolgreich erstellt!</b>\nPasswort: <code>{}</code>\nName: <code>{}</code>\nNAP: <code>{}</code>',
'versteck_deleted': '🟢 <b>Versteck erfolgreich gelöscht!</b>',
'in-token_created': '🟢 <b>In-Token erfolgreich erstellt!</b>\nToken: <code>{}</code>\nEinschränkungen: <code>{}</code>',
'in-token_deleted': '🟢 <b>In-Token erfolgreich gelöscht!</b>',
'module_result': '🟢 <b>Modul <code>{}</code> erfolgreich {}!</b>',
'local_file_not_found': '🔴 <b>Diese Datei ist nicht im Cache!</b>',
'cache_cleared': '🟢 <b>Cache erfolgreich gelöscht!</b>',
'cache_contents': '💾 <b>Cache-Inhalt:</b>\n',
'cache_empty': '🟠 <b>Der Cache ist leer!</b>',
'send_action:dwnld': 'heruntergeladen',
'send_action:frmcch': 'aus dem Cache extrahiert',
'_cls_doc': 'Modul für VersteckAPI — lade Module herunter, wenn du ein normaler Benutzer bist, gib '
'Berechtigungen für Herunterladungen, wenn du ein Entwickler bist!',
'_cmd_doc_newv': 'Erstellt einen neuen Versteck.',
'_cmd_doc_delv': 'Löscht einen Versteck.',
'_cmd_doc_newi': 'Erstellt einen neuen In-Token.',
'_cmd_doc_deli': 'Löscht einen In-Token.',
'_cmd_doc_testv': 'Überprüft die Verbindung mit Versteck.',
'_cmd_doc_vml': 'Lädt ein Modul aus einem Versteck herunter.',
'_cmd_doc_updateot': 'Aktualisiert den Aus-Token.',
'_cmd_doc_vcacheclear': 'Leert den Cache.',
'_cmd_doc_vcachefetch': 'Durchsucht den Cache und sendet, wenn ein Dateiname übergeben wird, die '
'entsprechende Datei.',
}
async def newvcmd(self, m: Message):
"""Create new Versteck."""
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings('args?'))
try:
username, repo, token, name, unauthorized_rule = args.split()
except ValueError:
return await utils.answer(m, self.strings('args?'))
data = {
'username': username,
'repo': repo,
'out_token': token,
'name': name,
'unauthorized_path': unauthorized_rule,
}
res = requests.post(f'{URL}/new/versteck', json=data).json()
logging.error(f'{URL}/new/versteck')
logging.error(res)
if res['result'] == 'Name already exists':
return await utils.answer(m, self.strings('name_already_exists'))
return await utils.answer(m, self.strings('versteck_created').format(res['password'], name, unauthorized_rule))
async def delvcmd(self, m: Message):
"""Delete Versteck."""
password = self.config['dev_password']
name = self.config['dev_name']
if not password or not name:
return await utils.answer(m, self.strings('args?'))
res = requests.delete(f'{URL}/versteck/{name}', params={'password': password}).json()
if res['result'] == 'Versteck not found':
return await utils.answer(m, self.strings('versteck_not_found'))
if res['result'] == 'Wrong password':
return await utils.answer(m, self.strings('password?!'))
return await utils.answer(m, self.strings('versteck_deleted'))
async def newicmd(self, m: Message):
"""Create new in-token."""
args = utils.get_args_raw(m)
if args:
regex = args
else:
regex = ''
password = self.config['dev_password']
name = self.config['dev_name']
if not password or not name:
return await utils.answer(m, self.strings('args?'))
data = {
'password': password,
'name': name,
'grant_to': regex
}
res = requests.post(f'{URL}/new/in-token', json=data).json()
if res['result'] == 'Versteck not found':
return await utils.answer(m, self.strings('versteck_not_found'))
if res['result'] == 'Wrong password':
return await utils.answer(m, self.strings('password?!'))
return await utils.answer(m, self.strings('in-token_created').format(res['in_token'], regex or 0))
async def delicmd(self, m: Message):
"""Delete in-token."""
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings('args?'))
token = args
name = self.config['dev_name']
password = self.config['dev_password']
res = requests.delete(f'{URL}/in-token/{name}', params={'in_token': token, 'password': password}).json()
if res['result'] == 'Versteck not found':
return await utils.answer(m, self.strings('versteck_not_found'))
if res['result'] == 'Wrong password':
return await utils.answer(m, self.strings('password?!'))
if res['result'] == 'Token not found':
return await utils.answer(m, self.strings('token_not_found'))
return await utils.answer(m, self.strings('in-token_deleted'))
async def testvconncmd(self, m: Message):
"""Test Versteck connection."""
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings('args?'))
try:
name, in_token = args.split(':')
except ValueError:
return await utils.answer(m, self.strings('args?'))
res = requests.get(f'{URL}/versteck/{name}/{in_token}/').json()
if res['result'] == 'Versteck not found':
return await utils.answer(m, self.strings('versteck_not_found'))
elif res['result'] == 'Wrong in-token':
return await utils.answer(m, self.strings('in-token_wrong'))
elif res['result'] == 'Out-token is invalid':
return await utils.answer(m, self.strings('out-token_invalid'))
return await utils.answer(m, self.strings('connection_succesfull'))
async def vmlcmd(self, m: Message):
"""Download module from Versteck."""
args = utils.get_args_raw(m)
if not os.path.exists('versteck_downloads'):
os.mkdir('versteck_downloads')
if not args:
return await utils.answer(m, self.strings('args?'))
try:
auth, path = args.split(' ')
except ValueError:
return await utils.answer(m, self.strings('args?'))
try:
name, in_token = auth.split(':')
except ValueError:
return await utils.answer(m, self.strings('args?'))
data = {
'name': name,
'in_token': in_token,
'path': path
}
res = requests.post(f'{URL}/versteck/file/', json=data)
try:
res = res.json()
except Exception as e:
logging.error(res)
if res['result'] == 'Versteck not found':
return await utils.answer(m, self.strings('versteck_not_found'))
elif res['result'] == 'Wrong in-token':
return await utils.answer(m, self.strings('in-token_wrong'))
elif res['result'] == 'File not found':
return await utils.answer(m, self.strings('file_not_found'))
elif res['result'] == 'Permission denied':
return await utils.answer(m, self.strings('permission_denied'))
elif res['result'] == 'Not a file':
return await utils.answer(m, self.strings('not_a_file'))
elif res['result'] == 'Out-token is invalid':
return await utils.answer(m, self.strings('out-token_invalid'))
elif res['result'] == 'Unauthorized access is not allowed':
return await utils.answer(m, self.strings('no_unauthorized'))
elif res['result'] == 'Unauthorized access is not allowed here':
return await utils.answer(m, self.strings('rights_of_unauthorized_insuffucient'))
with open(f"versteck_downloads/{path.split('/')[-1]}", 'w') as f:
f.write(res['result'])
await m.client.send_file(
m.to_id,
f"versteck_downloads/{path.split('/')[-1]}",
caption=self.strings('module_result').format(path.split('/')[-1], self.strings('send_action:dwnld'))
)
return await m.delete()
async def updateotcmd(self, m: Message):
"""Update out-token."""
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings('args?'))
out_token = args
password = self.config['dev_password']
name = self.config['dev_name']
data = {
'new_token': out_token,
}
res = requests.post(f'{URL}/update/{name}', params={'password': password}, json=data).json()
if res['result'] == 'Versteck not found':
return await utils.answer(m, self.strings('versteck_not_found'))
elif res['result'] == 'Wrong password':
return await utils.answer(m, self.strings('password?!'))
return await utils.answer(m, self.strings('out-token_updated'))
async def vcachefetchcmd(self, m: Message):
"""Fetch local cache and return a file if found."""
args = utils.get_args_raw(m)
if not args:
to_send = self.strings('cache_contents') + '\n'
# Check is there's any files in cache
if not os.listdir('versteck_downloads'):
return await utils.answer(m, self.strings('cache_empty'))
for file in os.listdir('versteck_downloads'):
to_send += f'≻ <code>{file}</code>\n'
return await utils.answer(m, to_send)
file = args
try:
with open(f'versteck_downloads/{file}', 'r') as _:
pass
except FileNotFoundError:
return await utils.answer(m, self.strings('local_file_not_found'))
await m.client.send_file(
m.to_id,
f"versteck_downloads/{file}",
caption=self.strings('module_result').format(file, self.strings('send_action:frmcch'))
)
return await m.delete()
async def vcacheclearcmd(self, m: Message):
"""Clear local cache."""
for file in os.listdir('versteck_downloads'):
os.remove(f'versteck_downloads/{file}')
return await utils.answer(m, self.strings('cache_cleared'))