diff --git a/Dockerfile b/Dockerfile index 3923d428..130e2847 100644 --- a/Dockerfile +++ b/Dockerfile @@ -52,7 +52,8 @@ COPY requirements.txt requirements.txt RUN apt-get update -y \ && apt-get install -y build-essential \ && pip install --upgrade pip \ - && pip install Cython \ + && pip install Cython pip-tools \ + && pip-compile requirements.in \ && pip install -r requirements.txt \ && playwright install-deps chromium \ && apt-get remove -y build-essential \ diff --git a/app/modules/filemanager/storages/alipan.py b/app/modules/filemanager/storages/alipan.py index 2689c34b..fd853403 100644 --- a/app/modules/filemanager/storages/alipan.py +++ b/app/modules/filemanager/storages/alipan.py @@ -569,7 +569,8 @@ def detail(self, fileitem: schemas.FileItem) -> Optional[schemas.FileItem]: extension=result.get("file_extension"), modify_time=StringUtils.str_to_timestamp(result.get("updated_at")), thumbnail=result.get("thumbnail"), - path=f"{fileitem.path}{result.get('name')}" + path=f"{fileitem.path}{result.get('name')}", + url=result.get("download_url") or result.get("url") ) else: self.__handle_error(res, "获取文件详情") @@ -626,34 +627,49 @@ def __get_play_url(): return list(play_dict.values())[-1] return None - res = RequestUtils(headers=headers, timeout=10).post_res(self.download_url, json={ - "drive_id": fileitem.drive_id, - "file_id": fileitem.fileid - }) - if res: - result = res.json() - download_url = result.get("url") - if not download_url: - download_url = __get_play_url() - if not download_url: - if result.get("internal_url"): - download_url = result.get("internal_url") - if not download_url: - logger.warn(f"{fileitem.path} 未获取到下载链接") - return None - res = RequestUtils(headers={ - "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", - "Referer": "https://www.alipan.com/", - "Sec-Fetch-Dest": "iframe", - "Sec-Fetch-Mode": "navigate", - "Sec-Fetch-Site": "cross-site", - "User-Agent": settings.USER_AGENT - }).get_res(download_url) + # 先获取文件详情 + fileinfo = self.detail(fileitem) + if not fileinfo: + logger.warn(f"{fileitem.path} 文件不存在") + return None + + # 文件下载链接 + download_url = None + if fileinfo.url: + # 使用文件详情中的链接 + download_url = fileinfo.url + else: + # 查询文件下载链接 + res = RequestUtils(headers=headers, timeout=10).post_res(self.download_url, json={ + "drive_id": fileitem.drive_id, + "file_id": fileitem.fileid, + "file_name": fileitem.name, + }) if res: - path = settings.TEMP_PATH / fileitem.name - with path.open("wb") as f: - f.write(res.content) - return path + result = res.json() + download_url = result.get("url") or result.get("internal_url") + + if not download_url: + # 查询播放链接 + download_url = __get_play_url() + + if not download_url: + logger.warn(f"{fileitem.path} 未获取到下载链接") + return None + # 下载文件到本地 + res = RequestUtils(headers={ + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", + "Referer": "https://www.alipan.com/", + "Sec-Fetch-Dest": "iframe", + "Sec-Fetch-Mode": "navigate", + "Sec-Fetch-Site": "cross-site", + "User-Agent": settings.USER_AGENT + }).get_res(download_url) + if res: + path = settings.TEMP_PATH / fileitem.name + with path.open("wb") as f: + f.write(res.content) + return path else: self.__handle_error(res, "获取下载链接") return None @@ -663,6 +679,8 @@ def upload(self, fileitem: schemas.FileItem, path: Path) -> Optional[schemas.Fil 上传文件,并标记完成 """ + __UPLOAD_CHUNK_SIZE: int = 10485760 # 10 MB + def __sha1(_path: Path): """ 计算文件sha1,用于快传 @@ -680,6 +698,7 @@ def __sha1(_path: Path): if not params: return None headers = self.__get_headers(params) + # 计算sha1 sha1 = __sha1(path) res = RequestUtils(headers=headers, timeout=10).post_res(self.create_folder_file_url, json={ diff --git a/app/schemas/file.py b/app/schemas/file.py index 9f260290..5cc2d55d 100644 --- a/app/schemas/file.py +++ b/app/schemas/file.py @@ -32,6 +32,8 @@ class FileItem(BaseModel): pickcode: Optional[str] = None # drive_id drive_id: Optional[str] = None + # url + url: Optional[str] = None class StorageUsage(BaseModel): diff --git a/requirements.in b/requirements.in index edb20d3f..4b6e0ade 100644 --- a/requirements.in +++ b/requirements.in @@ -60,4 +60,5 @@ pyotp~=2.9.0 Pinyin2Hanzi~=0.1.1 pywebpush~=2.0.0 py115j~=0.0.6 -oss2~=2.18.6 \ No newline at end of file +oss2~=2.18.6 +aligo~=6.2.4 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 22ae1530..c3ebf4e1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,6 +14,8 @@ aiosignal==1.3.1 # via aiohttp alembic==1.11.3 # via -r requirements.in +aligo==6.2.4 + # via -r requirements.in aliyun-python-sdk-core==2.15.1 # via # aliyun-python-sdk-kms @@ -23,7 +25,9 @@ aliyun-python-sdk-kms==2.16.4 anitopy==2.1.1 # via -r requirements.in anyio==4.4.0 - # via starlette + # via + # httpx + # starlette apscheduler==3.10.4 # via -r requirements.in attrs==24.2.0 @@ -41,7 +45,10 @@ cacheout==0.14.1 cachetools==5.3.3 # via -r requirements.in certifi==2024.7.4 - # via requests + # via + # httpcore + # httpx + # requests cf-clearance==0.31.0 # via -r requirements.in cffi==1.17.0 @@ -56,10 +63,8 @@ click==8.1.7 # uvicorn cn2an==0.5.22 # via -r requirements.in -colorama==0.4.6 - # via - # click - # tqdm +coloredlogs==15.0.1 + # via aligo crcmod==1.7 # via oss2 cryptography==43.0.0 @@ -73,6 +78,8 @@ cssselect==1.2.0 # via pyquery cython==3.0.11 # via -r requirements.in +datclass==0.2.27 + # via aligo dateparser==1.1.8 # via -r requirements.in docker==6.1.3 @@ -88,16 +95,23 @@ frozenlist==1.4.1 func-timeout==4.3.5 # via -r requirements.in greenlet==2.0.2 - # via - # playwright - # sqlalchemy + # via playwright h11==0.14.0 - # via uvicorn + # via + # httpcore + # uvicorn http-ece==1.2.1 # via pywebpush +httpcore==1.0.5 + # via httpx +httpx==0.27.2 + # via py115j +humanfriendly==10.0 + # via coloredlogs idna==3.7 # via # anyio + # httpx # requests # yarl jinja2==3.1.4 @@ -109,7 +123,7 @@ lxml==4.9.4 # -r requirements.in # pyquery lz4==4.3.3 - # via py115 + # via py115j mako==1.3.5 # via alembic markupsafe==2.1.5 @@ -134,6 +148,8 @@ pillow==10.4.0 # via # -r requirements.in # pystray + # qrcode + # qrcode-terminal pinyin2hanzi==0.1.1 # via -r requirements.in playwright==1.37.0 @@ -156,7 +172,7 @@ pycryptodome==3.20.0 # via # -r requirements.in # oss2 - # py115 + # py115j pydantic==1.10.17 # via # -r requirements.in @@ -165,10 +181,20 @@ pyee==9.0.4 # via playwright pyjwt==2.7.0 # via -r requirements.in +pyobjc-core==10.3.1 + # via + # pyobjc-framework-cocoa + # pyobjc-framework-quartz +pyobjc-framework-cocoa==10.3.1 + # via pyobjc-framework-quartz +pyobjc-framework-quartz==10.3.1 + # via pystray pyotp==2.9.0 # via -r requirements.in pyparsing==3.0.9 # via -r requirements.in +pypng==0.20220715.0 + # via qrcode pyquery==2.0.0 # via -r requirements.in pysocks==1.7.1 @@ -192,17 +218,19 @@ pytz==2023.4 # -r requirements.in # apscheduler # dateparser - # py115 + # py115j pyvirtualdisplay==3.0 # via -r requirements.in pywebpush==2.0.0 # via -r requirements.in -pywin32==306 ; platform_system == "Windows" - # via - # -r requirements.in - # docker qbittorrent-api==2023.5.48 # via -r requirements.in +qrcode[pil]==7.4.2 + # via + # aligo + # qrcode-terminal +qrcode-terminal==0.8 + # via aligo regex==2023.6.3 # via # -r requirements.in @@ -210,11 +238,12 @@ regex==2023.6.3 requests[socks]==2.32.3 # via # -r requirements.in + # aligo # docker # openai # oss2 # plexapi - # py115 + # py115j # pytelegrambotapi # pywebpush # qbittorrent-api @@ -241,7 +270,9 @@ slack-sdk==3.21.3 # -r requirements.in # slack-bolt sniffio==1.3.1 - # via anyio + # via + # anyio + # httpx soupsieve==2.6 # via beautifulsoup4 sqlalchemy==2.0.32 @@ -257,7 +288,9 @@ tailer==0.4.1 torrentool==1.2.0 # via -r requirements.in tqdm==4.66.5 - # via openai + # via + # aligo + # openai transmission-rpc==4.3.1 # via -r requirements.in typing-extensions==4.12.2 @@ -265,10 +298,9 @@ typing-extensions==4.12.2 # alembic # pydantic # pyee + # qrcode # sqlalchemy # transmission-rpc -tzdata==2024.1 - # via tzlocal tzlocal==5.2 # via # apscheduler