feature/FenyaBot #26

Merged
q merged 3 commits from Dan4ick/bot_tg:feature/FenyaBot into main 2026-04-16 09:19:47 +00:00
5 changed files with 54 additions and 6 deletions
Showing only changes of commit 3b29648a8c - Show all commits

1
.gitignore vendored
View file

@ -22,3 +22,4 @@ db/
AI/models/
main_legacy.py
docker-compose.override.yaml

View file

@ -95,10 +95,15 @@ async def fetch_uwu_post(tags: str) -> dict:
}
async def fetch_furtok_feed(safe: bool = True, page: int = 1, extra_tags: str = "") -> list[dict]:
is_custom = bool(extra_tags and extra_tags.strip())
rating = "rating:safe" if safe else "-rating:safe"
if is_custom:
# Кастомный запрос: без принудительного animated, поддержка картинок
tags = f"{extra_tags.strip()} order:random score:>200"
else:
# Стандартная лента: только видео
tags = f"{rating} animated order:random score:>200"
if extra_tags and extra_tags.strip():
tags = f"{extra_tags.strip()} animated order:random score:>200"
url = "https://e621.net/posts.json"
params = {
@ -122,18 +127,24 @@ async def fetch_furtok_feed(safe: bool = True, page: int = 1, extra_tags: str =
raise Exception("Не удалось загрузить ленту :(")
data = await resp.json()
VIDEO_EXTS = ("gif", "webm", "mp4")
IMAGE_EXTS = ("png", "jpg", "jpeg", "webp")
allowed_exts = VIDEO_EXTS + IMAGE_EXTS if is_custom else VIDEO_EXTS
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"):
if not file_url or ext not in allowed_exts:
continue
sample_url = post.get("sample", {}).get("url") or file_url
media_type = "image" if ext in IMAGE_EXTS else "video"
feed.append({
"url": file_url,
"sample": sample_url,
"ext": ext,
"type": media_type,
"score": post.get("score", {}).get("total", 0),
"fav_count": post.get("fav_count", 0),
})

View file

@ -8,12 +8,16 @@ REST API для Telegram Mini App. Использует те же SQLite баз
import asyncio
import logging
import os
import hashlib
from urllib.parse import quote
import sys
from contextlib import asynccontextmanager
from typing import Annotated
from fastapi import FastAPI, Depends, Header, HTTPException
import aiohttp
from fastapi import FastAPI, Depends, Header, HTTPException, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import Response
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel
@ -401,6 +405,34 @@ async def get_furtok_feed_api(
raise HTTPException(status_code=500, detail=str(e))
@app.get("/api/proxy-image")
async def proxy_image(url: str):
"""Проксирует картинку с e621 чтобы обойти hotlink protection."""
allowed = ("static1.e621.net", "static2.e621.net", "static1.e926.net")
from urllib.parse import urlparse
parsed = urlparse(url)
if parsed.hostname not in allowed:
raise HTTPException(status_code=403, detail="Forbidden host")
headers = {
"User-Agent": f"FenyaBot/1.0 (by {config.E621_LOGIN or 'unknown'} on e621)",
}
try:
async with aiohttp.ClientSession() as session:
async with session.get(url, headers=headers, timeout=aiohttp.ClientTimeout(total=15)) as resp:
if resp.status != 200:
raise HTTPException(status_code=resp.status, detail="Upstream error")
content_type = resp.content_type or "image/png"
body = await resp.read()
return Response(
content=body,
media_type=content_type,
headers={"Cache-Control": "public, max-age=86400"},
)
except aiohttp.ClientError:
raise HTTPException(status_code=502, detail="Failed to fetch image")
# --- ИИ Чат ---
@app.post("/api/talk")

View file

@ -913,9 +913,13 @@ body::before {
.furtok-card video,
.furtok-card img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: contain;
display: block;
}
.furtok-overlay {

View file

@ -743,7 +743,7 @@ async function loadFurtokPage(feedEl) {
card.className = 'furtok-card';
let mediaHtml = '';
if (post.ext === 'gif') {
if (post.type === 'image' || post.ext === 'gif') {
mediaHtml = `<img src="${post.url}" loading="lazy">`;
} else {
mediaHtml = `<video src="${post.url}" loop playsinline preload="metadata" muted></video>`;