-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathweb_server.py
More file actions
147 lines (119 loc) · 4.58 KB
/
web_server.py
File metadata and controls
147 lines (119 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
禁漫工具 Web 服务器
提供 Web 界面用于下载本子和导出收藏夹
"""
import os
import stat
import atexit
from flask import Flask, render_template
from flask_cors import CORS
from apscheduler.schedulers.background import BackgroundScheduler
from server.state import tasks, auto_tasks, auto_executions, init_task_counter, init_auto_task_counter, init_auto_execution_counter
from server.utils.storage import load_auto_tasks as storage_load_auto_tasks, load_auto_executions as storage_load_auto_executions, load_manual_tasks as storage_load_manual_tasks
from server.utils.logs import add_log, load_logs, logs
from server.routes import register_blueprints
from server.routes.automation_routes import recover_scheduled_auto_tasks
app = Flask(__name__,
static_folder='web/static',
template_folder='web')
CORS(app)
def _apply_umask_and_permissions() -> None:
"""根据环境变量设置 umask,并确保核心目录具备 0777 权限。"""
umask_str = os.getenv('UMASK', '000')
try:
os.umask(int(umask_str, 8))
except ValueError:
print(f"无效的 UMASK 值: {umask_str},保持默认 umask")
for rel_path in ('data', 'download', 'export'):
abs_path = os.path.abspath(rel_path)
os.makedirs(abs_path, exist_ok=True)
try:
os.chmod(abs_path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
except PermissionError:
print(f"无法修改目录权限: {abs_path}")
_apply_umask_and_permissions()
# 手动任务从磁盘恢复
try:
persisted_tasks = storage_load_manual_tasks()
if persisted_tasks:
tasks.update(persisted_tasks)
init_task_counter(max(persisted_tasks.keys()))
add_log(0, 'info', f'成功恢复 {len(persisted_tasks)} 个历史手动任务')
except Exception as e:
add_log(0, 'error', f'加载手动任务失败: {str(e)}')
# 自动化任务存储从磁盘恢复
try:
persisted = storage_load_auto_tasks()
if persisted:
auto_tasks.update(persisted)
init_auto_task_counter(max(auto_tasks.keys()))
except Exception as e:
add_log(0, 'error', f'加载自动化任务失败: {str(e)}')
# 执行记录从磁盘恢复
try:
persisted_executions = storage_load_auto_executions()
if persisted_executions:
auto_executions.update(persisted_executions)
init_auto_execution_counter(max(auto_executions.keys()))
except Exception as e:
add_log(0, 'error', f'加载执行记录失败: {str(e)}')
# 日志从磁盘恢复
try:
persisted_logs = load_logs()
if persisted_logs:
# 直接恢复所有日志,不清理
# 因为手动任务的日志应该和任务一起持久化保存
logs.clear()
logs.extend(persisted_logs)
add_log(0, 'info', f'成功恢复 {len(persisted_logs)} 条历史日志')
except Exception as e:
add_log(0, 'error', f'加载历史日志失败: {str(e)}')
# APScheduler 调度器
scheduler = BackgroundScheduler()
scheduler.start()
@atexit.register
def shutdown_scheduler():
"""优雅关闭调度器。"""
if scheduler.running:
add_log(0, 'info', '正在关闭调度器...')
scheduler.shutdown(wait=True)
add_log(0, 'info', '调度器已关闭')
# 注册所有路由 Blueprint
register_blueprints(app, scheduler)
# 启动时恢复调度(仅对启用中的任务)
try:
recovered_count = recover_scheduled_auto_tasks()
if recovered_count > 0:
add_log(0, 'info', f'已恢复 {recovered_count} 个自动化任务调度')
except Exception as e:
add_log(0, 'error', f'恢复自动化任务调度失败: {str(e)}')
@app.route('/')
def index():
"""主页"""
return render_template('index.html')
if __name__ == '__main__':
from server.version import get_full_version, __version__
host = os.getenv('WEB_SERVER_HOST', '127.0.0.1')
port = int(os.getenv('WEB_SERVER_PORT', '5000'))
print("=" * 60)
print(f"禁漫工具 Web 服务器 {__version__}")
print("=" * 60)
print()
print(f"访问地址: http://{host}:{port}")
print()
print("功能:")
print(" - 手动下载本子")
print(" - 导出收藏夹")
print(" - 自动化同步")
print(" - 失败图片重试")
print(" - 任务管理")
print(" - 日志查看")
print()
print("按 Ctrl+C 停止服务器")
print("=" * 60)
print()
# 关闭 debug 模式和 reloader,加快启动速度
# 默认监听本地,可通过 WEB_SERVER_HOST=0.0.0.0 放开访问(注意安全)
app.run(host=host, port=port, debug=False, threaded=True)