mirror of
https://github.com/MuRuLOSE/limoka.git
synced 2026-06-16 14:34:17 +02:00
Commited backup
This commit is contained in:
21
idiotcoders/idiotmodules/LICENSE
Normal file
21
idiotcoders/idiotmodules/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 idiotcoders
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
3
idiotcoders/idiotmodules/README.md
Normal file
3
idiotcoders/idiotmodules/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# idiotmodules
|
||||
The modules that are in this repo were created by three idiots
|
||||
Supports Hikka
|
||||
64
idiotcoders/idiotmodules/animearts.py
Normal file
64
idiotcoders/idiotmodules/animearts.py
Normal file
@@ -0,0 +1,64 @@
|
||||
# meta pic: https://static.whypodg.me/mods!animearts.png
|
||||
# meta banner: https://mods.whypodg.me/badges/animearts.jpg
|
||||
# meta developer: @idiotcoders
|
||||
# scope: hikka_only
|
||||
# scope: hikka_min 1.2.10
|
||||
|
||||
import asyncio
|
||||
import functools
|
||||
|
||||
import requests
|
||||
from telethon.tl.types import Message
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
async def photo():
|
||||
link = "https://api.waifu.pics/sfw/waifu"
|
||||
response = await utils.run_sync(requests.get, link)
|
||||
img = response.json()
|
||||
if "error" not in img:
|
||||
return img["url"]
|
||||
|
||||
async def nsfwphoto():
|
||||
link = "https://api.waifu.pics/nsfw/waifu"
|
||||
response = await utils.run_sync(requests.get, link)
|
||||
img = response.json()
|
||||
if "error" not in img:
|
||||
return img["url"]
|
||||
|
||||
@loader.tds
|
||||
class animeartsMod(loader.Module):
|
||||
"""Sends cute anime art"""
|
||||
|
||||
strings = {
|
||||
"name": "AnimeArts"
|
||||
}
|
||||
strings_ru = {"_cls_doc": "Отправляет милые аниме-арты"}
|
||||
|
||||
@loader.command(
|
||||
ru_doc="— Отправит милые аниме-арты"
|
||||
)
|
||||
async def artcmd(self, message: Message):
|
||||
"""Sends cute anime-art"""
|
||||
await self.inline.gallery(
|
||||
caption=lambda: f"<i>{utils.ascii_face()}</i>",
|
||||
message=message,
|
||||
next_handler=functools.partial(
|
||||
photo,
|
||||
),
|
||||
preload=5,
|
||||
)
|
||||
|
||||
@loader.command(
|
||||
ru_doc="— Отправит nsfw аниме-арты"
|
||||
)
|
||||
async def nsfwartcmd(self, message: Message):
|
||||
"""Sends nsfw anime-art"""
|
||||
await self.inline.gallery(
|
||||
caption=lambda: f"<i>{utils.ascii_face()}</i>",
|
||||
message=message,
|
||||
next_handler=functools.partial(
|
||||
nsfwphoto,
|
||||
),
|
||||
preload=5,
|
||||
)
|
||||
227
idiotcoders/idiotmodules/animetools.py
Normal file
227
idiotcoders/idiotmodules/animetools.py
Normal file
@@ -0,0 +1,227 @@
|
||||
# meta pic: https://static.whypodg.me/mods!animetools.png
|
||||
# meta banner: https://mods.whypodg.me/badges/animetools.jpg
|
||||
# meta developer: @idiotcoders
|
||||
# scope: hikka_only
|
||||
# scope: hikka_min 1.2.10
|
||||
|
||||
from deep_translator import GoogleTranslator
|
||||
from typing import Optional
|
||||
|
||||
import mimetypes
|
||||
import os
|
||||
import requests
|
||||
from io import BytesIO
|
||||
|
||||
from telethon.tl.types import Message
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
|
||||
|
||||
@loader.tds
|
||||
class animetoolsMod(loader.Module):
|
||||
"""AnimeTools"""
|
||||
|
||||
strings = {
|
||||
"name": "AnimeTools",
|
||||
"no_results": "<emoji document_id=5210952531676504517>❌</emoji> No results found!",
|
||||
"character": "\n<emoji document_id=5370765563226236970>👤</emoji> <b>Character:</b> <i>{}</i>",
|
||||
"quote": "\n<emoji document_id=5465300082628763143>💬</emoji> <b>Quote:</b> <i>{}</i>",
|
||||
"anime": "\n<emoji document_id=6334664298710697689>🍿</emoji> <b>Anime:</b> <i>{}</i>",
|
||||
"enter_name": "<emoji document_id=5467928559664242360>❗</emoji> <b>You must specify a character name!</b>",
|
||||
"description": "\n<emoji document_id=5818865088970362886>ℹ️</emoji> <b>Description:</b> <i>{}</i>",
|
||||
"genres": "\n<emoji document_id=5359441070201513074>🎭 </emoji> <b>Genres:</b> <i>{}</i>",
|
||||
"reply": "<emoji document_id=5215273032553078755>❌</emoji> You must reply to a some media or add it on your message!",
|
||||
"loading": "<emoji document_id=5213452215527677338>⏳</emoji> Loading...",
|
||||
"findanime": "<emoji document_id=5215644719022874555>ℹ️</emoji> <b>Anime:</b> <code>{}</code>\n<emoji document_id=6032602169360780718>🤨</emoji> <b>Similar to:</b> <code>{}%</code>\n<emoji document_id=6334664298710697689>🍿</emoji> <b>Episode:</b> <code>{}</code>",
|
||||
"error": "<emoji document_id=5215273032553078755>❎</emoji> An error has occurred, please try again",
|
||||
"no_desc": "❌ No description!",
|
||||
"no_photo": "<emoji document_id=5215273032553078755>❎</emoji> Need a picture"
|
||||
}
|
||||
|
||||
strings_ru = {
|
||||
"name": "AnimeTools",
|
||||
"no_results": "<emoji document_id=5210952531676504517>❌</emoji> Результатов не найдено!",
|
||||
"character": "\n<emoji document_id=5370765563226236970>👤</emoji> <b>Персонаж:</b> <i>{}</i>",
|
||||
"quote": "\n<emoji document_id=5465300082628763143>💬</emoji> <b>Цитата:</b> <i>{}</i>",
|
||||
"anime": "\n<emoji document_id=6334664298710697689>🍿</emoji> <b>Аниме:</b> <i>{}</i>",
|
||||
"description": "\n<emoji document_id=5818865088970362886>ℹ️</emoji> <b>Описание:</b> <i>{}</i>",
|
||||
"genres": "\n<emoji document_id=5359441070201513074>🎭 </emoji> <b>Жанры:</b> <i>{}</i>",
|
||||
"enter_name": "<emoji document_id=5467928559664242360>❗</emoji> <b>Вы должны указать имя персонажа!</b>",
|
||||
"loading": "<emoji document_id=5213452215527677338>⏳</emoji> Загрузка ...",
|
||||
"error": "<emoji document_id=5215273032553078755>❎</emoji> Произошла ошибка, попробуйте снова",
|
||||
"reply": "<emoji document_id=5215273032553078755>❌</emoji> Нужно ответить на фото/видео или прикрепить его!",
|
||||
"findanime": "<emoji document_id=5215644719022874555>ℹ️</emoji> <b>Аниме:</b> <code>{}</code>\n<emoji document_id=6032602169360780718>🤨</emoji> <b>Похоже на:</b> <code>{}%</code>\n<emoji document_id=6334664298710697689>🍿</emoji> <b>Эпизод:</b> <code>{}</code>",
|
||||
"_cmd_doc_findanime": "Ищет по картинке что за аниме",
|
||||
"_cmd_doc_animequote": "Отправляет аниме цитатки",
|
||||
"_cmd_doc_animechar": "Отправляет аниме цитатки определенного персонажа",
|
||||
"_cmd_doc_animeavailable": "Отправляет список всех доступных аниме на данный момент",
|
||||
"_cmd_doc_randomanime": "Отправляет случайное аниме",
|
||||
"_cmd_doc_characteravailable": "Отправляет список всех доступных персонажей на данный момент",
|
||||
"no_desc": "❌ Без описания!"
|
||||
}
|
||||
|
||||
|
||||
@loader.command(alias="fa")
|
||||
async def findanimecmd(self, message):
|
||||
"""Search by picture for what anime"""
|
||||
loading = await utils.answer(message, self.strings["loading"])
|
||||
reply_msg = await message.get_reply_message()
|
||||
msg = reply_msg or message
|
||||
media = msg.media
|
||||
if media:
|
||||
if msg.photo:
|
||||
filename = "photo.png"
|
||||
elif msg.video:
|
||||
filename = "video.mp4"
|
||||
elif msg.gif:
|
||||
filename = "gif.gif"
|
||||
else:
|
||||
filename = "photo.png"
|
||||
|
||||
filename = await self.client.download_media(media, file=filename)
|
||||
typem, encoding = mimetypes.guess_type(filename)
|
||||
r = requests.post(
|
||||
"https://api.trace.moe/search",
|
||||
data=open(filename, "rb"),
|
||||
headers={"Content-Type": typem}
|
||||
).json()
|
||||
|
||||
res = r['result'][0]
|
||||
episode = res['episode']
|
||||
video = res['video']
|
||||
name = res['filename'].split('.')[0]
|
||||
simil = res['similarity']
|
||||
await loading.delete()
|
||||
await utils.answer_file(
|
||||
message,
|
||||
file=video,
|
||||
caption=self.strings["findanime"].format(name, simil*100, episode)
|
||||
)
|
||||
os.remove(filename)
|
||||
else:
|
||||
await utils.answer(message, self.strings['reply'])
|
||||
|
||||
|
||||
@loader.command(alias="aq")
|
||||
async def animequotecmd(self, message: Message):
|
||||
"""Sends anime quotes"""
|
||||
args = utils.get_args_raw(message)
|
||||
link = "https://animechan.vercel.app/api/random"
|
||||
if args:
|
||||
link += "/anime?title={args}"
|
||||
qdata = (await utils.run_sync(requests.get, link)).json()
|
||||
|
||||
try:
|
||||
qdata["quote"] = GoogleTranslator(source="auto", target="ru").translate(qdata["quote"])
|
||||
except KeyError:
|
||||
qdata = {"quote": "no_results", "character": "no_results", "anime": "no_results"}
|
||||
|
||||
quote, chr, anime = qdata["quote"], qdata["character"], qdata["anime"]
|
||||
|
||||
if not qdata.get("quote") or "no_results" in [qdata.get("quote"), qdata.get("character"), qdata.get("anime")]:
|
||||
await utils.answer(message, self.strings["no_results"])
|
||||
return
|
||||
|
||||
quote = (
|
||||
self.strings['quote'].format(quote) +
|
||||
self.strings['character'].format(chr) +
|
||||
self.strings['anime'].format(anime)
|
||||
)
|
||||
await utils.answer(message, quote)
|
||||
|
||||
|
||||
@loader.command(alias="ac")
|
||||
async def animechar(self, message):
|
||||
"""Sends anime quotes for specific character"""
|
||||
character_name = utils.get_args_raw(message)
|
||||
if not character_name:
|
||||
await utils.answer(message, self.strings['enter_name'])
|
||||
return
|
||||
link = f"https://animechan.vercel.app/api/random/character?name={character_name}"
|
||||
qdata = (await utils.run_sync(requests.get, link)).json()
|
||||
|
||||
try:
|
||||
qdata["quote"] = GoogleTranslator(source="auto", target="ru").translate(qdata["quote"])
|
||||
except KeyError:
|
||||
qdata = {"quote": "no_results", "character": "no_results", "anime": "no_results"}
|
||||
|
||||
quote, chr, anime = qdata["quote"], qdata["character"], qdata["anime"]
|
||||
|
||||
if not qdata.get("quote") or "no_results" in [qdata.get("quote"), qdata.get("character"), qdata.get("anime")]:
|
||||
await utils.answer(message, self.strings["no_results"])
|
||||
return
|
||||
|
||||
quote = (
|
||||
self.strings['quote'].format(quote) +
|
||||
self.strings['character'].format(chr) +
|
||||
self.strings['anime'].format(anime)
|
||||
)
|
||||
await utils.answer(message, quote)
|
||||
|
||||
|
||||
@loader.command(alias="aa")
|
||||
async def animeavailable(self, message: Message):
|
||||
"""Sends a list of available anime"""
|
||||
args = utils.get_args_raw(message)
|
||||
link = "https://animechan.vercel.app/api/available/anime"
|
||||
response = await utils.run_sync(requests.get, link)
|
||||
available_anime = response.json()
|
||||
if args:
|
||||
matching_anime = [anime for anime in available_anime if args.lower() in anime.lower()]
|
||||
if matching_anime:
|
||||
anime_message = "\n".join(matching_anime)
|
||||
else:
|
||||
await utils.answer(message, self.strings["no_results"])
|
||||
return
|
||||
else:
|
||||
anime_message = "\n".join(available_anime)
|
||||
await utils.answer(message, anime_message)
|
||||
|
||||
|
||||
@loader.command(alias="ca")
|
||||
async def characteravailable(self, message: Message):
|
||||
"""Sends a list of available characters"""
|
||||
args = utils.get_args_raw(message)
|
||||
link = "https://animechan.vercel.app/api/available/character"
|
||||
response = await utils.run_sync(requests.get, link)
|
||||
available_anime = response.json()
|
||||
if args:
|
||||
matching_anime = [anime for anime in available_anime if args.lower() in anime.lower()]
|
||||
if matching_anime:
|
||||
anime_message = "\n".join(matching_anime)
|
||||
else:
|
||||
await utils.answer(message, self.strings["no_results"])
|
||||
return
|
||||
else:
|
||||
anime_message = "\n".join(available_anime)
|
||||
await utils.answer(message, anime_message)
|
||||
|
||||
|
||||
@loader.command(alias="ra")
|
||||
async def randomanime(self, message: Message):
|
||||
"""Sends a random anime"""
|
||||
a = await utils.answer(message, self.strings["loading"])
|
||||
try:
|
||||
link = "https://anime777.ru/api/rand"
|
||||
adata = (await utils.run_sync(requests.get, link)).json()
|
||||
|
||||
anime_kind = adata["material_data"]["anime_kind"]
|
||||
if anime_kind == "ova":
|
||||
return await self.randomanime(message)
|
||||
|
||||
title = adata["title"]
|
||||
genres = ", ".join(adata["material_data"]["anime_genres"])
|
||||
description = adata["material_data"]["description"]
|
||||
screenshots = adata["material_data"]["screenshots"]
|
||||
|
||||
anime_message = (
|
||||
self.strings['anime'].format(title) +
|
||||
self.strings['genres'].format(genres) +
|
||||
self.strings['description'].format(description)
|
||||
)
|
||||
await a.delete()
|
||||
await utils.answer_file(message, screenshots[0], anime_message)
|
||||
|
||||
except:
|
||||
await utils.answer(message, "error")
|
||||
2013
idiotcoders/idiotmodules/bio.py
Normal file
2013
idiotcoders/idiotmodules/bio.py
Normal file
File diff suppressed because it is too large
Load Diff
11
idiotcoders/idiotmodules/full.txt
Normal file
11
idiotcoders/idiotmodules/full.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
animetools
|
||||
animearts
|
||||
bio
|
||||
irisfarm
|
||||
lastfm
|
||||
loliart
|
||||
promote
|
||||
stablediffusion
|
||||
timer
|
||||
toadbot
|
||||
yoomoney
|
||||
30
idiotcoders/idiotmodules/irisfarm.py
Normal file
30
idiotcoders/idiotmodules/irisfarm.py
Normal file
@@ -0,0 +1,30 @@
|
||||
# meta pic: https://static.whypodg.me/mods!irisfarm.png
|
||||
# meta banner: https://mods.whypodg.me/badges/irisfarm.jpg
|
||||
# meta developer: @idiotcoders
|
||||
# scope: hikka_only
|
||||
# scope: hikka_min 1.2.10
|
||||
|
||||
|
||||
from .. import loader, utils
|
||||
import asyncio
|
||||
|
||||
|
||||
class IrisfarmMod(loader.Module):
|
||||
"""Автоматизирует работу с Iris Chat Manager (автоматическая ферма)"""
|
||||
|
||||
strings = {"name": "Irisfarm"}
|
||||
|
||||
async def farmcmd(self, message):
|
||||
"""Начинает автоматический фарм. """
|
||||
self.set("farm", True)
|
||||
while self.get("farm"):
|
||||
await message.reply("Ферма")
|
||||
await asyncio.sleep(14700)
|
||||
|
||||
async def unfarmcmd(self, message):
|
||||
"""Выключает автоферму."""
|
||||
self.set("farm", False)
|
||||
await utils.answer(
|
||||
message,
|
||||
"❗️ <b>Автоферма выключена.</b>",
|
||||
)
|
||||
299
idiotcoders/idiotmodules/lastfm.py
Normal file
299
idiotcoders/idiotmodules/lastfm.py
Normal file
@@ -0,0 +1,299 @@
|
||||
__version__ = (1, 0, 5)
|
||||
|
||||
# meta pic: https://static.whypodg.me/mods!lastfm.png
|
||||
# meta banner: https://mods.whypodg.me/badges/lastfm.jpg
|
||||
# meta developer: @idiotcoders
|
||||
# scope: hikka_only
|
||||
# scope: hikka_min 1.2.10
|
||||
# requires: pylast
|
||||
|
||||
import asyncio
|
||||
import contextlib
|
||||
import functools
|
||||
import logging
|
||||
import pylast
|
||||
import requests
|
||||
|
||||
from traceback import format_exc
|
||||
from typing import Optional
|
||||
from types import FunctionType
|
||||
from io import BytesIO
|
||||
|
||||
from telethon.tl.functions.account import UpdateProfileRequest
|
||||
from telethon.errors.rpcerrorlist import FloodWaitError
|
||||
from telethon.tl.types import Message
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@loader.tds
|
||||
class LastFMMod(loader.Module):
|
||||
"""LastFM Now (based on SpotifyNow)"""
|
||||
|
||||
strings = {
|
||||
"name": "LastFM",
|
||||
"_cfg_token": "Enter API token from your Last.fm account 🤫",
|
||||
"_cfg_secret": "Enter API secret from your Last.fm account 🤫",
|
||||
"_cfg_username": "Enter username from your Last.fm account 🤫",
|
||||
"_cfg_passwd": "Enter password from your Last.fm account 🤫",
|
||||
"_cfg_autobio": "Enter a template for auto-bio\nArguments: {author} — author of track, {track} — title of track",
|
||||
"error": "<emoji document_id=5312526098750252863>❌</emoji> <b>Error occurred. Make sure you are authorized and the track is playing!</b>\n\n<code>{error}</code>",
|
||||
"no_auth": "<emoji document_id=5312526098750252863>❌</emoji> <b>You are unauthorized!</b>",
|
||||
"nothing_playing": "<emoji document_id=5974411134936025665>❌</emoji> <b>Nothing is playing right now!</b>",
|
||||
"no_args": "<emoji document_id=5974411134936025665>❌</emoji> <b>Specify the args!</b>",
|
||||
"autobioe": "<emoji document_id=5197688912457245639>✅</emoji> <b>Last.fm bio enabled</b>",
|
||||
"autobiod": "<emoji document_id=5197688912457245639>✅</emoji> <b>Last.fm bio disabled</b>",
|
||||
"top": "<emoji document_id=5456498809875995940>🏆</emoji> <b>Your top-{count} the most listened tracks</b>:\n{top}",
|
||||
"nores": "<emoji document_id=5974411134936025665>❌</emoji> <b>No results!</b>",
|
||||
"now_playing": "<emoji document_id=5291772653567221434>🎧</emoji> {author} - {track}",
|
||||
"search": "<emoji document_id=5291772653567221434>🎧</emoji> {}"
|
||||
}
|
||||
|
||||
strings_ru = {
|
||||
"name": "LastFM",
|
||||
"_cfg_token": "Укажи API токен от аккаунта Last.fm 🤫",
|
||||
"_cfg_secret": "Укажи API секрет от аккаунта Last.fm 🤫",
|
||||
"_cfg_username": "Укажи логин от аккаунта Last.fm 🤫",
|
||||
"_cfg_passwd": "Укажи пароль от аккаунта Last.fm 🤫",
|
||||
"_cfg_autobio": "Укажи шаблон автобио\nАргументы: {author} — автор, {track} — название трека",
|
||||
"_cls_doc": "LastFM Now (основан на SpotifyNow)",
|
||||
"error": "<emoji document_id=5312526098750252863>❌</emoji> <b>Произошла ошибка. Убедитесь, что Вы автворизованы и музыка играет!</b>\n\n<code>{error}</code>",
|
||||
"no_auth": "<emoji document_id=5312526098750252863>❌</emoji> <b>Вы не авторизованы!</b>",
|
||||
"nothing_playing": "<emoji document_id=5974411134936025665>❌</emoji> <b>Ничего сейчас не играет!</b>",
|
||||
"no_args": "<emoji document_id=5974411134936025665>❌</emoji> <b>Укажите аргументы!</b>",
|
||||
"autobioe": "<emoji document_id=5197688912457245639>✅</emoji> <b>Авто-био для Last.fm включено</b>",
|
||||
"autobiod": "<emoji document_id=5197688912457245639>✅</emoji> <b>Авто-био для Last.fm выключено</b>",
|
||||
"top": "<emoji document_id=5456498809875995940>🏆</emoji> <b>Ваш топ-{count} самых прослушиваемых треков</b>:\n{top}",
|
||||
"nores": "<emoji document_id=5974411134936025665>❌</emoji> <b>Результатов не найдено!</b>",
|
||||
"now_playing": "<emoji document_id=5291772653567221434>🎧</emoji> {author} - {track}",
|
||||
"search": "<emoji document_id=5291772653567221434>🎧</emoji> {}"
|
||||
}
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"LastFmToken",
|
||||
None,
|
||||
lambda: self.strings["_cfg_token"],
|
||||
validator=loader.validators.Hidden(),
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"LastFmSecret",
|
||||
None,
|
||||
lambda: self.strings["_cfg_secret"],
|
||||
validator=loader.validators.Hidden(),
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"LastFmLogin",
|
||||
None,
|
||||
lambda: self.strings["_cfg_username"],
|
||||
validator=loader.validators.Hidden(),
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"LastFmPassword",
|
||||
None,
|
||||
lambda: self.strings["_cfg_passwd"],
|
||||
validator=loader.validators.Hidden(),
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"AutoBioTemplate",
|
||||
"🎧🎵 {author} - {track}",
|
||||
lambda: self.strings["_cfg_autobio"],
|
||||
validator=loader.validators.String(),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self._premium = getattr(await client.get_me(), "premium", False)
|
||||
try:
|
||||
self._netw = pylast.LastFMNetwork(
|
||||
api_key=self.config['LastFmToken'],
|
||||
api_secret=self.config['LastFmSecret'],
|
||||
username=self.config['LastFmLogin'],
|
||||
password_hash=pylast.md5(self.config['LastFmPassword'])
|
||||
)
|
||||
self._user = self._netw.get_user(self.config['LastFmLogin'])
|
||||
self.set("auth", True)
|
||||
except Exception:
|
||||
self.set("auth", False)
|
||||
|
||||
if self.get("autobio", False):
|
||||
self.autobio.start()
|
||||
|
||||
self.musicdl = await self.import_lib(
|
||||
"https://libs.hikariatama.ru/musicdl.py",
|
||||
suspend_on_error=True,
|
||||
)
|
||||
|
||||
|
||||
def error_handler(func) -> FunctionType:
|
||||
@functools.wraps(func)
|
||||
async def wrapped(*args, **kwargs):
|
||||
try:
|
||||
return await func(*args, **kwargs)
|
||||
except Exception:
|
||||
logger.exception(format_exc())
|
||||
with contextlib.supperss(Exception):
|
||||
await utils.answer(
|
||||
args[1],
|
||||
args[0].strings['error'].format(error=format_exc())
|
||||
)
|
||||
|
||||
wrapped.__doc__ = func.__doc__
|
||||
wrapped.__module__ = func.__module__
|
||||
|
||||
return wrapped
|
||||
|
||||
|
||||
@loader.loop(interval=90)
|
||||
async def autobio(self):
|
||||
if not self.get('auth', False):
|
||||
return
|
||||
now = self._user.get_now_playing()
|
||||
if not now:
|
||||
return
|
||||
|
||||
now = self._user.get_now_playing()
|
||||
bio = self.config["AutoBioTemplate"].format(
|
||||
author = str(now.artist),
|
||||
track = str(now.title)
|
||||
)
|
||||
|
||||
try:
|
||||
await self._client(
|
||||
UpdateProfileRequest(about=bio[: 140 if self._premium else 70])
|
||||
)
|
||||
except FloodWaitError as e:
|
||||
logger.info(f"Sleeping {max(e.seconds, 60)} bc of floodwait")
|
||||
await asyncio.sleep(max(e.seconds, 60))
|
||||
return
|
||||
|
||||
|
||||
@error_handler
|
||||
@loader.command(
|
||||
ru_doc="<название> 👉 Поиск по трекам. Работает без авторизации",
|
||||
alias="lsch"
|
||||
)
|
||||
async def lsearchcmd(self, message: Message):
|
||||
"<name of track> 👉 Search for tracks. Works without authorization"
|
||||
name = utils.get_args_raw(message)
|
||||
if not name:
|
||||
await utils.answer(
|
||||
message,
|
||||
self.strings['no_args']
|
||||
)
|
||||
return
|
||||
|
||||
await self._open_track(track=name, message=message)
|
||||
|
||||
|
||||
@error_handler
|
||||
@loader.command(
|
||||
ru_doc="[кол-во треков в топе] 👉 Получить топ самых прослушиваемых треков. Вы можете указать кол-во треков в топе (необязательно)"
|
||||
)
|
||||
async def ltopcmd(self, message: Message):
|
||||
"[count of tracks in top] 👉 Get the top most listened tracks. You can enter the count of tracks (optional)"
|
||||
args = utils.get_args(message)
|
||||
c, out = 5, ""
|
||||
if len(args) > 0 and args[0].isdigit():
|
||||
c = int(args[0])
|
||||
top = self._user.get_top_tracks(limit=c)
|
||||
emj = {'1': '<emoji document_id=5280735858926822987>🥇</emoji>', '2': '<emoji document_id=5283195573812340110>🥈</emoji>', '3': '<emoji document_id=5282750778409233531>🥉</emoji>'}
|
||||
for i in range(len(top)):
|
||||
out += f"{(str(i+1) + '.') if str(i+1) not in list(emj.keys()) else emj[str(i+1)]} <b>{top[i].item.artist}</b> - <i>{top[i].item.title}</i> — {top[i].weight}\n"
|
||||
await utils.answer(
|
||||
message,
|
||||
self.strings['top'].format(count=c, top=out)
|
||||
)
|
||||
|
||||
|
||||
@error_handler
|
||||
@loader.command(
|
||||
ru_doc="👉 Включить/выключить авто-био"
|
||||
)
|
||||
async def lbiocmd(self, message: Message):
|
||||
"""👉 Toggle bio playback streaming"""
|
||||
current = self.get("autobio", False)
|
||||
new = not current
|
||||
self.set("autobio", new)
|
||||
await utils.answer(
|
||||
message,
|
||||
self.strings[f"autobio{'e' if new else 'd'}"]
|
||||
)
|
||||
|
||||
if new:
|
||||
self.autobio.start()
|
||||
else:
|
||||
self.autobio.stop()
|
||||
|
||||
|
||||
@error_handler
|
||||
@loader.command(
|
||||
ru_doc="👉 Покажет проигрываемый сейчас трек"
|
||||
)
|
||||
async def lnowcmd(self, message: Message):
|
||||
"""👉 Shows track, that playing right now"""
|
||||
now = self._user.get_now_playing()
|
||||
if now is None:
|
||||
await utils.answer(
|
||||
message,
|
||||
self.strings['nothing_playing']
|
||||
)
|
||||
return
|
||||
artists = str(now.artist).split(', ')
|
||||
track = {'name': str(now.title), 'artists': []}
|
||||
track['artists'].append({'name': i for i in artists})
|
||||
await self._open_track(
|
||||
track=track, message=message,
|
||||
override_text=self.strings['now_playing'].format(
|
||||
author=str(now.artist), track=str(now.title)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def _open_track(
|
||||
self,
|
||||
track,
|
||||
message: Message,
|
||||
override_text: str = None,
|
||||
):
|
||||
if type(track) is dict:
|
||||
name = track.get("name")
|
||||
artists = [
|
||||
artist["name"] for artist in track.get("artists", []) if "name" in artist
|
||||
]
|
||||
full_song_name = f"{name} - {', '.join(artists)}"
|
||||
else:
|
||||
name = ""
|
||||
artists = []
|
||||
full_song_name = str(track)
|
||||
|
||||
music = await self.musicdl.dl(full_song_name, only_document=True)
|
||||
|
||||
if not override_text:
|
||||
override_text = (
|
||||
f"<emoji document_id=5291772653567221434>🎧</emoji> <b>{', '.join(artists)}</b> - <i>{name}</i>"
|
||||
if artists else
|
||||
f"<emoji document_id=5291772653567221434>🎧</emoji> <b>{full_song_name}</b>"
|
||||
)
|
||||
|
||||
try:
|
||||
await self._client.send_file(
|
||||
message.peer_id,
|
||||
music,
|
||||
caption=override_text
|
||||
)
|
||||
except:
|
||||
await utils.answer(
|
||||
message,
|
||||
"Some error!"
|
||||
)
|
||||
return
|
||||
|
||||
if message.out:
|
||||
await message.delete()
|
||||
48
idiotcoders/idiotmodules/loliart.py
Normal file
48
idiotcoders/idiotmodules/loliart.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# meta pic: https://static.whypodg.me/mods!loliart.png
|
||||
# meta banner: https://mods.whypodg.me/badges/loliart.jpg
|
||||
# meta developer: @idiotcoders
|
||||
# scope: hikka_only
|
||||
# scope: hikka_min 1.2.10
|
||||
|
||||
import asyncio
|
||||
import functools
|
||||
|
||||
import requests
|
||||
from telethon.tl.types import Message
|
||||
|
||||
from .. import loader, utils
|
||||
|
||||
|
||||
async def photo():
|
||||
link = "https://api.lolicon.app/setu/v2?tag=loli"
|
||||
img = (
|
||||
await utils.run_sync(
|
||||
requests.get,
|
||||
link
|
||||
)
|
||||
).json()
|
||||
if img["error"] == "":
|
||||
return img["data"][0]["urls"]["original"]
|
||||
|
||||
@loader.tds
|
||||
class loliartMod(loader.Module):
|
||||
"""Sends cute anime loli-art ☺"""
|
||||
|
||||
strings = {
|
||||
"name": "LoliArt"
|
||||
}
|
||||
strings_ru = {"_cls_doc": "Отправляет милые лоли-арты ☺"}
|
||||
|
||||
@loader.command(
|
||||
ru_doc="— Отправит милый лоли-арт"
|
||||
)
|
||||
async def lolicmd(self, message: Message):
|
||||
"""— Send cute loli-art"""
|
||||
await self.inline.gallery(
|
||||
caption=lambda: f"<i>{utils.ascii_face()}</i>",
|
||||
message=message,
|
||||
next_handler=functools.partial(
|
||||
photo,
|
||||
),
|
||||
preload=5,
|
||||
)
|
||||
538
idiotcoders/idiotmodules/promote.py
Normal file
538
idiotcoders/idiotmodules/promote.py
Normal file
@@ -0,0 +1,538 @@
|
||||
# meta developer: @idiotcoders
|
||||
# scope: hikka_min 1.6.3
|
||||
|
||||
|
||||
import io
|
||||
import logging
|
||||
|
||||
import telethon
|
||||
|
||||
from .. import loader, utils
|
||||
from ..inline.types import InlineCall
|
||||
|
||||
|
||||
@loader.tds
|
||||
class PromoteMod(loader.Module):
|
||||
"""Managing administrators rights in chats."""
|
||||
|
||||
strings = {
|
||||
"name": "Promote",
|
||||
"not_a_chat": "<emoji document_id=5312526098750252863>❌</emoji> <b>The command cannot be run in private messages.</b>",
|
||||
"no_rights": "<emoji document_id=5318764049121420145>🫤</emoji> <b>I have no administrator rights or cannot promote" \
|
||||
" and demote administrators.</b>",
|
||||
"no_user": "<emoji document_id=5312383351217201533>⚠️</emoji> <b>You should specify an user.</b>",
|
||||
"demoted": "<emoji document_id=5458403743835889060>😂</emoji> <b>{name} was demoted to an regular user.</b>",
|
||||
"promoted_full": "<emoji document_id=5271557007009128936>👑</emoji> <b>{name} was promoted to an administrator" \
|
||||
" with full rights.</b>\n<emoji document_id=5470060791883374114>✍️</emoji> <b>Rank:</b> {rank}",
|
||||
"promoted": "<emoji document_id=5451786809845491357>🫣</emoji> <b>{name} was promoted to an administrator.</b>\n" \
|
||||
"<emoji document_id=5470060791883374114>✍️</emoji> <b>Rank:</b> {rank}",
|
||||
"choose_rights": "<emoji document_id=5271557007009128936>👑</emoji> <b>Choose administrator rights for {name}</b>" \
|
||||
"\n<emoji document_id=5470060791883374114>✍️</emoji> <b>Rank</b>: {rank}",
|
||||
"right_change_info": "{emoji} Change info {channel_or_chat}",
|
||||
"of_channel": "of channel", "of_chat": "of chat",
|
||||
"right_post_messages": "{emoji} Post messages",
|
||||
"right_edit_messages": "{emoji} Edit posts",
|
||||
"right_delete_messages": "{emoji} Delete messages",
|
||||
"right_ban_users": "{emoji} Restrict users",
|
||||
"right_invite_users": "{emoji} Invite users",
|
||||
"right_pin_messages": "{emoji} Pin messages",
|
||||
"right_add_admins": "{emoji} Promote administrators",
|
||||
"right_anonymous": "{emoji} Anonymous",
|
||||
"right_manage_call": "{emoji} Manage calls",
|
||||
"confirm": "✅ Confirm",
|
||||
}
|
||||
|
||||
strings_ru = {
|
||||
"name": "Promote",
|
||||
"not_a_chat": "<emoji document_id=5312526098750252863>❌</emoji> <b>Команда не может быть запущена в личных сообщениях.</b>",
|
||||
"no_rights": "<emoji document_id=5318764049121420145>🫤</emoji> <b>У меня нет прав администратора в этом чате" \
|
||||
" или я не могу изменять права администраторов.</b>",
|
||||
"no_user": "<emoji document_id=5312383351217201533>⚠️</emoji> <b>Вы не указали пользователя.</b>",
|
||||
"demoted": "<emoji document_id=5458403743835889060>😂</emoji> <b>С {name} сняты права администратора.</b>",
|
||||
"promoted_full": "<emoji document_id=5271557007009128936>👑</emoji> <b>{name} повышен до администратора " \
|
||||
"с полными правами.</b>\n<emoji document_id=5470060791883374114>✍️</emoji> <b>Должность:</b> {rank}",
|
||||
"promoted": "<emoji document_id=5451786809845491357>🫣</emoji> <b>{name} повышен до администратора.</b>\n" \
|
||||
"<emoji document_id=5470060791883374114>✍️</emoji> <b>Должность:</b> {rank}",
|
||||
"choose_rights": "<emoji document_id=5271557007009128936>👑</emoji> <b>Выберите, какие права вы хотите дать " \
|
||||
"{name}</b>\n<emoji document_id=5470060791883374114>✍️</emoji> <b>Должность</b>: {rank}",
|
||||
"right_change_info": "{emoji} Изменение профиля {channel_or_chat}",
|
||||
"of_channel": "канала", "of_chat": "чата",
|
||||
"right_post_messages": "{emoji} Публиковать посты",
|
||||
"right_edit_messages": "{emoji} Изменять посты",
|
||||
"right_delete_messages": "{emoji} Удалять сообщения",
|
||||
"right_ban_users": "{emoji} Ограничивать пользователей",
|
||||
"right_invite_users": "{emoji} Добавлять пользователей",
|
||||
"right_pin_messages": "{emoji} Закреплять сообщения",
|
||||
"right_add_admins": "{emoji} Назначать администраторов",
|
||||
"right_anonymous": "{emoji} Анонимность",
|
||||
"right_manage_call": "{emoji} Управление звонками",
|
||||
"confirm": "✅ Подтвердить",
|
||||
"_cls_doc": "Управление правами администраторов в чатах."
|
||||
}
|
||||
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.client = client
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@loader.command(
|
||||
ru_doc="<пользователь> — Снятие прав администратора с пользователя."
|
||||
)
|
||||
async def demotecmd(self, message: telethon.types.Message):
|
||||
"""<user> — Demote an administrator to a user."""
|
||||
if message.is_private:
|
||||
return await utils.answer(
|
||||
message, self.strings("not_a_chat", message)
|
||||
)
|
||||
|
||||
user_id = None
|
||||
chat = await message.get_chat()
|
||||
reply = await message.get_reply_message()
|
||||
if reply:
|
||||
if reply.sender_id != message._client.tg_id:
|
||||
user_id = reply.sender_id
|
||||
else:
|
||||
user_id = await utils.get_target(message)
|
||||
|
||||
if (not chat.admin_rights or not chat.admin_rights.add_admins) and not chat.creator:
|
||||
return await utils.answer(message, self.strings("no_rights", message))
|
||||
if not user_id:
|
||||
return await utils.answer(
|
||||
message, self.strings("no_user", message)
|
||||
)
|
||||
|
||||
user = await message.client.get_entity(
|
||||
user_id
|
||||
)
|
||||
try:
|
||||
await message.client(
|
||||
telethon.tl.functions.channels.EditAdminRequest(
|
||||
message.chat_id, user.id,
|
||||
telethon.types.ChatAdminRights(
|
||||
other=False,
|
||||
change_info=None,
|
||||
post_messages=None,
|
||||
edit_messages=None,
|
||||
delete_messages=None,
|
||||
ban_users=None,
|
||||
invite_users=None,
|
||||
pin_messages=None,
|
||||
add_admins=None,
|
||||
anonymous=None,
|
||||
manage_call=None,
|
||||
manage_topics=None
|
||||
),
|
||||
""
|
||||
)
|
||||
)
|
||||
except telethon.errors.ChatAdminRequiredError:
|
||||
return await utils.answer(message, self.strings("no_rights", message))
|
||||
|
||||
await utils.answer(
|
||||
message, self.strings("demoted", message).format(
|
||||
name=user.first_name
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@loader.command(
|
||||
ru_doc="<пользователь> [роль (aka префикс)] — Повышение пользователя до администратора с полными правами."
|
||||
)
|
||||
async def fullrightscmd(self, message: telethon.types.Message):
|
||||
"""<user> [role (aka [prefix])] — Promote an user to administrator with full rights."""
|
||||
if message.is_private:
|
||||
return await utils.answer(
|
||||
message, self.strings("not_a_chat", message)
|
||||
)
|
||||
|
||||
rank, user_id = "Admin", None
|
||||
chat = await message.get_chat()
|
||||
args = utils.get_args_raw(message)
|
||||
reply = await message.get_reply_message()
|
||||
if reply:
|
||||
if reply.sender_id != message._client.tg_id:
|
||||
user_id = reply.sender_id
|
||||
if args:
|
||||
rank = args
|
||||
else:
|
||||
user_id = await utils.get_target(message)
|
||||
if len(args.split()) > 1:
|
||||
rank = " ".join(args.split()[1:])
|
||||
|
||||
if (not chat.admin_rights or not chat.admin_rights.add_admins) and not chat.creator:
|
||||
return await utils.answer(message, self.strings("no_rights", message))
|
||||
if not user_id:
|
||||
return await utils.answer(
|
||||
message, self.strings("no_user", message)
|
||||
)
|
||||
|
||||
user = await message.client.get_entity(
|
||||
user_id
|
||||
)
|
||||
try:
|
||||
await message.client(
|
||||
telethon.tl.functions.channels.EditAdminRequest(
|
||||
message.chat_id, user.id,
|
||||
telethon.types.ChatAdminRights(
|
||||
other=True,
|
||||
change_info=True,
|
||||
post_messages=True if chat.broadcast else None,
|
||||
edit_messages=True if chat.broadcast else None,
|
||||
delete_messages=True,
|
||||
ban_users=True,
|
||||
invite_users=True,
|
||||
add_admins=True,
|
||||
anonymous=None,
|
||||
pin_messages=True if not chat.broadcast else None,
|
||||
manage_call=True if not chat.broadcast else None
|
||||
),
|
||||
rank
|
||||
)
|
||||
)
|
||||
except telethon.errors.ChatAdminRequiredError:
|
||||
return await utils.answer(message, self.strings("no_rights", message))
|
||||
|
||||
await utils.answer(
|
||||
message,
|
||||
self.strings("promoted_full", message).format(
|
||||
name=user.first_name,
|
||||
rank=rank
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@loader.command(
|
||||
ru_doc="<пользователь> [роль (aka префикс)] — Повышение пользователя до администратора."
|
||||
)
|
||||
async def promotecmd(self, message: telethon.types.Message):
|
||||
"""<user> [role (aka [prefix])] — Promote an user to administrator."""
|
||||
if message.is_private:
|
||||
return await utils.answer(
|
||||
message, self.strings("not_a_chat", message)
|
||||
)
|
||||
|
||||
rank, user_id = "Admin", None
|
||||
chat = await message.get_chat()
|
||||
args = utils.get_args_raw(message)
|
||||
reply = await message.get_reply_message()
|
||||
if reply:
|
||||
if reply.sender_id != message._client.tg_id:
|
||||
user_id = reply.sender_id
|
||||
if args:
|
||||
rank = args
|
||||
else:
|
||||
user_id = await utils.get_target(message)
|
||||
if len(args.split()) > 1:
|
||||
rank = " ".join(args.split()[1:])
|
||||
|
||||
if (not chat.admin_rights or not chat.admin_rights.add_admins) and not chat.creator:
|
||||
return await utils.answer(message, self.strings("no_rights", message))
|
||||
if not user_id:
|
||||
return await utils.answer(
|
||||
message, self.strings("no_user", message)
|
||||
)
|
||||
|
||||
user = await message.client.get_entity(
|
||||
user_id
|
||||
)
|
||||
|
||||
rights = {
|
||||
"change_info": False,
|
||||
"post_messages": False,
|
||||
"edit_messages": False,
|
||||
"delete_messages": False,
|
||||
"ban_users": False,
|
||||
"invite_users": False,
|
||||
"pin_messages": False,
|
||||
"add_admins": False,
|
||||
"anonymous": False,
|
||||
"manage_call": False,
|
||||
"": False
|
||||
}
|
||||
|
||||
markup = []
|
||||
reply_markup = []
|
||||
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings('right_change_info').format(
|
||||
emoji='✏',
|
||||
channel_or_chat=self.strings('of_channel') if chat.broadcast else self.strings('of_chat')
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["change_info", True], rights, chat, rank, user]
|
||||
},
|
||||
)
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings('right_delete_messages').format(
|
||||
emoji='🗑'
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["delete_messages", True], rights, chat, rank, user]
|
||||
},
|
||||
)
|
||||
if chat.broadcast:
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings('right_post_messages').format(
|
||||
emoji='✉',
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["post_messages", True], rights, chat, rank, user]
|
||||
},
|
||||
)
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings('right_edit_messages').format(
|
||||
emoji='✏',
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["edit_messages", True], rights, chat, rank, user]
|
||||
},
|
||||
)
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings('right_ban_users').format(
|
||||
emoji='⛔',
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["ban_users", True], rights, chat, rank, user]
|
||||
},
|
||||
)
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings('right_pin_messages').format(
|
||||
emoji='📌',
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["pin_messages", True], rights, chat, rank, user]
|
||||
},
|
||||
)
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings('right_add_admins').format(
|
||||
emoji='👑',
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["add_admins", True], rights, chat, rank, user]
|
||||
},
|
||||
)
|
||||
if not chat.broadcast:
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings('right_manage_call').format(
|
||||
emoji='📞'
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["manage_call", True], rights, chat, rank, user]
|
||||
},
|
||||
)
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings('right_invite_users').format(
|
||||
emoji='➕',
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["invite_users", True], rights, chat, rank, user]
|
||||
},
|
||||
)
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings('right_anonymous').format(
|
||||
emoji='🎭',
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["anonymous", True], rights, chat, rank, user]
|
||||
},
|
||||
)
|
||||
|
||||
kb = []
|
||||
for i in markup:
|
||||
if len(kb) == 2:
|
||||
reply_markup.append(kb)
|
||||
kb = []
|
||||
kb.append(i)
|
||||
if kb != [] and kb not in reply_markup:
|
||||
reply_markup.append(kb)
|
||||
|
||||
reply_markup.append([
|
||||
{
|
||||
"text": self.strings("confirm"),
|
||||
"callback": self._inline_promote,
|
||||
"args": [rights, chat, rank, user]
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
await self.inline.form(
|
||||
message=message,
|
||||
text=self.strings("choose_rights").format(
|
||||
name=user.first_name,
|
||||
rank=rank
|
||||
),
|
||||
silent=True,
|
||||
reply_markup=reply_markup
|
||||
)
|
||||
|
||||
|
||||
async def _ch_rights(self, call: InlineCall, right: str, all_rights: dict, chat, rank: str, user):
|
||||
all_rights[right[0]] = right[1]
|
||||
|
||||
markup = []
|
||||
reply_markup = []
|
||||
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings("right_change_info").format(
|
||||
emoji='✏' if not all_rights.get('change_info', False) else '✅',
|
||||
channel_or_chat=self.strings('of_channel') if chat.broadcast else self.strings('of_chat')
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["change_info", not all_rights.get("change_info")], all_rights, chat, rank, user]
|
||||
},
|
||||
)
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings("right_delete_messages").format(
|
||||
emoji='🗑' if not all_rights.get('delete_messages', False) else '✅'
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["delete_messages", not all_rights.get("delete_messages", False)], all_rights, chat, rank, user]
|
||||
},
|
||||
)
|
||||
if chat.broadcast:
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings("right_post_messages").format(
|
||||
emoji='✉' if not all_rights.get('post_messages', False) else '✅'
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["post_messages", not all_rights.get("post_messages", False)], all_rights, chat, rank, user]
|
||||
},
|
||||
)
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings("right_edit_messages").format(
|
||||
emoji='✏' if not all_rights.get('edit_messages', False) else '✅'
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["edit_messages", not all_rights.get("edit_messages", False)], all_rights, chat, rank, user]
|
||||
},
|
||||
)
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings("right_ban_users").format(
|
||||
emoji='⛔' if not all_rights.get('ban_users', False) else '✅'
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["ban_users", not all_rights.get("ban_users", False)], all_rights, chat, rank, user]
|
||||
},
|
||||
)
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings("right_pin_messages").format(
|
||||
emoji='📌' if not all_rights.get('pin_messages', False) else '✅'
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["pin_messages", not all_rights.get("pin_messages", False)], all_rights, chat, rank, user]
|
||||
},
|
||||
)
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings("right_add_admins").format(
|
||||
emoji='👑' if not all_rights.get('add_admins', False) else '✅'
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["add_admins", not all_rights.get("add_admins", False)], all_rights, chat, rank, user]
|
||||
},
|
||||
)
|
||||
if not chat.broadcast:
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings("right_manage_call").format(
|
||||
emoji='📞' if not all_rights.get('manage_call', False) else '✅'
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["manage_call", not all_rights.get("manage_call", False)], all_rights, chat, rank, user]
|
||||
}
|
||||
)
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings("right_invite_users").format(
|
||||
emoji='➕' if not all_rights.get('invite_users', False) else '✅'
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["invite_users", not all_rights.get("invite_users", False)], all_rights, chat, rank, user]
|
||||
},
|
||||
)
|
||||
markup.append(
|
||||
{
|
||||
"text": self.strings("right_anonymous").format(
|
||||
emoji='🎭' if not all_rights.get('anonymous', False) else '✅'
|
||||
),
|
||||
"callback": self._ch_rights,
|
||||
"args": [["anonymous", not all_rights.get("anonymous", False)], all_rights, chat, rank, user]
|
||||
},
|
||||
)
|
||||
|
||||
kb = []
|
||||
for i in markup:
|
||||
if len(kb) == 2:
|
||||
reply_markup.append(kb)
|
||||
kb = []
|
||||
kb.append(i)
|
||||
if kb != [] and kb not in reply_markup:
|
||||
reply_markup.append(kb)
|
||||
|
||||
reply_markup.append([
|
||||
{
|
||||
"text": self.strings("confirm"),
|
||||
"callback": self._inline_promote,
|
||||
"args": [all_rights, chat, rank, user]
|
||||
}
|
||||
])
|
||||
|
||||
await call.edit(
|
||||
text=self.strings("choose_rights").format(
|
||||
name=user.first_name,
|
||||
rank=rank
|
||||
),
|
||||
reply_markup=reply_markup
|
||||
)
|
||||
|
||||
|
||||
async def _inline_promote(self, call: InlineCall, all_rights: dict, chat, rank: str, user):
|
||||
try:
|
||||
await self.client(
|
||||
telethon.tl.functions.channels.EditAdminRequest(
|
||||
chat.id, user.id,
|
||||
telethon.types.ChatAdminRights(
|
||||
other=True,
|
||||
change_info=all_rights.get('change_info'),
|
||||
post_messages=all_rights.get('post_messages') if chat.broadcast else None,
|
||||
edit_messages=all_rights.get('edit_messages') if chat.broadcast else None,
|
||||
delete_messages=all_rights.get('delete_messages'),
|
||||
ban_users=all_rights.get('ban_users'),
|
||||
invite_users=all_rights.get('invite_users'),
|
||||
add_admins=all_rights.get('add_admins'),
|
||||
anonymous=all_rights.get('anonymous'),
|
||||
pin_messages=all_rights.get('pin_messages') if not chat.broadcast else None,
|
||||
manage_call=all_rights.get('manage_call') if not chat.broadcast else None,
|
||||
manage_topics=all_rights.get('manage_topics') if not chat.broadcast else None
|
||||
),
|
||||
rank
|
||||
)
|
||||
)
|
||||
except telethon.errors.ChatAdminRequiredError:
|
||||
return await call.edit(
|
||||
text=self.strings("no_rights")
|
||||
)
|
||||
|
||||
await call.edit(
|
||||
text=self.strings("promoted").format(
|
||||
name=user.first_name,
|
||||
rank=rank
|
||||
)
|
||||
)
|
||||
284
idiotcoders/idiotmodules/stablediffusion.py
Normal file
284
idiotcoders/idiotmodules/stablediffusion.py
Normal file
@@ -0,0 +1,284 @@
|
||||
# meta pic: https://static.whypodg.me/mods!stablediffusion.png
|
||||
# meta banner: https://mods.whypodg.me/badges/stablediffusion.jpg
|
||||
# meta developer: @idiotcoders
|
||||
# scope: hikka_only
|
||||
# scope: hikka_min 1.6.2
|
||||
|
||||
import json
|
||||
import re
|
||||
import requests
|
||||
import datetime
|
||||
|
||||
from hikkatl.types import Message
|
||||
from .. import loader, utils
|
||||
|
||||
|
||||
@loader.tds
|
||||
class StableDiffusionMod(loader.Module):
|
||||
"""Some mod for work with StableDiffusion. API KEY required!"""
|
||||
strings = {
|
||||
"name": "StableDiffusion",
|
||||
"_cfg_api_key": "Insert the StableDiffusionApi.com API Key",
|
||||
"_cfg_model": "Pass the AI model",
|
||||
"_cfg_bad_prompt": "Pass the bad prompt — is that what you don't want to see in the pic",
|
||||
"_cfg_debug": "Debug mode",
|
||||
"_cfg_samples": "Default quantity of images to generate",
|
||||
"_cfg_steps": "Steps — The higher the number, the more the image will be detailed",
|
||||
"_cfg_upscale": "Using upscale",
|
||||
"error": "<emoji document_id=6325579261763651444>⚠</emoji> <b>Some error occured!</b>\n\n<code>{}</code>",
|
||||
"key_required": "<b>API Key required!</b> Insert it in <code>.cfg StableDiffusion</code>",
|
||||
"done": "<emoji document_id=5327958075158568158>✅</emoji> <b>Image is generated!</b>\n\n",
|
||||
"debug": "<b>Model:</b> <code>{model}</code>\n<b>Prompt:</b> <code>{prompt}</code>\n" \
|
||||
"<b>Bad prompt:</b> <code>{negative}</code>\n<b>Steps:</b> <i>{steps}, {upsc}" \
|
||||
"upscaled using external AI{time}</i>",
|
||||
"not": "not ",
|
||||
"drawing": "<emoji document_id=5431456208487716895>🎨</emoji> <b>Image is drawing...</b>",
|
||||
"help": "<emoji document_id=5325762745574891391>🥹</emoji> <b>Help for</b> <code>StableDiffusion</code> <b>module</b>\n\n\n" \
|
||||
"<emoji document_id=5409309265460471937>1️⃣</emoji> <b>Configuration:</b>\nAll configuration in the config" \
|
||||
" - <code>.cfg StableDiffusion</code>\n\n\n<emoji document_id=5408970203562255606>2️⃣</emoji> <b>" \
|
||||
"Parameters and their description:</b>\n <code>api_key</code> is your personal access key to StableDiffusionAPI.com, " \
|
||||
" you can get it <a href='https://stablediffusionapi.com/settings/api'>here</a>\n\n <code>model</code> is the model to be generated (in config specifies which " \
|
||||
"models are available)\n\n <code>bad_prompt</code> - negative input. It is needed in order to remove from your " \
|
||||
"images what you don't wanna see\n\n <code>debug</code> - if value is <i>True</i>, the response will contain" \
|
||||
" information about the generated image(s) (model, prompt, bad_prompt, steps, etc.)\n <code>samples</code> — " \
|
||||
"number of images generated\n\n <code>steps</code> are <i>«steps»</i> . the higher the number, the more detailed" \
|
||||
" the image will be\n\n <code>upscale</code> - improved generation using AI\n\n\n<emoji document_id=" \
|
||||
"5406784224122384435>3️⃣</emoji> <b>Usage:</b>\nLet's suppose that you have finished the setup. Let's move on to use.\n" \
|
||||
"You need to use it like this: <code>.sd</code> <prompt>\nWhere <prompt> is whatever you wanna see on " \
|
||||
"the image"
|
||||
}
|
||||
|
||||
strings_ru = {
|
||||
"_cls_doc": "Какой-то модуль для работы с StableDiffusion. Нужен API KEY!",
|
||||
"_cfg_api_key": "Укажи свой API Key от StableDiffusionAPI.com",
|
||||
"_cfg_model": "Укажи модель",
|
||||
"_cfg_bad_prompt": "Укажи негативный ввод — то, что ты не хочешь видеть на изображении",
|
||||
"_cfg_debug": "Debug мод",
|
||||
"_cfg_samples": "Количество изображений по умолчанию для генерации",
|
||||
"_cfg_steps": "Шаги - чем выше число, тем больше детальнее будет изображение.",
|
||||
"_cfg_upscale": "Использование улучшения",
|
||||
"error": "<emoji document_id=6325579261763651444>⚠</emoji> <b>Произошла ошибка!</b>\n\n<code>{}</code>",
|
||||
"key_required": "<emoji document_id=6325579261763651444>⚠</emoji> <b>Нужен API Key!</b> Укажи его в <code>.cfg StableDiffusion</code>",
|
||||
"done": "<emoji document_id=5327958075158568158>✅</emoji> <b>Изображение сгенерировано!</b>\n\n",
|
||||
"debug": "<b>Модель:</b> <code>{model}</code>\n<b>Ввод:</b> <code>{prompt}</code>\n" \
|
||||
"<b>Негативный ввод:</b> <code>{negative}</code>\n<b>Шаги:</b> <i>{steps}, {upsc}" \
|
||||
"улучшено с использованием ИИ{time}</i>",
|
||||
"not": "не было ",
|
||||
"drawing": "<emoji document_id=5431456208487716895>🎨</emoji> <b>Рисую…</b>",
|
||||
"help": "<emoji document_id=5325762745574891391>🥹</emoji> <b>Помощь по модулю </b><code>StableDiffusion</code>\n\n\n" \
|
||||
"<emoji document_id=5409309265460471937>1️⃣</emoji> <b>Настройка</b>.\nВся настройка проводится в конфиге — " \
|
||||
"<code>.cfg StableDiffusion</code>\n\n\n<emoji document_id=5408970203562255606>2️⃣</emoji> <b>Параметры и их описание" \
|
||||
":</b>\n <code>api_key</code> — это ваш персональный ключ доступа к StableDiffusionAPI.com, его можно получить на" \
|
||||
" этом же сайте\n\n <code>model</code> — это модель для генерации (в конфиге указано, какие модели есть)\n\n" \
|
||||
" <code>bad_prompt</code> — негативный ввод. он нужен для того, чтобы убрать с ваших изображений то, " \
|
||||
"что вы не хотите видеть\n\n <code>debug</code> — если установлено <i>True</i>, в ответе будет информация" \
|
||||
" о генерируемом(-ых) изображении(-ях) (модель, prompt, bad_prompt, steps и т.д.)" \
|
||||
"\n\n <code>samples</code> — кол-во генерации изображений" \
|
||||
"\n\n <code>steps</code> — это <i>«шаги»</i>. чем выше число, тем детальнее будет изображение" \
|
||||
"\n\n <code>upscale</code> — улучшение генерации с помощью ИИ" \
|
||||
"\n\n\n<emoji document_id=5406784224122384435>3️⃣</emoji> <b>Использование</b> \nПредположим, что Вы закончили настройку. " \
|
||||
"Перейдём к использованию.\n\nИспользовать нужно так: <code>.sd</code> <prompt>\nГде <prompt> — что угодно" \
|
||||
", что вы хотите видеть на изображении"
|
||||
}
|
||||
|
||||
def __init__(self): # debug: bool, bad_prompt
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"api_key",
|
||||
None,
|
||||
lambda: self.strings("_cfg_api_key"),
|
||||
validator=loader.validators.Hidden()
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"model",
|
||||
"anything-v5",
|
||||
lambda: self.strings("_cfg_model"),
|
||||
validator=loader.validators.Choice([
|
||||
'abyssorangemix2nsfw', 'anything-v4', 'anything-v5',
|
||||
'anythingelse-v4', 'bro623jbfe32', 'cetusmix', 'cnwi74tjsdfw',
|
||||
'counterfeit-v20', 'counterfeit-v30', 'dark-sushi-25d',
|
||||
'disillusionmix', 'grapefruit-nsfw-anim', 'hanfu',
|
||||
'hc-a-mecha-musume-a', 'hc-kokkoro', 'hc-kyoka', 'hc-sailor-mercury',
|
||||
'majicmixfantasy', 'meinamix', 'meinapastel', 'night-sky-yozora-sty',
|
||||
'tmnd-mix', 'troi4bwiyt4', 'ttksuperspirit'
|
||||
])
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"bad_prompt",
|
||||
(
|
||||
"(bad_prompt:0.8), multiple persons, multiple views, extra hands,"
|
||||
" ugly, lowres, bad quality, blurry, disfigured, extra limbs,"
|
||||
" missing limbs, deep fried, cheap art, missing fingers, out of"
|
||||
" frame, cropped, bad art, face hidden, text, speech bubble,"
|
||||
" stretched, bad hands, error, extra digit, fewer digits, worst"
|
||||
" quality, low quality, normal quality, mutated, mutation,"
|
||||
" deformed, severed, dismembered, corpse, pubic, poorly drawn,"
|
||||
" (((deformed hands))), (((more than two hands))), (((deformed"
|
||||
" body))), ((((mutant)))), painting, extra fingers, mutated hands,"
|
||||
" poorly drawn hands, poorly drawn face, bad anatomy, bad"
|
||||
" proportions, cloned face, skinny, glitchy, double torso,"
|
||||
" extra arms, mangled fingers, missing lips, distorted face,"
|
||||
" extra legs"
|
||||
),
|
||||
lambda: self.strings("_cfg_bad_prompt"),
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"debug",
|
||||
False,
|
||||
lambda: self.strings("_cfg_debug"),
|
||||
validator=loader.validators.Boolean()
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"samples",
|
||||
1,
|
||||
lambda: self.strings("_cfg_samples"),
|
||||
validator=loader.validators.Integer(minimum=1, maximum=4),
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"steps",
|
||||
30,
|
||||
lambda: self.strings("_cfg_steps"),
|
||||
validator=loader.validators.Integer(minimum=1, maximum=50),
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"upscale",
|
||||
False,
|
||||
lambda: self.strings("_cfg_upscale"),
|
||||
validator=loader.validators.Boolean()
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def getFetch(self, url):
|
||||
payload = json.dumps({"key": self.config['api_key']})
|
||||
headers = {"Content-Type": "application/json"}
|
||||
r = (await utils.run_sync(
|
||||
requests.post,
|
||||
url,
|
||||
headers=headers,
|
||||
data=payload
|
||||
)).json()
|
||||
|
||||
if r.get('status') == "success":
|
||||
return r['output']
|
||||
else:
|
||||
return (await self.getFetch(url))
|
||||
|
||||
|
||||
@loader.command(
|
||||
ru_doc="— помощь по использованию и настройке модуля",
|
||||
alias="sdh"
|
||||
)
|
||||
async def sdhelpcmd(self, message: Message):
|
||||
"""— help on using and configure the module"""
|
||||
await utils.answer(
|
||||
message,
|
||||
response=self.strings['help']
|
||||
)
|
||||
|
||||
|
||||
@loader.command(
|
||||
ru_doc="<prompt> — генерация изобраения с использованием StableDiffusion API."
|
||||
)
|
||||
async def sdcmd(self, message: Message):
|
||||
"""<prompt> — generate an image using StableDiffusion API"""
|
||||
if not self.config['api_key']:
|
||||
await utils.answer(
|
||||
message,
|
||||
self.strings['key_required']
|
||||
)
|
||||
return
|
||||
|
||||
await utils.answer(
|
||||
message,
|
||||
response=self.strings['drawing']
|
||||
)
|
||||
prompt = utils.get_args_raw(message)
|
||||
|
||||
url = "https://stablediffusionapi.com/api/v3/dreambooth"
|
||||
payload = json.dumps({
|
||||
"key": self.config['api_key'],
|
||||
"model_id": self.config['model'],
|
||||
"prompt": prompt,
|
||||
"negative_prompt": self.config['bad_prompt'],
|
||||
"width": "512",
|
||||
"height": "512",
|
||||
"samples": self.config['samples'],
|
||||
"num_inference_steps": self.config['steps'],
|
||||
"safety_checker": "no",
|
||||
"enhance_prompt": "yes",
|
||||
"seed": None,
|
||||
"guidance_scale": 7.5,
|
||||
"multi_lingual": "no",
|
||||
"panorama": "no",
|
||||
"self_attention": "no",
|
||||
"upscale": "yes" if self.config['upscale'] else "no",
|
||||
"embeddings": "embeddings_model_id",
|
||||
"lora": "lora_model_id",
|
||||
"webhook": None,
|
||||
"track_id": None
|
||||
})
|
||||
headers = {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
r = (await utils.run_sync(requests.post, url, headers=headers, data=payload)).json()
|
||||
|
||||
if r.get('status') == "error":
|
||||
await utils.answer(
|
||||
message,
|
||||
response=self.strings['error'].format(r)
|
||||
)
|
||||
return
|
||||
|
||||
if r.get('output'):
|
||||
out = self.strings['done']
|
||||
if self.config['debug']:
|
||||
out += self.strings['debug'].format(
|
||||
model=r['meta']['model_id'],
|
||||
prompt=r['meta']['prompt'],
|
||||
negative=r['meta']['negative_prompt'],
|
||||
steps=r['meta']['steps'],
|
||||
upsc=self.strings['not'] if not self.config['upscale'] else "",
|
||||
time=f", {round(r['generationTime'], 2)}s"
|
||||
)
|
||||
imgs = []
|
||||
for i in r['output']:
|
||||
img = (await utils.run_sync(
|
||||
requests.get,
|
||||
i
|
||||
)).content
|
||||
imgs.append(img)
|
||||
await utils.answer_file(
|
||||
message,
|
||||
file=imgs,
|
||||
caption=out
|
||||
)
|
||||
elif r.get('status') == "processing":
|
||||
out = self.strings['done']
|
||||
if self.config['debug']:
|
||||
out += self.strings['debug'].format(
|
||||
model=r['meta']['model_id'],
|
||||
prompt=r['meta']['prompt'],
|
||||
negative=r['meta']['negative_prompt'],
|
||||
steps=r['meta']['steps'],
|
||||
upsc=self.strings['not'] if not self.config['upscale'] else "",
|
||||
time=""
|
||||
)
|
||||
rr = await self.getFetch(r)
|
||||
imgs = []
|
||||
for i in rr['output']:
|
||||
img = (await utils.run_sync(
|
||||
requests.get,
|
||||
i
|
||||
)).content
|
||||
imgs.append(img)
|
||||
await utils.answer_file(
|
||||
message,
|
||||
file=imgs,
|
||||
caption=out
|
||||
)
|
||||
else:
|
||||
await utils.answer(
|
||||
message,
|
||||
response=self.strings['error'].format(r)
|
||||
)
|
||||
97
idiotcoders/idiotmodules/timer.py
Normal file
97
idiotcoders/idiotmodules/timer.py
Normal file
@@ -0,0 +1,97 @@
|
||||
# meta pic: https://static.whypodg.me/mods!timer.png
|
||||
# meta banner: https://mods.whypodg.me/badges/timer.jpg
|
||||
# meta developer: @idiotcoders
|
||||
# scope: hikka_only
|
||||
# scope: hikka_min 1.2.10
|
||||
|
||||
import re
|
||||
import datetime
|
||||
|
||||
from hikkatl.types import Message
|
||||
from .. import loader, utils
|
||||
|
||||
|
||||
@loader.tds
|
||||
class TimerMod(loader.Module):
|
||||
"""Module that shows the time before an event"""
|
||||
strings = {
|
||||
"name": "Timer",
|
||||
"_cfg_msg": "Custom message for command .time\nMay contain {date} — your custom date",
|
||||
"_cfg_date": "Custom date",
|
||||
"_lang": "en",
|
||||
"wrong_date": "<emoji document_id=5321493651161881544>❗</emoji> <b>You pass the wrong date in config!</b> Change it on <code>.cfg Timer</code>\n\nThe reason may be that this date has already passed",
|
||||
"default_msg": "<emoji document_id=6327819143043090120>🎄</emoji> <b>Until New Year's, there are {date}</b>\n<emoji document_id=5269693399224557532>🥰</emoji> <i>Waiting for the New Year surrounded by friends</i>"
|
||||
}
|
||||
|
||||
strings_ru = {
|
||||
"_cls_doc": "Модуль, показывающий время до какого-либо события",
|
||||
"_cfg_msg": "Кастомное сообщение для команды .time\nМожет содержать ключевое слово {date} — твою кастомную дату",
|
||||
"_cfg_date": "Кастомная дата",
|
||||
"_lang": "ru",
|
||||
"wrong_date": "<emoji document_id=5321493651161881544>❗</emoji> <b>Неправильно указана дата в конфиге!</b> Измени её в <code>.cfg Timer</code>\n\nПричиной может быть то, что эта дата уже прошла",
|
||||
"default_msg": "<emoji document_id=6327819143043090120>🎄</emoji> <b>До нового года осталось {date}</b>\n<emoji document_id=5269693399224557532>🥰</emoji> <i>Жду НГ в окружении друзей</i>"
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"date",
|
||||
"31.12.2023",
|
||||
lambda: self.strings("_cfg_date"),
|
||||
validator=loader.validators.RegExp(
|
||||
regex=r"^\d{1,2}\.\d{1,2}\.\d{4}$"
|
||||
)
|
||||
),
|
||||
loader.ConfigValue(
|
||||
"msg",
|
||||
self.strings["default_msg"],
|
||||
lambda: self.strings("_cfg_msg"),
|
||||
validator=loader.validators.String()
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def pluralForm(self, c, vs):
|
||||
c = abs(c)
|
||||
if c % 10 == 1 and c % 100 != 11:
|
||||
var = 0
|
||||
elif 2 <= c % 10 <= 4 and (c % 100 < 10 or c % 100 >= 20):
|
||||
var = 1
|
||||
else:
|
||||
var = 2
|
||||
return f"{c} {vs[var]}"
|
||||
|
||||
|
||||
@loader.command(
|
||||
ru_doc="— показать, сколько осталось до <чего-либо>"
|
||||
)
|
||||
async def timecmd(self, message: Message):
|
||||
"""— show how much time is left before the event"""
|
||||
d = str(self.config["date"]).split(".")
|
||||
msg = str(self.config["msg"])
|
||||
|
||||
date = datetime.datetime(int(d[2]), int(d[1]), int(d[0]))
|
||||
now = datetime.datetime.now()
|
||||
|
||||
if date < now:
|
||||
await utils.answer(message, self.strings["wrong_date"])
|
||||
return
|
||||
|
||||
t = abs(date-now)
|
||||
|
||||
if self.strings("_lang") == "ru":
|
||||
d = await self.pluralForm(t.days, ["день", "дня", "дней"])
|
||||
h = await self.pluralForm(t.seconds//3600, ["час", "часа", "часов"])
|
||||
m = await self.pluralForm(t.seconds//60%60, ["минута", "минуты", "минут"])
|
||||
s = await self.pluralForm(t.seconds%60, ["секунда", "секунды", "секунд"])
|
||||
else:
|
||||
d = str(t.days) + (" day" if t.days == 1 else " days")
|
||||
h = str(t.seconds//3600) + (" hour" if t.seconds//3600 == 1 else " hours")
|
||||
m = str(t.seconds//60%60) + (" minute" if t.seconds//60%60 == 1 else " minutes")
|
||||
s = str(t.seconds%60) + (" second" if t.seconds%60 == 1 else " seconds")
|
||||
|
||||
time = f"{d}, {h}, {m}, {s}"
|
||||
await utils.answer(
|
||||
message,
|
||||
self.config["msg"].format(date=time)
|
||||
)
|
||||
109
idiotcoders/idiotmodules/toadbot.py
Normal file
109
idiotcoders/idiotmodules/toadbot.py
Normal file
@@ -0,0 +1,109 @@
|
||||
# meta pic: https://static.whypodg.me/mods!toadbot.png
|
||||
# meta banner: https://mods.whypodg.me/badges/toadbot.jpg
|
||||
# meta developer: @idiotcoders
|
||||
# scope: hikka_only
|
||||
# scope: hikka_min 1.2.10
|
||||
|
||||
|
||||
import asyncio
|
||||
from .. import loader, utils
|
||||
from telethon.tl.types import Message
|
||||
|
||||
|
||||
@loader.tds
|
||||
class ToadBotMod(loader.Module):
|
||||
"""Модуль для ухода за вашей жабой, когда вам лень или же когда у вас нет на это времени
|
||||
"""
|
||||
"""
|
||||
Module for @toadbot, use it, when you have no time to take care of your frog or you are lazy
|
||||
"""
|
||||
|
||||
strings = {
|
||||
"name": "ToadBot",
|
||||
"jobs": "Choose a job where your toad will work.",
|
||||
"eats": "Enable toad auto-feeding?"
|
||||
}
|
||||
|
||||
strings = {
|
||||
"name": "ToadBot",
|
||||
"_cls_doc": "Модуль для @toadbot, используйте его, когда у вас нет времени, чтобы ухаживать за жабой или вам лень",
|
||||
"jobs": "Выберите работу на которую будет ходить ваша жаба.",
|
||||
"eats": "Включить авто кормёжку жабы?"
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"jobs",
|
||||
"Поход в столовую",
|
||||
lambda: self.strings("jobs"),
|
||||
validator=loader.validators.Choice(["Поход в столовую", "Работа грабитель", "Работа крупье"]),
|
||||
))
|
||||
@loader.command()
|
||||
async def frogcmd(self, message):
|
||||
"""Уход за жабой | чтобы остановить пиши 'Уход за жабой стоп'"""
|
||||
if message.is_private:
|
||||
await utils.answer(message, "❌| <b>Команда не может быть запущена в личных сообщениях.</b>")
|
||||
return
|
||||
|
||||
elif self.get("job") is None or self.get("job") is False:
|
||||
self.set("job", True)
|
||||
await utils.answer(message, "✅| <b>Авто-уход за жабой был успешно запущен.</b>")
|
||||
|
||||
job = self.config["jobs"]
|
||||
if job == "Поход в столовую":
|
||||
while self.get("job"):
|
||||
await message.respond("Поход в столовую")
|
||||
await asyncio.sleep(7200)
|
||||
await message.respond("Забрать жабу с работы")
|
||||
await asyncio.sleep(21600)
|
||||
return
|
||||
elif job == "Работа грабитель":
|
||||
while self.get("job"):
|
||||
await message.respond("Работа грабитель")
|
||||
await asyncio.sleep(7200)
|
||||
await message.respond("Забрать жабу с работы")
|
||||
await asyncio.sleep(21600)
|
||||
return
|
||||
elif job == "Работа крупье":
|
||||
while self.get("job"):
|
||||
await message.respond("Работа крупье")
|
||||
await asyncio.sleep(7200)
|
||||
await message.respond("Забрать жабу с работы")
|
||||
await asyncio.sleep(21600)
|
||||
return
|
||||
|
||||
@loader.command()
|
||||
async def eatcmd(self, message):
|
||||
"""Кормёжка жабы | чтобы остановить используйте 'корм стоп'"""
|
||||
if message.is_private:
|
||||
await utils.answer(message, "❌| <b>Команда не может быть запущена в личных сообщениях.</b>")
|
||||
return
|
||||
|
||||
elif self.get("eat") is None or self.get("eat") is True:
|
||||
self.set("eat", False)
|
||||
await utils.answer(message, "<b>Авто-кормежка была успешно остановлена.</b>")
|
||||
return
|
||||
elif self.get("eat") is None or self.get("eat") is False:
|
||||
self.set("eat", True)
|
||||
await utils.answer(message, "✅| <b>Авто-кормежка жабы запущена.</b>")
|
||||
|
||||
eat = self.get("eat")
|
||||
if eat == True:
|
||||
while self.get("eat"):
|
||||
await message.respond("Покормить жабу")
|
||||
await asyncio.sleep(0.5)
|
||||
await message.respond("Жаба успешно покормлена.\n\nСледующая команда будет произведена через 12 часов.")
|
||||
await asyncio.sleep(43200)
|
||||
|
||||
@loader.watcher()
|
||||
async def watcher(self, message):
|
||||
if not getattr(message, "out", False):
|
||||
return
|
||||
if message.out:
|
||||
if message.raw_text.lower() == "корм стоп":
|
||||
self.set("eat", False)
|
||||
await utils.answer(message, "✅| <b>Авто кормёжка жабы успешно остановлена.</b>")
|
||||
elif message.raw_text.lower() == "уход за жабой стоп":
|
||||
self.set("job", False)
|
||||
await utils.answer(message, "✅| <b>Авто уход за жабой успешно остановлен.</b>")
|
||||
247
idiotcoders/idiotmodules/yoomoney.py
Normal file
247
idiotcoders/idiotmodules/yoomoney.py
Normal file
@@ -0,0 +1,247 @@
|
||||
# meta pic: https://static.whypodg.me/mods!yoomoney.png
|
||||
# meta banner: https://mods.whypodg.me/badges/yoomoney.jpg
|
||||
# meta developer: @idiotcoders
|
||||
# scope: hikka_only
|
||||
# scope: hikka_min 1.2.10
|
||||
# requires: yoomoney
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import logging
|
||||
import requests
|
||||
import yoomoney
|
||||
|
||||
from .. import loader, utils
|
||||
from hikkatl.types import Message
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@loader.tds
|
||||
class YooMoneyMod(loader.Module):
|
||||
"""Yoomoney Module."""
|
||||
|
||||
strings = {
|
||||
"name": "YooMoney",
|
||||
"_cfg_token": "Pass the API token from your YooMoney account. If you don't know how to get it, use the .yauth command",
|
||||
"need_auth": "<emoji document_id=5312526098750252863>❌</emoji> <b>Call</b> <code>.yauth</code> <b>before using this action.</b>",
|
||||
"auth": (
|
||||
"🔐 <b>Follow the link in the button, approve request, then</b> <code>.ycode https://...</code> <b>with redirected url</b>\n\n"
|
||||
"<b>As example:</b> <code>.ycode https://yoomoney.whypodg.me/?code=1234zxcv5678</code> <b>OR</b> <code>.ycode 1234zxcv5678</code>"
|
||||
),
|
||||
"yoomoney_error": (
|
||||
"<emoji document_id=5312526098750252863>❌</emoji> <b>An YooMoney API error has occured!</b>\n\n"
|
||||
"<b>API returned this response:</b>\n<code>{}</code>"
|
||||
),
|
||||
"successful_auth": "<emoji document_id=5280757711720423435>💜</emoji> <b>Auth successful</b>",
|
||||
"follow_me": "Follow me",
|
||||
"statuses": {
|
||||
"anonymous": "<emoji document_id=5371017798065592581>👻</emoji> <b>Anonymous</b>",
|
||||
"named": "<emoji document_id=5370900820336319679>🥰</emoji> <b>Reviewed</b>",
|
||||
"identified": "<emoji document_id=5388929052935462187>😎</emoji> <b>Identified</b>"
|
||||
},
|
||||
"out": (
|
||||
"<emoji document_id=5280757711720423435>💜</emoji> <b>Your YooMoney wallet info:</b>\n\n"
|
||||
"<emoji document_id=5974526806995242353>🆔</emoji> <b>Wallet ID:</b> <code>{id}</code>\n"
|
||||
"<emoji document_id=5850654130497916523>✅️</emoji> <b>Wallet status:</b> {status}\n"
|
||||
"<emoji document_id=5357315181649076022>📂</emoji> <b>Wallet type:</b> <code>{type}</code>\n"
|
||||
"<emoji document_id=5328236964564967681>🤑</emoji> <b>Balance:</b> <code>{balance}₽</code>"
|
||||
),
|
||||
"payme": "<b>📄 {}\n<a href='{}'>Pay {} RUB 💳</a></b>",
|
||||
"args": "<b>🚫 Incorrect args</b>"
|
||||
}
|
||||
|
||||
strings_ru = {
|
||||
"_cfg_token": "Введите API токен ЮMoney аккаунта. Если не знаешь, как его получить — используй команду .yauth",
|
||||
"need_auth": (
|
||||
"<emoji document_id=5312526098750252863>❌</emoji> <b>Выполни</b> <code>.yauth</code> "
|
||||
"<b>перед выполнением этого действия.</b>"
|
||||
),
|
||||
"auth": (
|
||||
"🔐 <b>Перейдите по ссылке в кнопке, одобрите запрос, затем используйте</b> <code>.ycode https://...</code> "
|
||||
"<b>с URL-адресом, куда вас перенаправило</b>\n\n"
|
||||
"<b>Пример:</b> <code>.ycode https://yoomoney.whypodg.me/?code=1234zxcv5678</code> <b>ИЛИ</b> <code>.ycode 1234zxcv5678</code>"
|
||||
),
|
||||
"yoomoney_error": (
|
||||
"<emoji document_id=5312526098750252863>❌</emoji> <b>Произошла ошибка ЮMoney!</b>\n\n"
|
||||
"<b>API вернуло такой ответ:</b>\n<code>{}</code>"
|
||||
),
|
||||
"successful_auth": "<emoji document_id=5280757711720423435>💜</emoji> <b>Успешная аутентификация</b>",
|
||||
"follow_me": "Перейди по мне",
|
||||
"statuses": {
|
||||
"anonymous": "<emoji document_id=5371017798065592581>👻</emoji> <b>Анонимный</b>",
|
||||
"named": "<emoji document_id=5370900820336319679>🥰</emoji> <b>Именной</b>",
|
||||
"identified": "<emoji document_id=5388929052935462187>😎</emoji> <b>Идентифицированный</b>"
|
||||
},
|
||||
"out": (
|
||||
"<emoji document_id=5280757711720423435>💜</emoji> <b>Информация о ЮMoney кошельке:</b>\n\n"
|
||||
"<emoji document_id=5974526806995242353>🆔</emoji> <b>Номер кошелька:</b> <code>{id}</code>\n"
|
||||
"<emoji document_id=5850654130497916523>✅️</emoji> <b>Статус кошелька:</b> {status}\n"
|
||||
"<emoji document_id=5357315181649076022>📂</emoji> <b>Тип кошелька:</b> <code>{type}</code>\n"
|
||||
"<emoji document_id=5328236964564967681>🤑</emoji> <b>Баланс:</b> <code>{balance}₽</code>"
|
||||
),
|
||||
"payme": "<b>📄 {}\n<a href='{}'>Оплатить {} RUB 💳</a></b>",
|
||||
"args": "<b>🚫 Неверные аргументы</b>"
|
||||
}
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self.config = loader.ModuleConfig(
|
||||
loader.ConfigValue(
|
||||
"YooMoneyToken",
|
||||
None,
|
||||
lambda: self.strings["_cfg_token"],
|
||||
validator=loader.validators.Hidden(),
|
||||
)
|
||||
)
|
||||
|
||||
async def client_ready(self, client, db):
|
||||
self.yoom = {
|
||||
"id": "C801B504CF3753A05164548B116221C72FDE40D4D4A9297821A4F2FA3D7B5612",
|
||||
"secret": "9DE4A15EAE2C063A2DFA4196371EB9655923503B728FFA9A76909B90B4815CB13A0976CB8C79E9235B48C165E026423B2C598EB31CB2AB263B218F50AEA471CE"
|
||||
}
|
||||
self.yclient = None
|
||||
|
||||
if self.config['YooMoneyToken']:
|
||||
try:
|
||||
self.yclient = yoomoney.Client(self.config['YooMoneyToken'])
|
||||
except yoomoney.exceptions.InvalidToken:
|
||||
pass
|
||||
|
||||
|
||||
@loader.command(
|
||||
ru_doc="<сумма> <назначение> ; <комментарий> 👉 Отправить ссылку для перевода\n" \
|
||||
"E.g: .ypay 100 На кофе ; Бро, купи мне кофе, вот ссылка для перевода"
|
||||
)
|
||||
async def ypaycmd(self, message: Message):
|
||||
"""<sum> <title> ; <comment> 👉 Send payment link
|
||||
E.g: .ypay 100 For a coffee ; Bro, buy me a coffee, here is the link
|
||||
"""
|
||||
args = utils.get_args_raw(message)
|
||||
try:
|
||||
amount, titlecomm = args.split(maxsplit=1)
|
||||
amount = int(amount)
|
||||
title, comment = titlecomm.split(";", 1)
|
||||
if amount < 2:
|
||||
await utils.answer(message, self.strings("args"))
|
||||
return
|
||||
except Exception:
|
||||
await utils.answer(message, self.strings("args"))
|
||||
return
|
||||
|
||||
quickpay = yoomoney.Quickpay(
|
||||
receiver=self.yclient.account_info().account,
|
||||
quickpay_form="shop",
|
||||
targets=title.strip(),
|
||||
paymentType="SB",
|
||||
sum=amount,
|
||||
label="Money transfer to an individual",
|
||||
)
|
||||
|
||||
await utils.answer(
|
||||
message,
|
||||
self.strings("payme").format(
|
||||
utils.escape_html(comment.strip()),
|
||||
quickpay.redirected_url,
|
||||
amount,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@loader.command(
|
||||
ru_doc="👉 Узнать информацию вашего кошелька",
|
||||
alias="yw"
|
||||
)
|
||||
async def ywalletcmd(self, message: Message):
|
||||
"""👉 Get YooMoney wallet info"""
|
||||
if not self.config['YooMoneyToken']:
|
||||
await utils.answer(
|
||||
message,
|
||||
self.strings["need_auth"]
|
||||
)
|
||||
return
|
||||
|
||||
try:
|
||||
self.yclient = yoomoney.Client(self.config['YooMoneyToken'])
|
||||
user = self.yclient.account_info()
|
||||
except yoomoney.exceptions.InvalidToken:
|
||||
await utils.answer(
|
||||
message,
|
||||
self.strings['need_auth']
|
||||
)
|
||||
return
|
||||
|
||||
status = self.strings['statuses'][user.account_status]
|
||||
|
||||
await utils.answer(
|
||||
message,
|
||||
self.strings['out'].format(id=user.account, status=status, type=user.account_type, balance=round(user.balance, 2))
|
||||
)
|
||||
|
||||
|
||||
@loader.command(
|
||||
ru_doc="👉 Первый этап авторизации"
|
||||
)
|
||||
async def yauthcmd(self, message: Message):
|
||||
"""👉 First stage of auth"""
|
||||
scopes = [
|
||||
"account-info", "operation-history"#, "operation-details",
|
||||
#"incoming-transfers", "payment-p2p", "payment-shop"
|
||||
]
|
||||
|
||||
a = (await utils.run_sync(
|
||||
requests.post,
|
||||
f"https://yoomoney.ru/oauth/authorize?client_id={self.yoom['id']}&response_type=code" \
|
||||
f"&redirect_uri=https://yoomoney.whypodg.me&scope={' '.join(scopes)}",
|
||||
headers = {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
)).url
|
||||
|
||||
await self.inline.form(
|
||||
text=self.strings['auth'],
|
||||
message=message,
|
||||
reply_markup=[{
|
||||
"text": self.strings['follow_me'],
|
||||
"url": a
|
||||
}]
|
||||
)
|
||||
|
||||
|
||||
@loader.command(
|
||||
ru_doc="👉 Второй этап авторизации"
|
||||
)
|
||||
async def ycodecmd(self, message: Message):
|
||||
"""👉 Second stage of auth"""
|
||||
args = utils.get_args_raw(message)
|
||||
code = list(args.partition("code="))
|
||||
code = str(args) if not code[2] else code[2]
|
||||
|
||||
req = (await utils.run_sync(
|
||||
requests.post,
|
||||
f"https://yoomoney.ru/oauth/token?code={code}&client_id={self.yoom['id']}&client_secret={self.yoom['secret']}" \
|
||||
f"&grant_type=authorization_code&redirect_uri=https://yoomoney.whypodg.me",
|
||||
headers = {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
)).json()
|
||||
|
||||
if not req.get("access_token"):
|
||||
err = json.dumps(req, indent=4, ensure_ascii=False)
|
||||
await utils.answer(
|
||||
message,
|
||||
self.strings['yoomoney_error'].format(err)
|
||||
)
|
||||
return
|
||||
|
||||
self.config['YooMoneyToken'] = req['access_token']
|
||||
await utils.answer(
|
||||
message,
|
||||
self.strings['successful_auth']
|
||||
)
|
||||
|
||||
try:
|
||||
self.yclient = yoomoney.Client(self.config['YooMoneyToken'])
|
||||
except yoomoney.exceptions.InvalidToken:
|
||||
pass
|
||||
Reference in New Issue
Block a user