This commit is contained in:
limil 2024-10-31 01:27:39 +08:00
parent 2b0d9360aa
commit e970f765e9
3 changed files with 144 additions and 25 deletions

33
main.py
View File

@ -36,7 +36,7 @@ def setup_logging():
setup_logging() setup_logging()
MainLoop : asyncio.AbstractEventLoop = None MainLoop : asyncio.AbstractEventLoop = None
Client = PKFs("token.json", proxy="http://127.0.0.1:7890") Client = PKFs("token.json", proxy="http://127.0.0.1:7897")
def RunSync(func): def RunSync(func):
@wraps(func) @wraps(func)
@ -108,19 +108,26 @@ class Console(cmd2.Cmd):
self.outputThread.join() self.outputThread.join()
# commands # # commands #
def do_debug(self, args): def do_logging_off(self, args):
"""
Disable logging
"""
logging.getLogger().setLevel(logging.CRITICAL)
logging.critical("Logging disabled")
def do_logging_debug(self, args):
""" """
Enable debug mode Enable debug mode
""" """
logging.getLogger().setLevel(logging.DEBUG) logging.getLogger().setLevel(logging.DEBUG)
logging.debug("Debug mode enabled") logging.debug("Debug mode enabled")
def do_debugoff(self, args): def do_logging_info(self, args):
""" """
Disable debug mode Enable info mode
""" """
logging.getLogger().setLevel(logging.INFO) logging.getLogger().setLevel(logging.INFO)
logging.info("Debug mode disabled") logging.info("Info mode enabled")
login_parser = cmd2.Cmd2ArgumentParser() login_parser = cmd2.Cmd2ArgumentParser()
login_parser.add_argument("username", help="username", nargs="?") login_parser.add_argument("username", help="username", nargs="?")
@ -273,15 +280,21 @@ class Console(cmd2.Cmd):
Query All Tasks Query All Tasks
""" """
tasks = await Client.QueryTasks(PKTaskStatus(args.filter) if args.filter is not None else None) tasks = await Client.QueryTasks(PKTaskStatus(args.filter) if args.filter is not None else None)
# 格式化输出所有task信息idstatuslastStatus的信息输出表格
await self.AsyncPrint("id\tstatus\tlastStatus")
for task in tasks: for task in tasks:
await self.AsyncPrint(f"{task.id}: {task.status.name}") await self.AsyncPrint(f"{task.id}\t{task.status.value}\t{task.recoverStatus.value}")
def print_debug(self, jsonObject): retry_parser = cmd2.Cmd2ArgumentParser()
logging.debug(json.dumps(jsonObject, indent=4)) retry_parser.add_argument("taskId", help="taskId", type=int)
@RunSync @RunSync
async def do_test(self, args): @cmd2.with_argparser(retry_parser)
self.print_debug(await Client.client.offline_list()) async def do_retry(self, args):
"""
Retry a task
"""
await Client.RetryTask(args.taskId)
async def mainLoop(): async def mainLoop():
global MainLoop, Client global MainLoop, Client

View File

