This commit is contained in:
fengfeng 2024-10-29 22:01:18 +08:00
parent f56cd2bf49
commit 6f78ceac53
2 changed files with 52 additions and 30 deletions

View File

@ -4,7 +4,7 @@ from functools import wraps
import logging import logging
import threading import threading
import colorlog import colorlog
from pikpakFs import VirtFsNode, DirNode, FileNode, PKVirtFs, IsDir, IsFile from pikpakFs import FsNode, DirNode, FileNode, PKFs, IsDir, IsFile
import os import os
def RunSyncInLoop(loop): def RunSyncInLoop(loop):
@ -142,7 +142,7 @@ class PikpakConsole(cmd2.Cmd):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self._setup_logging() self._setup_logging()
self.client = PKVirtFs("token.json", proxy="http://127.0.0.1:7897") self.client = PKFs("token.json", proxy="http://127.0.0.1:7890")
async def Run(self): async def Run(self):
# 1. 设置忽略SIGINT # 1. 设置忽略SIGINT

View File

@ -7,6 +7,27 @@ import json
import re import re
import os import os
import logging import logging
from enum import Enum
class PKTaskStatus(Enum):
pending = "pending"
offline_downloading = "offline_downloading"
downloading = "downloading"
done = "done"
error = "error"
class PkTask:
id = 0
def __init__(self, torrent : str, toDirId : str, status : PKTaskStatus = PKTaskStatus.pending):
id += 1
self.taskId = id
self.status = status
self.toDirId = toDirId
self.torrent = torrent
self.url = None
self.pkTaskId = None
class PathWalker(): class PathWalker():
def __init__(self, pathStr : str, sep : str = "/"): def __init__(self, pathStr : str, sep : str = "/"):
@ -25,30 +46,30 @@ class PathWalker():
def Walk(self) -> list[str]: def Walk(self) -> list[str]:
return self.__pathSpots return self.__pathSpots
class VirtFsNode: class FsNode:
def __init__(self, id : str, name : str, fatherId : str): def __init__(self, id : str, name : str, fatherId : str):
self.id = id self.id = id
self.name = name self.name = name
self.fatherId = fatherId self.fatherId = fatherId
self.lastUpdate : datetime = None self.lastUpdate : datetime = None
class DirNode(VirtFsNode): class DirNode(FsNode):
def __init__(self, id : str, name : str, fatherId : str): def __init__(self, id : str, name : str, fatherId : str):
super().__init__(id, name, fatherId) super().__init__(id, name, fatherId)
self.childrenId : list[str] = [] self.childrenId : list[str] = []
class FileNode(VirtFsNode): class FileNode(FsNode):
def __init__(self, id : str, name : str, fatherId : str): def __init__(self, id : str, name : str, fatherId : str):
super().__init__(id, name, fatherId) super().__init__(id, name, fatherId)
self.url : str = None self.url : str = None
def IsDir(node : VirtFsNode) -> bool: def IsDir(node : FsNode) -> bool:
return isinstance(node, DirNode) return isinstance(node, DirNode)
def IsFile(node : VirtFsNode) -> bool: def IsFile(node : FsNode) -> bool:
return isinstance(node, FileNode) return isinstance(node, FileNode)
class PikpakToken: class PkToken:
def __init__(self, username, password, access_token, refresh_token, user_id): def __init__(self, username, password, access_token, refresh_token, user_id):
self.username = username self.username = username
self.password = password self.password = password
@ -64,18 +85,22 @@ class PikpakToken:
data = json.loads(json_str) data = json.loads(json_str)
return cls(**data) return cls(**data)
class PKVirtFs: class PKFs:
async def RunTasks(self):
pass
def __init__(self, loginCachePath : str = None, proxy : str = None, rootId = None): def __init__(self, loginCachePath : str = None, proxy : str = None, rootId = None):
self.nodes : Dict[str, VirtFsNode] = {} self.nodes : Dict[str, FsNode] = {}
self.root = DirNode(rootId, "", None) self.root = DirNode(rootId, "", None)
self.currentLocation = self.root self.currentLocation = self.root
self.tasks : list[PkTask] = []
self.loginCachePath = loginCachePath self.loginCachePath = loginCachePath
self.proxyConfig = proxy self.proxyConfig = proxy
self.client : PikPakApi = None self.client : PikPakApi = None
self._try_login_from_cache() self._try_login_from_cache()
def _init_client_by_token(self, token : PikpakToken): def _init_client_by_token(self, token : PkToken):
self._init_client_by_username_and_password(token.username, token.password) self._init_client_by_username_and_password(token.username, token.password)
self.client.access_token = token.access_token self.client.access_token = token.access_token
self.client.refresh_token = token.refresh_token self.client.refresh_token = token.refresh_token
@ -102,7 +127,7 @@ class PKVirtFs:
return return
with open(self.loginCachePath, 'r', encoding='utf-8') as file: with open(self.loginCachePath, 'r', encoding='utf-8') as file:
content = file.read() content = file.read()
token = PikpakToken.from_json(content) token = PkToken.from_json(content)
self._init_client_by_token(token) self._init_client_by_token(token)
logging.info("successfully load login info from cache") logging.info("successfully load login info from cache")
@ -110,11 +135,11 @@ class PKVirtFs:
if self.loginCachePath is None: if self.loginCachePath is None:
return return
with open(self.loginCachePath, 'w', encoding='utf-8') as file: with open(self.loginCachePath, 'w', encoding='utf-8') as file:
token = PikpakToken(self.client.username, self.client.password, self.client.access_token, self.client.refresh_token, self.client.user_id) token = PkToken(self.client.username, self.client.password, self.client.access_token, self.client.refresh_token, self.client.user_id)
file.write(token.to_json()) file.write(token.to_json())
logging.info("successfully dump login info to cache") logging.info("successfully dump login info to cache")
def _is_ancestors_of(self, nodeA : VirtFsNode, nodeB : VirtFsNode) -> bool: def _is_ancestors_of(self, nodeA : FsNode, nodeB : FsNode) -> bool:
if nodeB is nodeA: if nodeB is nodeA:
return False return False
if nodeA is self.root: if nodeA is self.root:
@ -125,12 +150,12 @@ class PKVirtFs:
return True return True
return False return False
def GetNodeById(self, id : str) -> VirtFsNode: def GetNodeById(self, id : str) -> FsNode:
if id == self.root.id: if id == self.root.id:
return self.root return self.root
return self.nodes[id] return self.nodes[id]
def GetFatherNode(self, node : VirtFsNode) -> VirtFsNode: def GetFatherNode(self, node : FsNode) -> FsNode:
if node is self.root: if node is self.root:
return self.root return self.root
return self.GetNodeById(node.fatherId) return self.GetNodeById(node.fatherId)
@ -144,7 +169,7 @@ class PKVirtFs:
return node return node
return None return None
async def Refresh(self, node : VirtFsNode): async def Refresh(self, node : FsNode):
if node.lastUpdate != None: if node.lastUpdate != None:
return return
if IsDir(node): if IsDir(node):
@ -160,7 +185,7 @@ class PKVirtFs:
node.childrenId.clear() node.childrenId.clear()
for childInfo in childrenInfo: for childInfo in childrenInfo:
child : VirtFsNode = None child : FsNode = None
id = childInfo["id"] id = childInfo["id"]
name = childInfo["name"] name = childInfo["name"]
fatherId = node.id fatherId = node.id
@ -178,7 +203,7 @@ class PKVirtFs:
node.lastUpdate = datetime.now() node.lastUpdate = datetime.now()
async def PathToNode(self, pathStr : str) -> VirtFsNode: async def PathToNode(self, pathStr : str) -> FsNode:
father, sonName = await self.PathToFatherNodeAndNodeName(pathStr) father, sonName = await self.PathToFatherNodeAndNodeName(pathStr)
if sonName == "": if sonName == "":
return father return father
@ -186,9 +211,9 @@ class PKVirtFs:
return None return None
return self.FindChildInDirByName(father, sonName) return self.FindChildInDirByName(father, sonName)
async def PathToFatherNodeAndNodeName(self, pathStr : str) -> tuple[VirtFsNode, str]: async def PathToFatherNodeAndNodeName(self, pathStr : str) -> tuple[FsNode, str]:
pathWalker = PathWalker(pathStr) pathWalker = PathWalker(pathStr)
father : VirtFsNode = None father : FsNode = None
sonName : str = None sonName : str = None
current = self.root if pathWalker.IsAbsolute() else self.currentLocation current = self.root if pathWalker.IsAbsolute() else self.currentLocation
@ -215,7 +240,7 @@ class PKVirtFs:
return father, sonName return father, sonName
def NodeToPath(self, node : VirtFsNode) -> str: def NodeToPath(self, node : FsNode) -> str:
if node is self.root: if node is self.root:
return "/" return "/"
spots : list[str] = [] spots : list[str] = []
@ -239,9 +264,6 @@ class PKVirtFs:
await self.client.login() await self.client.login()
self._dump_login_info() self._dump_login_info()
def log_json(self, json_obj):
logging.debug(json.dumps(json_obj, indent=4))
async def MakeDir(self, node : DirNode, name : str) -> DirNode: async def MakeDir(self, node : DirNode, name : str) -> DirNode:
result = await self.client.create_folder(name, node.id) result = await self.client.create_folder(name, node.id)
id = result["file"]["id"] id = result["file"]["id"]
@ -251,12 +273,12 @@ class PKVirtFs:
node.childrenId.append(id) node.childrenId.append(id)
return newDir return newDir
async def Download(self, url : str, dirNode : DirNode) -> None : async def Download(self, url : str, dirNode : DirNode) -> PkTask :
# 默认创建在当前目录下 task = PkTask(url, dirNode.id)
# todo: 完善离线下载task相关 self.tasks.append(task)
self.log_json(await self.client.offline_download(url, dirNode.id)) return task
async def Delete(self, nodes : list[VirtFsNode]) -> None: async def Delete(self, nodes : list[FsNode]) -> None:
nodeIds = [node.id for node in nodes] nodeIds = [node.id for node in nodes]
await self.client.delete_to_trash(nodeIds) await self.client.delete_to_trash(nodeIds)
for node in nodes: for node in nodes: