fix: критические баги, FurTok картинки, image proxy, gitignore
- Удалён дубликат handle_uwu_cmd в uwu.py - Исправлен UnboundLocalError (delta/next_dt) в main.py - FurTok: поддержка картинок при кастомном запросе - Добавлен image proxy /api/proxy-image для e621 - CSS: абсолютное позиционирование медиа в furtok-card - .gitignore: docker-compose.override.yaml
This commit is contained in:
parent
dd36d8f1c3
commit
3b29648a8c
5 changed files with 54 additions and 6 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -22,3 +22,4 @@ db/
|
|||
AI/models/
|
||||
|
||||
main_legacy.py
|
||||
docker-compose.override.yaml
|
||||
|
|
|
|||
17
games/uwu.py
17
games/uwu.py
|
|
@ -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),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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>`;
|
||||
|
|
|
|||
Loading…
Reference in a new issue