@ -1,5 +1,5 @@
import httpx import httpx
from pikpakapi import PikPakApi from pikpakapi import PikPakApi, DownloadStatus
from typing import Dict from typing import Dict
from datetime import datetime from datetime import datetime
import json import json
@ -10,21 +10,25 @@ import asyncio
class PKTaskStatus(Enum): class PKTaskStatus(Enum):
pending = "pending" pending_offline_download = "pending"
offline_downloading = "offline_downloading" offline_downloading = "remote_downloading"
pending_download = "pending_for_download"
downloading = "downloading" downloading = "downloading"
done = "done" done = "done"
error = "error" error = "error"
class PkTask: class PkTask:
id = 0 id = 0
def __init__(self, torrent : str, toDirId : str, status : PKTaskStatus = PKTaskStatus.pending): def __init__(self, torrent : str, toDirId : str, status : PKTaskStatus = PKTaskStatus.pending_offline_download):
PkTask.id += 1 PkTask.id += 1
self.taskId = PkTask.id self.taskId = PkTask.id
self.status = status self.status = status
self.recoverStatus = status
self.name : str = ""
self.runningTask : asyncio.Task = None self.runningTask : asyncio.Task = None
self.toDirId = toDirId self.toDirId = toDirId
self.nodeId : str = None
self.torrent = torrent self.torrent = torrent
self.url = None self.url = None
self.pkTaskId = None self.pkTaskId = None
@ -86,24 +90,70 @@ class PkToken:
return cls(**data) return cls(**data)
class PKFs: class PKFs:
async def RetryTask(self, taskId : int):
task = self.tasks[taskId]
if task == None or task.status != PKTaskStatus.error:
return
task.status = task.recoverStatus
self.RunTask(task)
async def _task_pending(self, task : PkTask): async def _task_pending(self, task : PkTask):
pkTask = await self.client.offline_download(task.torrent, task.toDirId) pkTask = await self.client.offline_download(task.torrent, task.toDirId)
task.pkTaskId = pkTask["task"]["id"] task.pkTaskId = pkTask["task"]["id"]
task.nodeId = pkTask["task"]["file_id"]
task.name = pkTask["task"]["name"]
task.status = PKTaskStatus.offline_downloading task.status = PKTaskStatus.offline_downloading
async def _task_offline_downloading(self, task : PkTask): async def _task_offline_downloading(self, task : PkTask):
waitTime = 1 waitTime = 3
await asyncio.sleep(waitTime) while True:
# status = await self.client.get_task_status(task.pkTaskId) await asyncio.sleep(waitTime)
status = await self.client.get_task_status(task.pkTaskId, task.nodeId)
if status == DownloadStatus.not_found or status == DownloadStatus.not_found or status == DownloadStatus.error:
task.recoverStatus = PKTaskStatus.pending_offline_download
task.status = PKTaskStatus.error
break
elif status == DownloadStatus.done:
fileInfo = await self.client.offline_file_info(file_id=task.nodeId)
if self.GetNodeById(task.nodeId) is not None:
oldFather = self.GetFatherNode(task.nodeId)
if oldFather is not None:
oldFather.childrenId.remove(task.nodeId)
task.toDirId = fileInfo["parent_id"]
task.name = fileInfo["name"]
type = fileInfo["kind"]
if type.endswith("folder"):
self.nodes[task.nodeId] = DirNode(task.nodeId, task.name, task.toDirId)
else:
self.nodes[task.nodeId] = FileNode(task.nodeId, task.name, task.toDirId)
father = self.GetNodeById(task.toDirId)
if father.id is not None:
father.childrenId.append(task.nodeId)
task.status = PKTaskStatus.pending_download
break
waitTime = waitTime * 1.5
async def _task_worker(self, task : PkTask): async def _task_worker(self, task : PkTask):
while task.status != PKTaskStatus.done and task.status != PKTaskStatus.error: while task.status != PKTaskStatus.done and task.status != PKTaskStatus.error:
if task.status == PKTaskStatus.pending: try:
await self._task_pending(task) if task.status == PKTaskStatus.pending_offline_download:
if task.status == PKTaskStatus.offline_downloading: await self._task_pending(task)
await self._task_offline_downloading(task) continue
break
if task.status == PKTaskStatus.offline_downloading:
await self._task_offline_downloading(task)
continue
if task.status == PKTaskStatus.pending_download:
task.status = PKTaskStatus.done
pass
break
except Exception as e:
logging.error(f"task failed, exception occured: {e}")
task.recoverStatus = task.status
task.status = PKTaskStatus.error
def RunTask(self, task : PkTask): def RunTask(self, task : PkTask):
self.tasks.append(task) self.tasks.append(task)
@ -174,6 +224,8 @@ class PKFs:
def GetNodeById(self, id : str) -> FsNode: def GetNodeById(self, id : str) -> FsNode:
if id == self.root.id: if id == self.root.id:
return self.root return self.root
if id not in self.nodes:
return None
return self.nodes[id] return self.nodes[id]
def GetFatherNode(self, node : FsNode) -> FsNode: def GetFatherNode(self, node : FsNode) -> FsNode:
@ -191,9 +243,9 @@ class PKFs:
return None return None
async def Refresh(self, node : FsNode): async def Refresh(self, node : FsNode):
if node.lastUpdate != None:
return
if IsDir(node): if IsDir(node):
if node.lastUpdate != None:
return
next_page_token = None next_page_token = None
childrenInfo = [] childrenInfo = []
while True: while True:

View File

@ -99,6 +99,60 @@ Todo:
3. offline_list 3. offline_list
```json ```json
{
"tasks": [
{
"kind": "drive#task",
"id": "VOASrVEVIQmaCBjEu8Y1VDb7o1",
"name": "[LoliHouse] Mahoutsukai ni Narenakatta Onnanoko no Hanashi - 04 [WebRip 1080p HEVC-10bit AAC SRTx2].mkv",
"type": "offline",
"user_id": "ZEBRT8Wc1IzU1rfZ",
"statuses": [],
"status_size": 1,
"params": {
"age": "0",
"mime_type": "video/x-matroska",
"predict_speed": "73300775185",
"predict_type": "3",
"url": "magnet:?xt=urn:btih:02816d3bd51f9e3ac72c986cc65f3f7a2b201b5b"
},
"file_id": "VOASrVFTIQmaCBjEu8Y1VDbAo1",
"file_name": "[LoliHouse] Mahoutsukai ni Narenakatta Onnanoko no Hanashi - 04 [WebRip 1080p HEVC-10bit AAC SRTx2].mkv",
"file_size": "726857457",
"message": "Saving",
"created_time": "2024-10-30T22:39:27.712+08:00",
"updated_time": "2024-10-30T22:39:27.712+08:00",
"third_task_id": "",
"phase": "PHASE_TYPE_RUNNING",
"progress": 90,
"icon_link": "https://static.mypikpak.com/39998a187e280e2ee9ceb5f58315a1bcc744fa64",
"callback": "",
"reference_resource": {
"@type": "type.googleapis.com/drive.ReferenceFile",
"kind": "drive#file",
"id": "VOASrVFTIQmaCBjEu8Y1VDbAo1",
"parent_id": "VNTQEPvYTRlbqP1pB2YGZorwo1",
"name": "[LoliHouse] Mahoutsukai ni Narenakatta Onnanoko no Hanashi - 04 [WebRip 1080p HEVC-10bit AAC SRTx2].mkv",
"size": "726857457",
"mime_type": "video/x-matroska",
"icon_link": "https://static.mypikpak.com/39998a187e280e2ee9ceb5f58315a1bcc744fa64",
"hash": "",
"phase": "PHASE_TYPE_RUNNING",
"thumbnail_link": "",
"params": {},
"space": "",
"medias": [],
"starred": false,
"tags": []
},
"space": ""
}
],
"next_page_token": "",
"expires_in": 3
}
{ {
"tasks": [], "tasks": [],
"next_page_token": "", "next_page_token": "",