调整完毕

This commit is contained in:
limil 2024-11-03 10:50:23 +08:00
parent 2aa4d0870b
commit 72ecb98c56
3 changed files with 67 additions and 64 deletions

View File

@ -221,12 +221,14 @@ class PikPakFileSystem:
return father, sonName return father, sonName
async def _node_to_path(self, node : NodeBase) -> str: async def _node_to_path(self, node : NodeBase, root : NodeBase = None) -> str:
if node is self._root: if root is None:
root = self._root
if node is root:
return "/" return "/"
spots : list[str] = [] spots : list[str] = []
current = node current = node
while current is not self._root: while current is not root:
spots.append(current.name) spots.append(current.name)
current = await self._get_father_node(current) current = await self._get_father_node(current)
spots.append("") spots.append("")
@ -307,18 +309,20 @@ class PikPakFileSystem:
async def GetCwd(self) -> str: async def GetCwd(self) -> str:
return await self._node_to_path(self._cwd) return await self._node_to_path(self._cwd)
async def GetNodeIdByPath(self, path : str) -> str: async def GetChildren(self, node : NodeBase) -> list[NodeBase]:
if not isinstance(node, DirNode):
return []
await self._refresh(node)
return [await self._get_node_by_id(child_id) for child_id in node.children_id]
async def PathToNode(self, path : str) -> NodeBase:
node = await self._path_to_node(path) node = await self._path_to_node(path)
if node is None: if node is None:
return None return None
return node.id return node
async def IfExists(self, path : str) -> bool: async def NodeToPath(self, from_node : NodeBase, to_node : NodeBase) -> str:
return await self._path_to_node(path) is not None return await self._node_to_path(to_node, from_node)
async def ToFullPath(self, path : str) -> str:
node = await self._path_to_node(path)
return await self._node_to_path(node)
async def RemoteDownload(self, torrent : str, remote_base_path : str) -> tuple[str, str]: async def RemoteDownload(self, torrent : str, remote_base_path : str) -> tuple[str, str]:
node = await self._path_to_node(remote_base_path) node = await self._path_to_node(remote_base_path)
@ -328,25 +332,19 @@ class PikPakFileSystem:
async def QueryTaskStatus(self, task_id : str, node_id : str) -> DownloadStatus: async def QueryTaskStatus(self, task_id : str, node_id : str) -> DownloadStatus:
return await self._pikpak_client.get_task_status(task_id, node_id) return await self._pikpak_client.get_task_status(task_id, node_id)
async def UpdateDirectory(self, path : str, son_id : str) -> str: async def UpdateNode(self, node_id : str) -> NodeBase:
await self._path_to_node(path) node : NodeBase = await self._get_node_by_id(node_id)
son_info = await self._pikpak_client.offline_file_info(son_id) if node is None:
kind = son_info["kind"] info = await self._pikpak_client.offline_file_info(node_id)
parent_id = son_info["parent_id"] kind = info["kind"]
name = son_info["name"] parent_id = info["parent_id"]
son : NodeBase = None name = info["name"]
if kind.endswith("folder"): if kind.endswith("folder"):
son = DirNode(son_id, name, parent_id) node = DirNode(node_id, name, parent_id)
else: else:
son = FileNode(son_id, name, parent_id) node = FileNode(node_id, name, parent_id)
await self._add_node(son) await self._add_node(node)
return await self._node_to_path(son) node.lastUpdate = None
return node
async def JoinPath(self, father : str, son : str) -> str:
father_node = await self._path_to_node(father)
son_node = await self._find_child_in_dir_by_name(father_node, son)
if son_node is None:
raise Exception("Son not found")
return await self._node_to_path(son_node)
#endregion #endregion

View File

@ -3,7 +3,7 @@ from typing import Awaitable, Callable, Dict
import asyncio import asyncio
import logging import logging
import shortuuid import shortuuid
from PikPakFileSystem import PikPakFileSystem from PikPakFileSystem import PikPakFileSystem, FileNode, DirNode
from pikpakapi import DownloadStatus from pikpakapi import DownloadStatus
import random import random
@ -49,11 +49,11 @@ class TorrentTask(TaskBase):
super().__init__(self) super().__init__(self)
self.torrent_status : TorrentTaskStatus = TorrentTaskStatus.PENDING self.torrent_status : TorrentTaskStatus = TorrentTaskStatus.PENDING
self.torrent : str = torrent self.torrent : str = torrent
self.remote_full_path : str = None
self.remote_base_path : str = None
self.info : str = "" self.info : str = ""
self.name : str = ""
# 和PikPak交互需要的信息 # 和PikPak交互需要的信息
self.remote_base_path : str = None
self.node_id : str = None self.node_id : str = None
self.task_id : str = None self.task_id : str = None
@ -62,9 +62,10 @@ class FileDownloadTask(TaskBase):
TAG = "FileDownloadTask" TAG = "FileDownloadTask"
MAX_CONCURRENT_NUMBER = 5 MAX_CONCURRENT_NUMBER = 5
def __init__(self, remote_path : str, owner_id : str): def __init__(self, node_id : str, remote_path : str, owner_id : str):
super().__init__(self) super().__init__(self)
self.file_download_status : FileDownloadTaskStatus = FileDownloadTaskStatus.PENDING self.file_download_status : FileDownloadTaskStatus = FileDownloadTaskStatus.PENDING
self.node_id : str = node_id
self.remote_path : str = remote_path self.remote_path : str = remote_path
self.owner_id : str = owner_id self.owner_id : str = owner_id
@ -141,25 +142,28 @@ class TaskManager:
await asyncio.sleep(wait_seconds) await asyncio.sleep(wait_seconds)
wait_seconds = wait_seconds * 1.5 wait_seconds = wait_seconds * 1.5
task.remote_full_path = await self.client.UpdateDirectory(task.remote_base_path, task.node_id)
task.torrent_status = TorrentTaskStatus.LOCAL_DOWNLOADING task.torrent_status = TorrentTaskStatus.LOCAL_DOWNLOADING
async def _on_torrent_local_downloading(self, task : TorrentTask): async def _on_torrent_local_downloading(self, task : TorrentTask):
path = task.remote_full_path node = await self.client.UpdateNode(task.node_id)
task.name = node.name
task.node_id = node.id
if not await self.client.IsDir(path): if isinstance(node, FileNode):
await self._init_file_download_task(path, task.id) await self._init_file_download_task(task.node_id, task.name, task.id)
else: elif isinstance(node, DirNode):
# 使用广度优先遍历 # 使用广度优先遍历
queue : list[str] = [path] queue : list[str] = [node]
while len(queue) > 0: while len(queue) > 0:
current_path = queue.pop(0) current = queue.pop(0)
for child_name in await self.client.GetChildrenNames(current_path, False): for child in await self.client.GetChildren(current):
child_path = await self.client.JoinPath(current_path, child_name) if isinstance(child, DirNode):
if await self.client.IsDir(child_path): queue.append(child)
queue.append(child_path) if isinstance(child, FileNode):
child_path = task.name + await self.client.NodeToPath(node, child)
await self._init_file_download_task(child.id, child_path, task.id)
else: else:
await self._init_file_download_task(child_path, task.id) raise Exception("unknown node type")
# 开始等待下载任务完成 # 开始等待下载任务完成
while True: while True:
@ -214,22 +218,21 @@ class TaskManager:
#region 文件下载部分 #region 文件下载部分
async def _init_file_download_task(self, remote_path : str, owner_id : str) -> str: async def _init_file_download_task(self, node_id : str, remote_path : str, owner_id : str) -> str:
queue = await self._get_file_download_queue(owner_id) queue = await self._get_file_download_queue(owner_id)
for task in queue: for task in queue:
if not isinstance(task, FileDownloadTask): if not isinstance(task, FileDownloadTask):
continue continue
if task.remote_path == remote_path: if task.node_id == node_id:
if task.status in {TaskStatus.PAUSED, TaskStatus.ERROR}: if task.status in {TaskStatus.PAUSED, TaskStatus.ERROR}:
task.status = TaskStatus.PENDING task.status = TaskStatus.PENDING
return task.id return task.id
task = FileDownloadTask(remote_path, owner_id) task = FileDownloadTask(node_id, remote_path, owner_id)
task.handler = self._file_download_task_handler task.handler = self._file_download_task_handler
await self._append_task(task) await self._append_task(task)
return task.id return task.id
async def _file_download_task_handler(self, task : FileDownloadTask): async def _file_download_task_handler(self, task : FileDownloadTask):
await asyncio.sleep(30)
if random.randint(1, 5) == 2: if random.randint(1, 5) == 2:
raise asyncio.CancelledError() raise asyncio.CancelledError()
if random.randint(1, 5) == 3: if random.randint(1, 5) == 3:
@ -260,17 +263,19 @@ class TaskManager:
await self._append_task(task) await self._append_task(task)
return task.id return task.id
async def PullRemote(self, remote_full_path : str) -> str: async def PullRemote(self, path : str) -> str:
if not await self.client.IfExists(remote_full_path): target = await self.client.PathToNode(path)
if target is None:
raise Exception("target not found") raise Exception("target not found")
queue = await self._get_torrent_queue() queue = await self._get_torrent_queue()
for task in queue: for task in queue:
if not isinstance(task, TorrentTask): if not isinstance(task, TorrentTask):
continue continue
if task.remote_full_path == remote_full_path: if task.node_id == target.id:
return task.id return task.id
task = TorrentTask(None) task = TorrentTask(None)
task.remote_full_path = remote_full_path task.name = target.name
task.node_id = target.id
task.handler = self._torrent_task_handler task.handler = self._torrent_task_handler
task.torrent_status = TorrentTaskStatus.LOCAL_DOWNLOADING task.torrent_status = TorrentTaskStatus.LOCAL_DOWNLOADING
await self._append_task(task) await self._append_task(task)

