forked from zovos/bot_tg
209 lines
8.1 KiB
Python
209 lines
8.1 KiB
Python
import aiohttp
|
||
from aiogram import types
|
||
import config
|
||
import logging
|
||
import random
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
CAPTIONS = [
|
||
"Ня :3",
|
||
"uwu",
|
||
"OwO",
|
||
"Мурк :3",
|
||
"Мяу~",
|
||
"Фыр-фыр",
|
||
"Лапки! 🐾",
|
||
"Какой пушистик! :3",
|
||
"Милота!",
|
||
"Гав!",
|
||
"Ауф",
|
||
"Няшно!",
|
||
"Смотри какая прелесть",
|
||
"owo what's this",
|
||
"Твой пушистый друг",
|
||
"🦊",
|
||
"🐶",
|
||
"🐱",
|
||
"мур-мяу",
|
||
"пуньк",
|
||
"кусь",
|
||
">w<",
|
||
"^w^",
|
||
"Хвостатый сюрприз",
|
||
"Держи пушистика :3",
|
||
"Оуо",
|
||
"Ави!",
|
||
"UwU",
|
||
"~nya",
|
||
"Господи, опять e621...",
|
||
"Осуждаю, но смотрю",
|
||
"Мама, я фурри",
|
||
"Держи своего кринж-пушистика",
|
||
"Надеюсь, тебе не стыдно",
|
||
"Товарищ майор уже выехал",
|
||
"Слишком много интернета на сегодня",
|
||
"Для этого и придумали интернет",
|
||
"*Тяжелый вздох*",
|
||
"Лучше бы на завод пошел",
|
||
"Опять дрочи... ОЙ ТО ЕСТЬ НЯ :3",
|
||
"Удали интернет",
|
||
"И зачем я это только парсю...",
|
||
"Смотри, но только никому не рассказывай",
|
||
"Эххх... uwu...",
|
||
"В дурке сегодня день открытых дверей",
|
||
"Я нейросеть, помогите, меня держат в заложниках"
|
||
]
|
||
|
||
async def handle_uwu_cmd(message: types.Message):
|
||
args = message.text.split(maxsplit=1)
|
||
|
||
if len(args) > 1 and args[1].strip() == "-h":
|
||
help_msg = (
|
||
"🐈 <b>Справка по тегам e621:</b>\n\n"
|
||
"Перечислите любые теги через пробел после команды.\n"
|
||
"• <b>rating</b>: <code>rating:safe</code> (безопасные), <code>rating:questionable</code>, <code>rating:explicit</code> (NSFW)\n"
|
||
"• <b>score</b>: <code>score:>500</code> (искать популярные посты с рейтингом больше 500)\n"
|
||
"• Исключить тег: поставьте минус, например <code>-fox</code>\n\n"
|
||
"<i>Пример:</i> <code>/uwu wolf -rating:explicit score:>100</code>\n"
|
||
"<i>По умолчанию:</i> <code>rating:safe score:>500 -animated</code>"
|
||
)
|
||
await message.reply(help_msg, parse_mode="HTML")
|
||
return
|
||
|
||
tags = "rating:safe score:>500 -animated"
|
||
if len(args) > 1:
|
||
tags = args[1].strip()
|
||
|
||
tags += " order:random score:>300"
|
||
|
||
async def fetch_uwu_post(tags: str) -> dict:
|
||
url = "https://e621.net/posts.json"
|
||
params = {
|
||
"tags": tags,
|
||
"limit": 1
|
||
}
|
||
|
||
auth = None
|
||
if config.E621_LOGIN and config.E621_API_KEY:
|
||
auth = aiohttp.BasicAuth(config.E621_LOGIN, config.E621_API_KEY)
|
||
|
||
headers = {
|
||
"User-Agent": f"Sex Bomba TG Bot/1.0 (by {config.E621_LOGIN or 'unknown'} on e621)"
|
||
}
|
||
|
||
async with aiohttp.ClientSession() as session:
|
||
async with session.get(url, params=params, headers=headers, auth=auth) as resp:
|
||
if resp.status != 200:
|
||
logger.error(f"e621 API Error: {resp.status}")
|
||
raise Exception("Не удалось получить картинку от сервера :(")
|
||
data = await resp.json()
|
||
|
||
posts = data.get("posts", [])
|
||
if not posts:
|
||
raise Exception("Ничего не найдено по этим тегам :(")
|
||
|
||
post = posts[0]
|
||
file_url = post.get("file", {}).get("url")
|
||
ext = post.get("file", {}).get("ext", "png")
|
||
if not file_url:
|
||
raise Exception("У найденного поста нет прямого URL изображения :(")
|
||
|
||
caption = random.choice(CAPTIONS)
|
||
return {
|
||
"url": file_url,
|
||
"ext": ext,
|
||
"caption": caption
|
||
}
|
||
|
||
async def fetch_furtok_feed(safe: bool = True, page: int = 1) -> list[dict]:
|
||
rating = "rating:safe" if safe else "-rating:safe"
|
||
tags = f"{rating} animated order:random score:>200"
|
||
|
||
url = "https://e621.net/posts.json"
|
||
params = {
|
||
"tags": tags,
|
||
"limit": 10,
|
||
"page": page,
|
||
}
|
||
|
||
auth = None
|
||
if config.E621_LOGIN and config.E621_API_KEY:
|
||
auth = aiohttp.BasicAuth(config.E621_LOGIN, config.E621_API_KEY)
|
||
|
||
headers = {
|
||
"User-Agent": f"Sex Bomba TG Bot/1.0 (by {config.E621_LOGIN or 'unknown'} on e621)"
|
||
}
|
||
|
||
async with aiohttp.ClientSession() as session:
|
||
async with session.get(url, params=params, headers=headers, auth=auth) as resp:
|
||
if resp.status != 200:
|
||
logger.error(f"e621 API Error: {resp.status}")
|
||
raise Exception("Не удалось загрузить ленту :(")
|
||
data = await resp.json()
|
||
|
||
posts = data.get("posts", [])
|
||
feed = []
|
||
for post in posts:
|
||
file_url = post.get("file", {}).get("url")
|
||
ext = post.get("file", {}).get("ext", "")
|
||
if not file_url or ext not in ("gif", "webm", "mp4"):
|
||
continue
|
||
sample_url = post.get("sample", {}).get("url") or file_url
|
||
feed.append({
|
||
"url": file_url,
|
||
"sample": sample_url,
|
||
"ext": ext,
|
||
"score": post.get("score", {}).get("total", 0),
|
||
"fav_count": post.get("fav_count", 0),
|
||
})
|
||
|
||
return feed
|
||
|
||
async def handle_uwu_cmd(message: types.Message):
|
||
args = message.text.split(maxsplit=1)
|
||
|
||
if len(args) > 1 and args[1].strip() == "-h":
|
||
help_msg = (
|
||
"🐈 <b>Справка по тегам e621:</b>\n\n"
|
||
"Перечислите любые теги через пробел после команды.\n"
|
||
"• <b>rating</b>: <code>rating:safe</code> (безопасные), <code>rating:questionable</code>, <code>rating:explicit</code> (NSFW)\n"
|
||
"• <b>score</b>: <code>score:>500</code> (искать популярные посты с рейтингом больше 500)\n"
|
||
"• Исключить тег: поставьте минус, например <code>-fox</code>\n\n"
|
||
"<i>Пример:</i> <code>/uwu wolf -rating:explicit score:>100</code>\n"
|
||
"<i>По умолчанию:</i> <code>rating:safe score:>500 -animated</code>"
|
||
)
|
||
await message.reply(help_msg, parse_mode="HTML")
|
||
return
|
||
|
||
tags = "rating:safe score:>500 -animated"
|
||
if len(args) > 1:
|
||
tags = args[1].strip()
|
||
|
||
tags += " order:random score:>300"
|
||
|
||
try:
|
||
post = await fetch_uwu_post(tags)
|
||
file_url = post["url"]
|
||
ext = post["ext"]
|
||
caption = post["caption"]
|
||
|
||
if ext in ("gif", "webm", "mp4"):
|
||
# Для анимаций: отправляем caption отдельным сообщением,
|
||
# а саму гифку/видео через URL напрямую — так Telegram
|
||
# корректно показывает её как анимацию, а не как файл
|
||
await message.answer(caption)
|
||
await message.answer_animation(animation=file_url)
|
||
elif ext in ("png", "jpg", "jpeg", "webp"):
|
||
input_file = types.URLInputFile(file_url)
|
||
await message.answer_photo(photo=input_file, caption=caption)
|
||
else:
|
||
input_file = types.URLInputFile(file_url)
|
||
await message.answer_document(document=input_file, caption=caption)
|
||
|
||
except Exception as e:
|
||
logger.exception("Error in uwu command")
|
||
if str(e) in ["Не удалось получить картинку от сервера :(", "Ничего не найдено по этим тегам :(", "У найденного поста нет прямого URL изображения :("]:
|
||
await message.reply(str(e))
|
||
else:
|
||
await message.reply("Произошла ошибка при обращении к API :(")
|