Files
JieXi/routes/main.py
2025-11-30 19:49:25 +08:00

137 lines
4.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from flask import Blueprint, render_template, redirect, request, Response
import requests
main_bp = Blueprint('main', __name__)
@main_bp.route('/')
def index():
from models import SiteConfig
config = {}
configs = SiteConfig.query.all()
for c in configs:
config[c.config_key] = c.config_value
return render_template('index.html', config=config)
@main_bp.route('/api-docs')
def api_docs():
"""API 文档页面"""
return render_template('api_docs.html')
@main_bp.route('/favicon.ico')
def favicon():
"""处理 favicon 请求"""
from models import SiteConfig
favicon_config = SiteConfig.query.filter_by(config_key='site_favicon').first()
if favicon_config and favicon_config.config_value:
return redirect(favicon_config.config_value)
# 如果没有设置 favicon尝试使用 logo
logo_config = SiteConfig.query.filter_by(config_key='site_logo').first()
if logo_config and logo_config.config_value:
return redirect(logo_config.config_value)
# 返回空响应避免 404
return '', 204
@main_bp.route('/proxy/download')
def proxy_download():
"""代理下载视频/图片,绕过防盗链,支持 Range 请求"""
url = request.args.get('url')
if not url:
return 'Missing url parameter', 400
# 限制只能代理特定域名
allowed_domains = [
'weibocdn.com', 'sinaimg.cn', 'weibo.com',
'ppxvod.com', 'byteimg.com', 'pipix.com', '365yg.com', 'ixigua.com',
'kwimgs.com', 'kwaicdn.com', 'kuaishou.com', 'gifshow.com', 'yximgs.com',
'douyinvod.com', 'douyin.com', 'tiktokcdn.com', 'bytedance.com',
'bilivideo.com', 'bilibili.com', 'hdslb.com',
'zjcdn.com', 'douyinpic.com'
]
from urllib.parse import urlparse
parsed = urlparse(url)
domain = parsed.netloc.lower()
is_allowed = any(d in domain for d in allowed_domains)
if not is_allowed:
return f'Domain not allowed: {domain}', 403
# 根据域名设置不同的 Referer
referer_map = {
'weibo': 'https://weibo.com/',
'sina': 'https://weibo.com/',
'pipix': 'https://www.pipix.com/',
'365yg': 'https://www.pipix.com/',
'ixigua': 'https://www.ixigua.com/',
'kuaishou': 'https://www.kuaishou.com/',
'kwimgs': 'https://www.kuaishou.com/',
'kwaicdn': 'https://www.kuaishou.com/',
'yximgs': 'https://www.kuaishou.com/',
'douyin': 'https://www.douyin.com/',
'bytedance': 'https://www.douyin.com/',
'zjcdn': 'https://www.douyin.com/',
'douyinpic': 'https://www.douyin.com/',
'bilibili': 'https://www.bilibili.com/',
'hdslb': 'https://www.bilibili.com/',
}
referer = 'https://www.google.com/'
for key, ref in referer_map.items():
if key in domain:
referer = ref
break
try:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Referer': referer
}
# 转发 Range 请求头,支持视频进度条拖动
range_header = request.headers.get('Range')
if range_header:
headers['Range'] = range_header
resp = requests.get(url, headers=headers, stream=True, timeout=30)
# 获取文件类型
content_type = resp.headers.get('Content-Type', 'application/octet-stream')
# 设置下载文件名
if 'video' in content_type:
filename = f'video_{int(__import__("time").time())}.mp4'
elif 'image' in content_type:
filename = f'image_{int(__import__("time").time())}.jpg'
else:
filename = f'file_{int(__import__("time").time())}'
def generate():
for chunk in resp.iter_content(chunk_size=8192):
yield chunk
# 构建响应头
response_headers = {
'Content-Type': content_type,
'Accept-Ranges': 'bytes'
}
# 转发相关响应头
if resp.headers.get('Content-Length'):
response_headers['Content-Length'] = resp.headers.get('Content-Length')
if resp.headers.get('Content-Range'):
response_headers['Content-Range'] = resp.headers.get('Content-Range')
# 根据是否是 Range 请求返回不同状态码
status_code = resp.status_code
return Response(
generate(),
status=status_code,
headers=response_headers
)
except Exception as e:
return f'Download failed: {str(e)}', 500