12
main.py
View File

@ -166,10 +166,10 @@ class App(cmd2.Cmd):
await Client.Login(args.username, args.password) await Client.Login(args.username, args.password)
await self.print("Logged in successfully") await self.print("Logged in successfully")
async def _path_completer(self, text, line, begidx, endidx, ignoreFiles): async def _path_completer(self, text, line, begidx, endidx, ignore_files):
father_path, son_name = await Client.SplitPath(text) father_path, son_name = await Client.SplitPath(text)
children_names = await Client.GetChildrenNames(father_path, ignoreFiles) children_names = await Client.GetChildrenNames(father_path, ignore_files)
matches = [] matches : list[str] = []
for child_name in children_names: for child_name in children_names:
if child_name.startswith(son_name): if child_name.startswith(son_name):
self.display_matches.append(child_name) self.display_matches.append(child_name)
@ -177,8 +177,8 @@ class App(cmd2.Cmd):
matches.append(text + child_name) matches.append(text + child_name)
elif text.endswith(son_name): elif text.endswith(son_name):
matches.append(text[:text.rfind(son_name)] + child_name) matches.append(text[:text.rfind(son_name)] + child_name)
if len(matches) == 1 and await Client.IsDir(father_path + matches[0]): if len(matches) == 1 and await Client.IsDir(matches[0]):
if matches[0] == son_name: if matches[0].endswith(son_name):
matches[0] += "/" matches[0] += "/"
self.allow_appended_space = False self.allow_appended_space = False
self.allow_closing_quote = False self.allow_closing_quote = False
@ -278,7 +278,7 @@ class App(cmd2.Cmd):
""" """
Pull a file or directory Pull a file or directory
""" """
task_id = await self.task_manager.PullRemote(await Client.ToFullPath(args.target)) task_id = await self.task_manager.PullRemote(args.target)
await self.print(f"Task {task_id} created") await self.print(f"Task {task_id} created")