Skip to content

Commit

Permalink
feat: delete task, remote and local files (#85)
Browse files Browse the repository at this point in the history
  • Loading branch information
xyb authored Aug 10, 2023
1 parent b01ce19 commit d97223c
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 37 deletions.
3 changes: 3 additions & 0 deletions task/baidupcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ def leech(self, remote_dir, local_dir, sample_size=0):

self.download_dir(remote_dir, local_dir, sample_size=sample_size)

def delete(self, remote_dir):
self.api.remove(remote_dir)


def remotepath_exists(api, name: str, rd: str, _cache={}) -> bool:
names = _cache.get(rd)
Expand Down
12 changes: 12 additions & 0 deletions task/models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import shutil
from json import dumps
from json import loads
from os import makedirs
from os import walk
from os.path import exists
from os.path import getsize
from os.path import join
from pathlib import Path
Expand Down Expand Up @@ -361,3 +363,13 @@ def recoverable(self):

# assume task is not recoverable by default to avoid flood requests
return False

def delete_files(self):
if exists(self.sample_path):
shutil.rmtree(self.sample_path)
if exists(self.data_path):
shutil.rmtree(self.data_path)

def erase(self):
self.delete_files()
self.delete()
89 changes: 64 additions & 25 deletions task/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,30 @@ def setUp(self):
self.task = Task.objects.create(
shared_link="https://pan.baidu.com/s/123abc?pwd=def",
)
self.task.set_files(
[
{
"path": "张楚",
"is_dir": True,
"is_file": False,
"size": 0,
"md5": None,
},
{
"path": "张楚/孤独的人是可耻的.mp3",
"is_dir": False,
"is_file": True,
"size": 9518361,
"md5": "6d5bea8001e9db88f8cd8145aaf8cce4",
},
{
"path": "张楚/蚂蚁蚂蚁.mp3",
"is_dir": False,
"is_file": True,
"size": 1234567,
"md5": "1eec826501e9db88f8cd8145aaf8cce4",
},
],
)
self.remote_files = [
{
"path": "张楚",
"is_dir": True,
"is_file": False,
"size": 0,
"md5": None,
},
{
"path": "张楚/孤独的人是可耻的.mp3",
"is_dir": False,
"is_file": True,
"size": 9518361,
"md5": "6d5bea8001e9db88f8cd8145aaf8cce4",
},
{
"path": "张楚/蚂蚁蚂蚁.mp3",
"is_dir": False,
"is_file": True,
"size": 1234567,
"md5": "1eec826501e9db88f8cd8145aaf8cce4",
},
]
self.task.set_files(self.remote_files)
self.task.save()

def test_create_task(self):
Expand Down Expand Up @@ -216,7 +215,47 @@ def test_resume_not_failed_task_do_nothing(self):
assert task.message == ""

def test_files(self):
response = self.client.get(
reverse("task-files", args=[self.task.id]),
{},
format="json",
)

assert response.json() == self.remote_files
assert self.task.total_files == 2
assert self.task.total_size == 10752928
assert self.task.largest_file == "张楚/孤独的人是可耻的.mp3"
assert self.task.largest_file_size == 9518361

def test_local_files(self):
response = self.client.get(
reverse("task-local-files", args=[self.task.id]),
{},
format="json",
)

assert response.json() == []

@patch("task.views.get_baidupcs_client")
def test_delete_remote_files(self, mock_get_baidupcs_client):
mock_get_baidupcs_client.return_value = Mock()

id = self.task.id
response = self.client.delete(reverse("task-files", args=[id]))

assert response.json() == {str(id): "remote files deleted"}

def test_delete_local_files(self):
id = self.task.id
response = self.client.delete(reverse("task-local-files", args=[id]))

assert response.json() == {str(id): "local files deleted"}

@patch("task.views.get_baidupcs_client")
def test_erase(self, mock_get_baidupcs_client):
mock_get_baidupcs_client.return_value = Mock()

id = self.task.id
response = self.client.delete(reverse("task-erase", args=[id]))

assert response.json() == {str(id): "task deleted"}
67 changes: 56 additions & 11 deletions task/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging
from io import BytesIO

from baidupcs_py.baidupcs import BaiduPCSError
from django.http import HttpResponse
from django_filters import rest_framework as filters
from rest_framework import mixins
Expand All @@ -20,6 +21,23 @@
logger = logging.getLogger(__name__)


def delete_remote_files(
task_id,
remote_path,
success_message,
catch_error=True,
):
try:
client = get_baidupcs_client()
client.delete(remote_path)
except Exception as exc:
if catch_error:
return Response({"error": str(exc)}, status=status.HTTP_400_BAD_REQUEST)
else:
raise exc
return Response({task_id: success_message})


class TaskViewSet(
mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
Expand All @@ -32,22 +50,33 @@ class TaskViewSet(
filter_backends = (filters.DjangoFilterBackend,)
filterset_fields = ("shared_link", "shared_id", "status", "failed")

@action(detail=True)
@action(methods=["get", "delete"], detail=True, name="Remote Files")
def files(self, request, pk=None):
task = self.get_object()
return Response(task.load_files())
if request.method == "GET":
return Response(task.load_files())
if request.method == "DELETE":
return delete_remote_files(
task.id,
task.remote_path,
"remote files deleted",
)

@action(detail=True)
@action(methods=["get", "delete"], detail=True, name="Local Files")
def local_files(self, request, pk=None):
task = self.get_object()
return Response(task.list_local_files())
if request.method == "GET":
return Response(task.list_local_files())
if request.method == "DELETE":
task.delete_files()
return Response({task.id: "local files deleted"})

@action(detail=True)
@action(detail=True, name="Captch Image")
def captcha(self, request, pk=None):
task = self.get_object()
return HttpResponse(BytesIO(task.captcha), content_type="image/jpeg")

@action(methods=["post"], detail=True)
@action(methods=["post"], detail=True, name="Input Captcha Code")
def captcha_code(self, request, pk=None):
serializer = CaptchaCodeSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
Expand All @@ -71,7 +100,7 @@ def captcha_code(self, request, pk=None):
return Response({"error": str(exc)}, status=status.HTTP_400_BAD_REQUEST)
return Response(TaskSerializer(task).data)

@action(methods=["post"], detail=True)
@action(methods=["post"], detail=True, name="Approve to download whole files")
def full_download_now(self, request, pk=None):
serializer = FullDownloadNowSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
Expand All @@ -80,29 +109,45 @@ def full_download_now(self, request, pk=None):
task.save()
return Response(TaskSerializer(task).data)

@action(methods=["post"], detail=True)
@action(methods=["post"], detail=True, name="Restart task to downloading files")
def restart_downloading(self, request, pk=None):
task = self.get_object()
task.restart_downloading()
return Response({"status": task.status})

@action(methods=["post"], detail=True)
@action(methods=["post"], detail=True, name="Restart task from inited status")
def restart(self, request, pk=None):
task = self.get_object()
task.restart()
return Response({"status": task.status})

@action(methods=["post"], detail=True)
@action(methods=["post"], detail=True, name="Resume failed task")
def resume(self, request, pk=None):
task = self.get_object()
task.schedule_resume()
return Response({"status": task.status})

@action(methods=["delete"], detail=True, name="Erase task, remote and local files")
def erase(self, request, pk=None):
task = self.get_object()
task_id = task.id
task.erase()
message = "task deleted"
try:
return delete_remote_files(
task_id,
task.remote_path,
message,
catch_error=False,
)
except BaiduPCSError:
return Response({task_id: message})

def get_serializer(self, *args, **kwargs):
if self.action == "captcha_code":
return CaptchaCodeSerializer(*args, **kwargs)
if self.action == "full_download_now":
return FullDownloadNowSerializer(*args, **kwargs)
if self.action in ["restart", "restart_downloading", "resume"]:
if self.action in ["restart", "restart_downloading", "resume", "erase"]:
return OperationSerializer(*args, **kwargs)
return super().get_serializer(*args, **kwargs)
2 changes: 1 addition & 1 deletion ui/templates/ui/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<script src="https://unpkg.com/htmx.org"></script>
<script src="https://unpkg.com/htmx.org/dist/ext/debug.js"></script>
<script src="https://unpkg.com/htmx.org/dist/ext/response-targets.js"></script>
<link href="https://cdn.jsdelivr.net/npm/daisyui@3.3.1/dist/full.css" rel="stylesheet" type="text/css" />
<link href="https://unpkg.com/daisyui@3.5.0/dist/full.css" rel="stylesheet" type="text/css" />
<script src="https://cdn.tailwindcss.com"></script>
</head>

Expand Down

0 comments on commit d97223c

Please sign in to comment.