From bad8d6cd154d461886e76c5ebdcf688aefd02270 Mon Sep 17 00:00:00 2001 From: Krcia <1503175889@qq.com> Date: Mon, 10 Nov 2025 15:56:42 +0800 Subject: [PATCH] =?UTF-8?q?=E9=97=AD=E7=8E=AF=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api.py | 7 ++--- docker/Dockerfile | 5 ++-- docker/html/home.html | 7 ++--- docker/server/api.py | 20 ++++--------- docker/server/download.py | 59 +++++++++++++++++++++++++++++++++------ download.py | 2 +- 6 files changed, 65 insertions(+), 35 deletions(-) diff --git a/api.py b/api.py index 06afae3..8dfc9d6 100644 --- a/api.py +++ b/api.py @@ -7,7 +7,6 @@ from functools import wraps from download import M3U8Downloader from function import crawl_missav -from urllib.parse import urlparse app = Flask(__name__) app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'your-secret-key-here') @@ -100,7 +99,7 @@ def check_url(url): return jsonify({ 'msg': '成功', 'code': 200, - 'dat': result + 'data': result }), 200 except: return jsonify({ @@ -130,12 +129,12 @@ def download(): return jsonify({ 'msg': '成功', 'code': 200, - 'dat': task_id + 'data': task_id }), 200 @app.route('/api/all-task', methods=['GET']) -# @token_required +@token_required def all_task(): all_tasks = downloader.get_all_tasks() return jsonify({ diff --git a/docker/Dockerfile b/docker/Dockerfile index 5ca973f..6020c5d 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.12-slim +FROM ubuntu:24.04 # 安装系统依赖 RUN apt-get update && apt-get install -y \ @@ -26,8 +26,9 @@ RUN apt-get update && apt-get install -y \ fonts-liberation \ libnss3-tools \ xvfb \ + python3 \ + python3-pip \ && rm -rf /var/lib/apt/lists/* - # 设置工作目录 WORKDIR /app diff --git a/docker/html/home.html b/docker/html/home.html index 662cd4c..8cf1b86 100644 --- a/docker/html/home.html +++ b/docker/html/home.html @@ -301,10 +301,10 @@ }) .then(response => { if (response.status === 401) { - throw new Error('认证失败'); + location.href='/'; } if (!response.ok) { - throw new Error('网络响应不正常'); + location.href='/'; } return response.json(); }) @@ -407,7 +407,6 @@ fetchTasks().then(tasks => { currentTasks = tasks; renderTaskList(tasks); - // 启动定时更新 startAutoUpdate(); }).catch(error => { @@ -428,7 +427,7 @@ currentTasks = tasks; updateTaskProgress(tasks); }); - }, 5000); + }, 1000); } // 添加新任务 diff --git a/docker/server/api.py b/docker/server/api.py index 57e3969..4c061aa 100644 --- a/docker/server/api.py +++ b/docker/server/api.py @@ -22,7 +22,7 @@ PASSWORD = os.getenv('PASSWORD') def token_required(f): @wraps(f) def decorated(*args, **kwargs): - token = request.headers.get('Authorization') + token = request.headers.get(f'Authorization') if not token: return jsonify({ @@ -93,17 +93,16 @@ def login(): @app.route('/api/check/') @token_required def check_url(url): - status = is_from_missav(url) - if (status): + try: result = asyncio.run(crawl_missav( url )) return jsonify({ 'msg': '成功', 'code': 200, - 'dat': result + 'data': result }), 200 - else: + except: return jsonify({ 'msg': '不是来自missav的链接', 'code': 500 @@ -131,7 +130,7 @@ def download(): return jsonify({ 'msg': '成功', 'code': 200, - 'dat': task_id + 'data': task_id }), 200 @@ -163,15 +162,6 @@ def progress(task_id): }), 200 -def is_from_missav(url): - try: - parsed = urlparse(url) - hostname = parsed.netloc.lower() - return hostname == 'missav.ws' or hostname.endswith('.missav.ws') - except: - return False - - if __name__ == '__main__': # 检查环境变量是否设置 if not USERNAME or not PASSWORD: diff --git a/docker/server/download.py b/docker/server/download.py index 5e3f36d..e002c21 100644 --- a/docker/server/download.py +++ b/docker/server/download.py @@ -7,19 +7,41 @@ import m3u8 from Crypto.Cipher import AES import concurrent.futures from pathlib import Path +import shutil class M3U8Downloader: - def __init__(self, max_workers=5, output_dir="downloads"): + def __init__(self, max_workers=5, output_dir="/app/downloads", cache_dir="cache"): self.max_workers = max_workers self.output_dir = Path(output_dir) + self.cache_dir = Path(cache_dir) + + # 创建目录 self.output_dir.mkdir(exist_ok=True) + self.cache_dir.mkdir(exist_ok=True) + + # 清空缓存目录 + self.clear_cache() # 存储下载任务状态 self.tasks = {} self.lock = threading.Lock() self.task_counter = 0 + def clear_cache(self): + """清空缓存目录""" + try: + if self.cache_dir.exists(): + # 删除缓存目录中的所有内容 + for item in self.cache_dir.iterdir(): + if item.is_file(): + item.unlink() + elif item.is_dir(): + shutil.rmtree(item) + print(f"缓存目录已清空: {self.cache_dir}") + except Exception as e: + print(f"清空缓存目录失败: {e}") + def get_task_info(self, task_id): """获取任务信息""" with self.lock: @@ -62,7 +84,8 @@ class M3U8Downloader: 'filename': task_info['output_filename'], 'status': task_info['status'], 'progress': round(progress, 4), - 'start_time': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(task_info.get('start_time', time.time()))) + 'start_time': time.strftime('%Y-%m-%d %H:%M:%S', + time.localtime(task_info.get('start_time', time.time()))) }) # 按开始时间倒序排列,最新的任务在前面 @@ -111,6 +134,9 @@ class M3U8Downloader: cipher = AES.new(task_info['key'], AES.MODE_CBC, task_info['iv']) ts_data = cipher.decrypt(ts_data) + # 确保缓存目录存在 + output_path.parent.mkdir(parents=True, exist_ok=True) + with open(output_path, 'wb') as f: f.write(ts_data) @@ -201,15 +227,17 @@ class M3U8Downloader: task_info['total_segments'] = len(ts_segments) task_info['status'] = 'downloading' - # 设置输出文件路径 + # 设置输出文件路径(在下载目录中) output_path = self.output_dir / output_filename task_info['output_file'] = str(output_path) - # 创建临时目录存储TS片段 - temp_dir = self.output_dir / f"temp_{task_id}" + # 创建临时目录存储TS片段(在缓存目录中) + temp_dir = self.cache_dir / f"temp_{task_id}" temp_dir.mkdir(exist_ok=True) print(f"开始下载任务 {task_id}: {len(ts_segments)} 个片段") + print(f"缓存目录: {temp_dir}") + print(f"输出文件: {output_path}") # 使用线程池下载所有TS片段 with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor: @@ -236,23 +264,30 @@ class M3U8Downloader: task_info['error'] = '部分片段下载失败' task_info['progress'] = 0.0 print(f"任务 {task_id} 下载失败,部分片段下载失败") + + # 清理缓存 + if temp_dir.exists(): + shutil.rmtree(temp_dir) return - # 合并TS文件 + # 合并TS文件到下载目录 print(f"开始合并TS文件...") task_info['status'] = 'merging' task_info['progress'] = 1.0 + # 确保输出目录存在 + self.output_dir.mkdir(exist_ok=True) + with open(output_path, 'wb') as outfile: for i in range(len(ts_segments)): ts_path = temp_dir / f"segment_{i:05d}.ts" if ts_path.exists(): with open(ts_path, 'rb') as infile: outfile.write(infile.read()) - ts_path.unlink() - # 清理临时目录 - temp_dir.rmdir() + # 清理缓存目录 + if temp_dir.exists(): + shutil.rmtree(temp_dir) task_info['status'] = 'completed' task_info['progress'] = 1.0 @@ -264,6 +299,12 @@ class M3U8Downloader: task_info['status'] = 'failed' task_info['error'] = str(e) task_info['progress'] = 0.0 + + # 清理缓存 + temp_dir = self.cache_dir / f"temp_{task_id}" + if temp_dir.exists(): + shutil.rmtree(temp_dir) + print(f"任务 {task_id} 失败: {e}") def download(self, output_filename, m3u8_url): diff --git a/download.py b/download.py index 1e0cfe2..e002c21 100644 --- a/download.py +++ b/download.py @@ -11,7 +11,7 @@ import shutil class M3U8Downloader: - def __init__(self, max_workers=5, output_dir="downloads", cache_dir="cache"): + def __init__(self, max_workers=5, output_dir="/app/downloads", cache_dir="cache"): self.max_workers = max_workers self.output_dir = Path(output_dir) self.cache_dir = Path(cache_dir)