main.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. from fastapi import FastAPI, Request
  2. from fastapi.staticfiles import StaticFiles
  3. from fastapi.templating import Jinja2Templates
  4. from fastapi.responses import JSONResponse, FileResponse
  5. import uvicorn
  6. import glob
  7. import os
  8. from pydantic import BaseModel
  9. import step2
  10. from utils import *
  11. app = FastAPI(title="EH-Downloader", version="1.0.0")
  12. # 在应用启动时检查并创建data文件夹和targets.txt,以及proxy.txt
  13. @app.on_event("startup")
  14. async def startup_event():
  15. # 检查并创建data文件夹
  16. data_dir = "data"
  17. if not os.path.exists(data_dir):
  18. os.makedirs(data_dir)
  19. print(f"创建目录: {data_dir}")
  20. # 检查并创建targets.txt文件
  21. targets_file = os.path.join(data_dir, "targets.txt")
  22. if not os.path.exists(targets_file):
  23. with open(targets_file, 'w', encoding='utf-8') as f:
  24. f.write("# 在这里添加目标URL,每行一个\n")
  25. f.write("# 示例:\n")
  26. f.write("https://e-hentai.org/g/3550066/47d6393550\n")
  27. print(f"创建文件: {targets_file}")
  28. else:
  29. print(f"文件已存在: {targets_file}")
  30. # 检查并创建proxy.txt文件
  31. proxy_file = "proxy.txt"
  32. if not os.path.exists(proxy_file):
  33. with open(proxy_file, 'w', encoding='utf-8') as f:
  34. f.write("127.0.0.1:7890\n")
  35. print(f"创建文件: {proxy_file}")
  36. else:
  37. print(f"文件已存在: {proxy_file}")
  38. # 挂载静态文件和模板
  39. app.mount("/static", StaticFiles(directory="static"), name="static")
  40. templates = Jinja2Templates(directory="templates")
  41. # favicon 路由
  42. @app.get("/favicon.ico", include_in_schema=False)
  43. async def favicon():
  44. return FileResponse("static/favicon.ico")
  45. @app.get("/")
  46. async def home(request: Request):
  47. """主页面"""
  48. # 读取proxy.txt中的代理列表
  49. proxies = []
  50. try:
  51. with open("proxy.txt", 'r', encoding='utf-8') as f:
  52. proxies = [line.strip() for line in f.readlines() if line.strip()]
  53. except Exception as e:
  54. print(f"读取proxy.txt失败: {e}")
  55. proxies = ["127.0.0.1:7890"]
  56. # 如果没有代理配置,使用默认值
  57. if not proxies:
  58. proxies = ["127.0.0.1:7890"]
  59. return templates.TemplateResponse("index.html", {
  60. "request": request,
  61. "proxies": proxies,
  62. "default_proxy": proxies[0] if proxies else "127.0.0.1:7890"
  63. })
  64. @app.post("/load_urls")
  65. async def load_urls():
  66. """读取 targets.txt 文件中的URL"""
  67. try:
  68. file_path = "data/targets.txt"
  69. # 读取文件内容
  70. with open(file_path, 'r', encoding='utf-8') as f:
  71. urls = [line.strip() for line in f.readlines() if line.strip()]
  72. # 过滤掉空行和注释行(以#开头的行)
  73. urls = [url for url in urls if url and not url.startswith('#')]
  74. if not urls:
  75. return JSONResponse({
  76. "success": True,
  77. "message": "targets.txt 文件为空,请在data/targets.txt中添加URL",
  78. "urls": []
  79. })
  80. return JSONResponse({
  81. "success": True,
  82. "message": f"成功读取 {len(urls)} 个URL",
  83. "urls": urls
  84. })
  85. except Exception as e:
  86. return JSONResponse({
  87. "success": False,
  88. "message": f"读取文件时出错: {str(e)}",
  89. "urls": []
  90. })
  91. @app.post("/clear")
  92. async def clear_output():
  93. """清除输出"""
  94. return JSONResponse({
  95. "success": True,
  96. "message": "输出已清除",
  97. "output": ""
  98. })
  99. class ProxyRequest(BaseModel):
  100. proxy: str # 修改为单个proxy字段
  101. @app.post("/download_urls")
  102. async def download_urls(req: ProxyRequest):
  103. # 解析proxy字符串为ip和port
  104. if ":" in req.proxy:
  105. ip, port = req.proxy.split(":", 1)
  106. proxy = f"http://{ip}:{port}"
  107. else:
  108. proxy = None
  109. msg = await run_step1(proxy)
  110. return JSONResponse({"success": True, "message": msg})
  111. @app.post("/download_images")
  112. async def download_images(req: ProxyRequest):
  113. # 解析proxy字符串为ip和port
  114. if ":" in req.proxy:
  115. ip, port = req.proxy.split(":", 1)
  116. proxy = f"http://{ip}:{port}"
  117. else:
  118. proxy = None
  119. msg = await run_step2(proxy)
  120. return JSONResponse({"success": True, "message": msg})
  121. @app.post("/clean_files")
  122. async def clean_files():
  123. """清理项目目录下的所有 .log 和 .json 文件"""
  124. try:
  125. deleted_files = []
  126. error_files = []
  127. # 查找当前目录及所有子目录中的 .log 和 .json 文件
  128. patterns = ["**/*.log", "**/*.json"]
  129. for pattern in patterns:
  130. for file_path in glob.glob(pattern, recursive=True):
  131. try:
  132. # 跳过 data/targets.txt 文件,因为这是配置文件
  133. if file_path == "data/targets.txt":
  134. continue
  135. os.remove(file_path)
  136. deleted_files.append(file_path)
  137. print(f"已删除文件: {file_path}")
  138. except Exception as e:
  139. error_files.append(f"{file_path}: {str(e)}")
  140. print(f"删除文件失败 {file_path}: {str(e)}")
  141. if error_files:
  142. return JSONResponse({
  143. "success": False,
  144. "message": f"清理完成,但部分文件删除失败",
  145. "deleted_count": len(deleted_files),
  146. "error_count": len(error_files),
  147. "deleted_files": deleted_files,
  148. "error_files": error_files
  149. })
  150. else:
  151. return JSONResponse({
  152. "success": True,
  153. "message": f"成功清理 {len(deleted_files)} 个文件",
  154. "deleted_count": len(deleted_files),
  155. "error_count": 0,
  156. "deleted_files": deleted_files
  157. })
  158. except Exception as e:
  159. return JSONResponse({
  160. "success": False,
  161. "message": f"清理过程中出错: {str(e)}",
  162. "deleted_count": 0,
  163. "error_count": 0
  164. })
  165. @app.post("/check_incomplete")
  166. async def check_incomplete():
  167. result = await step2.scan_tasks()
  168. """检查未完成文件"""
  169. return JSONResponse({
  170. "success": True,
  171. "message": "检查未完成文件功能已就绪",
  172. "data": f"共 {len(result)} 个文件未下载"
  173. })
  174. if __name__ == "__main__":
  175. uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)