1
0
Fork 0
forked from zovos/bot_tg

some fix for nude

This commit is contained in:
q 2026-04-10 11:17:45 +03:00
parent 06d97cbff0
commit 7afd8ca216

View file

@ -1,108 +1,159 @@
import aiohttp
from aiogram import types
import config
import logging import logging
import random import random
import re from pathlib import PurePosixPath
from urllib.parse import urlparse
import aiohttp
from aiogram import types
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
CAPTIONS = [ CAPTIONS = [
"Hot stuff 🔥", "Hot stuff 🔥",
"Sexy content 😏" "Sexy content 😏",
] ]
LESAINT_POSTS_API = "https://lesaintdesseins.fr/wp-json/wp/v2/posts"
LESAINT_REFERER = "https://lesaintdesseins.fr/"
LATEST_POSTS_LIMIT = 30
REQUEST_HEADERS = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/124.0.0.0 Safari/537.36"
),
"Accept": "application/json,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Referer": LESAINT_REFERER,
}
def _extract_photo_candidates(posts: list[dict]) -> list[dict]:
candidates = []
for post in posts:
embedded = post.get("_embedded") or {}
media_items = embedded.get("wp:featuredmedia") or []
for media in media_items:
if media.get("media_type") != "image":
continue
media_details = media.get("media_details") or {}
sizes = media_details.get("sizes") or {}
image_url = (
(sizes.get("full") or {}).get("source_url")
or media.get("source_url")
)
if not image_url:
continue
candidates.append(
{
"image_url": image_url,
"post_url": post.get("link", LESAINT_REFERER),
"title": (post.get("title") or {}).get("rendered", "").strip(),
}
)
break
return candidates
def _guess_filename(image_url: str) -> str:
parsed = urlparse(image_url)
filename = PurePosixPath(parsed.path).name or "nude.jpg"
if "." not in filename:
filename = f"{filename}.jpg"
return filename
async def _fetch_latest_photo_candidates(session: aiohttp.ClientSession) -> list[dict]:
params = {
"per_page": str(LATEST_POSTS_LIMIT),
"orderby": "date",
"order": "desc",
"_embed": "wp:featuredmedia",
}
async with session.get(LESAINT_POSTS_API, params=params, headers=REQUEST_HEADERS) as resp:
if resp.status != 200:
body = await resp.text()
raise RuntimeError(f"API returned {resp.status}: {body[:300]}")
posts = await resp.json(content_type=None)
if not isinstance(posts, list):
raise RuntimeError("Unexpected API response format")
return _extract_photo_candidates(posts)
async def _download_photo(
session: aiohttp.ClientSession, image_url: str
) -> tuple[bytes | None, str]:
async with session.get(image_url, headers=REQUEST_HEADERS) as resp:
if resp.status != 200:
logger.warning("Image download failed for %s: %s", image_url, resp.status)
return None, _guess_filename(image_url)
content_type = resp.headers.get("Content-Type", "")
if "image" not in content_type.lower():
logger.warning(
"Unexpected content type for %s: %s", image_url, content_type
)
return None, _guess_filename(image_url)
return await resp.read(), _guess_filename(image_url)
async def handle_nude_cmd(message: types.Message): async def handle_nude_cmd(message: types.Message):
args = message.text.split(maxsplit=1) args = message.text.split(maxsplit=1)
if len(args) > 1 and args[1].strip() == "-h": if len(args) > 1 and args[1].strip() == "-h":
help_msg = ( help_msg = (
"🔥 <b>Справка по команде /nude:</b>\n\n" "🔥 <b>Справка по команде /nude:</b>\n\n"
"Получает случайные изображения взрослых женщин из открытых источников.\n" "Берет случайную фотку из последних постов сайта le saint des seins.\n"
"• Использует прямое сканирование сайтов для поиска контента\n" "• Источник: <code>https://lesaintdesseins.fr/</code>\n"
"• По умолчанию ищет популярные изображения\n" "• Достает последние посты через WordPress REST API\n"
"• Отправляет изображения напрямую\n\n" "• Выбирает случайную картинку и отправляет ее прямо в Telegram\n\n"
"<i>Пример:</i> <code>/nude</code>\n" "<i>Пример:</i> <code>/nude</code>"
"<i>По умолчанию:</i> Случайные изображения с популярных сайтов"
) )
await message.reply(help_msg, parse_mode="HTML") await message.reply(help_msg, parse_mode="HTML")
return return
# Список сайтов для сканирования timeout = aiohttp.ClientTimeout(total=30)
sites = [
"https://www.imagefap.com/gallery.php?pg=random",
"https://xhamster.com/photos?sort=random",
"https://spankbang.com/random"
]
random_site = random.choice(sites)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
"Accept-Encoding": "gzip, deflate",
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": "1"
}
try: try:
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession(timeout=timeout) as session:
async with session.get(random_site, headers=headers) as resp: candidates = await _fetch_latest_photo_candidates(session)
if resp.status != 200:
logger.error(f"Site access error: {resp.status}")
await message.reply("Не удалось получить доступ к сайту :(")
return
html = await resp.text() if not candidates:
await message.reply("Не удалось найти свежие фотки :(")
return
# Ищем URL изображений в HTML selected = random.choice(candidates)
img_patterns = [ caption = random.choice(CAPTIONS)
r'<img[^>]+src="([^"]+)"', image_bytes, filename = await _download_photo(session, selected["image_url"])
r'<a[^>]+href="([^"]+\.(jpg|jpeg|png|gif|webp))"',
r'data-src="([^"]+)"'
]
img_urls = [] if image_bytes:
for pattern in img_patterns: photo = types.BufferedInputFile(image_bytes, filename=filename)
matches = re.findall(pattern, html, re.IGNORECASE) await message.answer_photo(photo=photo, caption=caption)
img_urls.extend(matches) return
if not img_urls: try:
await message.reply("Изображения не найдены на странице :(") photo = types.URLInputFile(selected["image_url"])
return await message.answer_photo(photo=photo, caption=caption)
except Exception:
logger.exception("Failed to send photo by URL")
await message.answer(
f"{caption}\n{selected['image_url']}\n{selected['post_url']}"
)
# Фильтруем и выбираем случайное изображение except Exception:
valid_imgs = []
for img_url in img_urls:
if img_url.startswith('//'):
img_url = 'https:' + img_url
elif img_url.startswith('/'):
if 'imagefap.com' in random_site:
img_url = 'https://www.imagefap.com' + img_url
elif 'xhamster.com' in random_site:
img_url = 'https://xhamster.com' + img_url
elif 'spankbang.com' in random_site:
img_url = 'https://spankbang.com' + img_url
if any(ext in img_url.lower() for ext in ['.jpg', '.jpeg', '.png', '.gif', '.webp']):
valid_imgs.append(img_url)
if not valid_imgs:
await message.reply("Подходящие изображения не найдены :(")
return
final_img_url = random.choice(valid_imgs)
caption = random.choice(CAPTIONS)
# Отправляем изображение
try:
input_file = types.URLInputFile(final_img_url)
await message.answer_photo(photo=input_file, caption=caption)
except Exception as e:
logger.error(f"Error sending photo: {e}")
await message.answer(f"{caption}\n{final_img_url}")
except Exception as e:
logger.exception("Error in nude command") logger.exception("Error in nude command")
await message.reply("Произошла ошибка при обработке запроса :(") await message.reply("Произошла ошибка при получении фото :(")