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()
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):
@wraps(func)
@ -108,19 +108,26 @@ class Console(cmd2.Cmd):
self.outputThread.join()
# 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
"""
logging.getLogger().setLevel(logging.DEBUG)
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.info("Debug mode disabled")
logging.info("Info mode enabled")
login_parser = cmd2.Cmd2ArgumentParser()
login_parser.add_argument("username", help="username", nargs="?")
@ -273,15 +280,21 @@ class Console(cmd2.Cmd):
Query All Tasks
"""
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:
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):
logging.debug(json.dumps(jsonObject, indent=4))
retry_parser = cmd2.Cmd2ArgumentParser()
retry_parser.add_argument("taskId", help="taskId", type=int)
@RunSync
async def do_test(self, args):
self.print_debug(await Client.client.offline_list())
@cmd2.with_argparser(retry_parser)
async def do_retry(self, args):
"""
Retry a task
"""
await Client.RetryTask(args.taskId)
async def mainLoop():
global MainLoop, Client

View File

@ -1,5 +1,5 @@
import httpx
from pikpakapi import PikPakApi
from pikpakapi import PikPakApi, DownloadStatus
from typing import Dict
from datetime import datetime
import json
@ -10,21 +10,25 @@ import asyncio
class PKTaskStatus(Enum):
pending = "pending"
offline_downloading = "offline_downloading"
pending_offline_download = "pending"
offline_downloading = "remote_downloading"
pending_download = "pending_for_download"
downloading = "downloading"
done = "done"
error = "error"
class PkTask:
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
self.taskId = PkTask.id
self.status = status
self.recoverStatus = status
self.name : str = ""
self.runningTask : asyncio.Task = None
self.toDirId = toDirId
self.nodeId : str = None
self.torrent = torrent
self.url = None
self.pkTaskId = None
@ -86,24 +90,70 @@ class PkToken:
return cls(**data)
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):
pkTask = await self.client.offline_download(task.torrent, task.toDirId)
task.pkTaskId = pkTask["task"]["id"]
task.nodeId = pkTask["task"]["file_id"]
task.name = pkTask["task"]["name"]
task.status = PKTaskStatus.offline_downloading
async def _task_offline_downloading(self, task : PkTask):
waitTime = 1
await asyncio.sleep(waitTime)
# status = await self.client.get_task_status(task.pkTaskId)
waitTime = 3
while True:
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):
while task.status != PKTaskStatus.done and task.status != PKTaskStatus.error:
if task.status == PKTaskStatus.pending:
await self._task_pending(task)
if task.status == PKTaskStatus.offline_downloading:
await self._task_offline_downloading(task)
break
try:
if task.status == PKTaskStatus.pending_offline_download:
await self._task_pending(task)
continue
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):
self.tasks.append(task)
@ -174,6 +224,8 @@ class PKFs:
def GetNodeById(self, id : str) -> FsNode:
if id == self.root.id:
return self.root
if id not in self.nodes:
return None
return self.nodes[id]
def GetFatherNode(self, node : FsNode) -> FsNode:
@ -191,9 +243,9 @@ class PKFs:
return None
async def Refresh(self, node : FsNode):
if node.lastUpdate != None:
return
if IsDir(node):
if node.lastUpdate != None:
return
next_page_token = None
childrenInfo = []
while True:

View File

@ -99,6 +99,60 @@ Todo:
3. offline_list
```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": [],
"next_page_token": "",