feat: 新增平台
This commit is contained in:
112
routes/main.py
112
routes/main.py
@@ -1,4 +1,5 @@
|
||||
from flask import Blueprint, render_template, redirect
|
||||
from flask import Blueprint, render_template, redirect, request, Response
|
||||
import requests
|
||||
|
||||
main_bp = Blueprint('main', __name__)
|
||||
|
||||
@@ -11,6 +12,12 @@ def index():
|
||||
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 请求"""
|
||||
@@ -24,3 +31,106 @@ def favicon():
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user